Skip to main content

Prebuilt UI

Light offers several ways to integrate customer experiences, from fully custom UIs built on our API to prebuilt interfaces you can launch with minimal code. All prebuilt options use the same public APIs you can call directly, so you can start with a prebuilt experience and migrate to a custom integration over time.

Choosing an integration approach

Pick the approach that matches where the customer completes the experience and how much UI you want to own. You can combine Embedded Flow, Light-Hosted Flow, and Light-Hosted Application in the same integration. All prebuilt options share a default look and feel and can be minimally configured with your logo and company name to match your brand.

ApproachWhat the customer seesRecommended when
Embedded FlowA branded, singular flow that appears as a modal within your app via iframe or webviewCustomers should stay in your product while enrolling, paying bills, or completing other flows
Light-Hosted FlowA branded, singular flow on a standalone page opened from email, SMS, or another out-of-band linkYou need a scoped interaction outside your app, such as enrollment, billing, renewals, or battery connection
Light-Hosted ApplicationA full, branded customer dashboard experience using your website domainYou want a complete account portal that includes all flows without building one
Custom API integrationYour UI, powered by Light endpointsYou need full control over layout, navigation, and business logic

Embedded Flow

Embedded Flow is a low-code option where you embed a scoped Light experience inside your website or mobile app as an iframe or webview. Customers never leave your product, but you skip building the flow UI yourself.

Recommended when:

  • You want customers to complete enrollment, billing, documents, or other flows without leaving your app
  • You need to ship a complete experience quickly inside an existing product
  • You can surface the flow at the right moment (for example, after a button click or route change)

Use POST /v1/app/accounts/{account_uuid}/flow-login with "behavior": "embedded". See the Embedded Flow tutorial below.

Both Embedded Flow and Light-Hosted Flow use the same scope values. Scope of the session should be one of:

  • "enrollment" — enrollment flow
  • "update-payment-method" — update payment method
  • "documents" — account documents
  • "billing" — invoices and billing
  • "renewal" — renewal flow for an active service location
  • "connect-battery" — battery connection flow

Light-Hosted Flow

Light-Hosted Flow is a branded, singular flow on a standalone page hosted by Light for discrete transactional interactions. Customers typically open it from a pre-authenticated link sent by email or SMS.

Recommended when:

  • The interaction happens outside your app, for example a renewal reminder email or a battery-connection campaign
  • You want a focused, single-purpose flow without using Embedded Flow in your product
  • You need to ship regulatory or lifecycle flows (like renewals) with minimal implementation

Use POST /v1/app/accounts/{account_uuid}/flow-login with "behavior": "hosted". See the renewal guide for a common use case.

const response = await fetch(
`https://api.light.dev/v1/app/accounts/${accountUuid}/flow-login`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.LIGHT_APP_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
scope: "renewal",
behavior: "hosted",
}),
},
);

const flowData = await response.json();
console.log("Light-Hosted Flow URL:", flowData.login_link);

Light-Hosted Application

Light-Hosted Application is your white-labeled customer web app—a single portal on a Light-Hosted subdomain or your own custom domain that brings together enrollment, billing, documents, service details, energy usage, and the rest of your account flows. Embedded Flow and Light-Hosted Flow each deliver one scoped experience; the hosted application is the full account app customers return to over time.

Light-Hosted Application must be set up for your organization before you can use it or generate login links. Reach out to get started. You can use the default Light-Hosted subdomain or configure a custom domain so customers see your own URL.

Recommended when:

  • You want a complete post-enrollment portal without building and maintaining your own app
  • Customers should manage their account on a standalone site (for example, linked from your marketing site or emails)
  • You are fine with Light's portal layout and navigation patterns

Use POST /v1/app/accounts/{account_uuid}/app-login with a route to control where the customer lands after login (for example "billing"). Links expire 14 days after they are generated.

const response = await fetch(
`https://api.light.dev/v1/app/accounts/${accountUuid}/app-login`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.LIGHT_APP_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
route: "billing",
}),
},
);

const appData = await response.json();
console.log("Portal URL:", appData.login_link);

Tutorial

When you launch Embedded Flow, you'll launch it for a specific Account. Use the uuid of the Account as the account_uuid in a POST to /v1/app/accounts/{account_uuid}/flow-login?scope=enrollment with "behavior": "embedded":

// Get the Embedded Flow URL for enrollment
const response = await fetch(
`https://api.light.dev/v1/app/accounts/${accountUuid}/flow-login`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.LIGHT_APP_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
scope: "enrollment",
}),
},
);

const flowData = await response.json();
console.log("Flow URL:", flowData.login_link);
Response format
{
"login_link": "https://flow.light.dev/login?token=6277d9fb7b76832d1fc7545d4ed649d7",
"scope": "enrollment",
"behavior": "embedded",
"expires_at": "2025-09-30T14:30:00.753Z"
}

The login_link returned will be a pre-authenticated flow link that can be used to launch an iframe or webview. The expires_at indicates when the pre-authenticated token included in the login_link will expire. Currently set to 1 hour from creation.

2. Surface Embedded Flow at the right moment

Embedded Flow is usually displayed inside an iframe or webview after a user clicks a button or navigates to another page.

For end users to successfully navigate Embedded Flow, no other UI elements should visually appear on top of the iframe or webview. Ensure other UI elements, such as nav bars, have a lower z-index and are not absolute-positioned on top.

<iframe
src="https://flow.light.dev/login?token=6277d9fb7b76832d1fc7545d4ed649d7"
width="100%"
height="100%"
style="position: fixed; top: 0; left: 0; z-index: 99999;"
title="Light Flow"
allow="payment"
></iframe>

3. Close the flow

You'll need to close Embedded Flow once a user chooses to exit the flow. Close Embedded Flow by listening for the light-flow-close event emitted by the flow.

<!doctype html>
<html>
<head>
<title>Light Enrollment Flow</title>
<style>
.flow-container {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
}

.flow-iframe {
width: 100%;
height: 100%;
border: none;
}
</style>
</head>
<body>
<div id="flow-container" class="flow-container" style="display: none;">
<iframe id="flow-iframe" class="flow-iframe" title="Light Flow" allow="payment"></iframe>
</div>

<script>
function showFlow(url) {
const container = document.getElementById("flow-container");
const iframe = document.getElementById("flow-iframe");

iframe.src = url;
container.style.display = "block";

// Listen for the close event
window.addEventListener("message", handleMessage);
}

function hideFlow() {
const container = document.getElementById("flow-container");
container.style.display = "none";

// Remove the event listener
window.removeEventListener("message", handleMessage);
}

function handleMessage(event) {
const eventType = event.data?.type;
if (!eventType) {
return;
}
if (eventType === "light-flow-close") {
hideFlow();
}
}
</script>
</body>
</html>

Custom API integration

Build every screen yourself using Light's App API and Account API. You control the full user experience, including enrollment steps, billing dashboards, document viewers, and renewal flows, while Light handles electricity service, billing, and compliance behind the scenes.

Recommended when:

  • You already have a customer dashboard or mobile app and want Light to feel native to your product
  • You need custom business logic, branching, or design that Embedded Flow, Light-Hosted Application, and Light-Hosted Flow cannot support
  • You are optimizing a mature funnel and want full ownership of analytics and UX

Tradeoff: Custom API integration requires the most frontend and integration work. See the enrollment, billing, and renewal guides for API walkthroughs.