Get started with the quickstart
In the quickstart, we'll show you how to:
- Set up a sandbox app and get app credentials in the Light dashboard
- Use the API and an embedded flow (prebuilt UI) to let customers enroll in your power plan
- Verify customers are able to enroll
Prerequisites
- An account or invite to the Light dashboard
- An existing web or native mobile app to add the enrollment experience to
- If not, use our example app
1. Set up a sandbox app and get app credentials in the Light dashboard
- Log in to the Light dashboard
- On the Apps page, create a new app that uses the sandbox environment
- Select the app you just created and go to API Keys from the sidebar
- Create a new API key and store the
AppTokensomewhere for later
We now have an AppToken that can be used on all requests for authentication. An additional customer AccountToken is needed to complete actions on behalf of the customer, but that's not needed in this quickstart.
Make sure you keep your AppToken a secret and only use it on the server side of your project to hide it from users. See how we use Next.js serverside app requests to protect our AppToken in our our example app. If you want to make requests directly from your client, look into the AccountToken. Learn more
2. Create user's Light Account
Before showing the embedded enrollment flow, we need a customer's Light account. Create an account by sending a POST to /v1/app/accounts:
- Node.js
- Python
- cURL
// Create a new customer account
const response = await fetch("https://api.light.dev/v1/app/accounts", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.LIGHT_APP_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
email: "customer@example.com",
first_name: "John",
last_name: "Doe",
}),
});
const account = await response.json();
console.log("Account created:", account.uuid);
import requests
import os
response = requests.post(
'https://api.light.dev/v1/app/accounts',
headers={
'Authorization': f'Bearer {os.getenv("LIGHT_APP_TOKEN")}',
'Content-Type': 'application/json'
},
json={
'email': 'customer@example.com',
'first_name': 'John',
'last_name': 'Doe'
}
)
account = response.json()
print(f"Account created: {account['uuid']}")
# Create a new customer account
$ curl -X POST "https://api.light.dev/v1/app/accounts" \
-H "Authorization: Bearer $LIGHT_APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"email": "customer@example.com",
"first_name": "John",
"last_name": "Doe"
}'
{
"uuid": "123e4567-e89b-12d3-a456-426614174000",
"email": "customer@example.com",
"first_name": "John",
"last_name": "Doe",
"created_at": "2024-01-15T10:30:00Z"
}
See the API reference for the complete response format.
In a real situation, you should save the customer's account_uuid to your own database and avoid creating duplicate accounts on Light.
3. Launch embedded flow
Then, we need to get a URL that includes the enrollment flow's prebuilt UI. We can use the uuid in the last request's response to get a URL specific to your current customer. We place that uuid as the account_uuid in a POST to /v1/app/accounts/{account_uuid}/flow-login:
- Node.js
- Python
- cURL
// Get the embedded flow URL for enrollment
const flowResponse = await fetch(
`https://api.light.dev/v1/app/accounts/${account.uuid}/flow-login`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.LIGHT_APP_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
scope: "enrollment",
}),
},
);
const flowData = await flowResponse.json();
console.log("Flow URL:", flowData.login_link);
# Get the embedded flow URL for enrollment
flow_response = requests.post(
f'https://api.light.dev/v1/app/accounts/{account["uuid"]}/flow-login',
headers={
'Authorization': f'Bearer {os.getenv("LIGHT_APP_TOKEN")}',
'Content-Type': 'application/json'
},
json={
'scope': 'enrollment'
}
)
flow_data = flow_response.json()
print(f"Flow URL: {flow_data['login_link']}")
# Get the embedded flow URL for enrollment
$ curl -X POST "https://api.light.dev/v1/app/accounts/ACCOUNT_UUID/flow-login" \
-H "Authorization: Bearer $LIGHT_APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"scope": "enrollment"
}'
{
"login_link": "https://flow.light.dev/login?token=6277d9fb7b76832d1fc7545d4ed649d7",
"scope": "enrollment",
"expires_at": "2024-01-15T11:30:00Z"
}
See the API reference for the complete response format.
4. Surface enrollment flow at the right moment
The enrollment flow is usually displayed after a user clicks a button or navigates to another page within an iframe or webview. Display the flow in an iframe or webview:
- React
- HTML
import React from "react";
interface FlowIframeProps {
url: string;
}
const FlowIframe: React.FC<FlowIframeProps> = ({ url }) => {
return (
<div
style={{
position: "fixed",
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: 9999,
}}
>
<iframe
src={url}
style={{ width: "100%", height: "100%", border: "none" }}
title="Flow"
/>
</div>
);
};
export default FlowIframe;
<!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="Flow"></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";
}
function hideFlow() {
const container = document.getElementById("flow-container");
container.style.display = "none";
}
</script>
</body>
</html>
5. Close the enrollment flow
We need to close the embedded flow once a user completes or chooses to exit the flow early. Close the embedded flow by listening for the light-flow-close event.
Update the component from step 4 to handle the event:
- React
- HTML
import React, { useEffect } from "react";
interface FlowIframeProps {
url: string;
onClose: () => void;
}
const FlowIframe: React.FC<FlowIframeProps> = ({ url, onClose }) => {
useEffect(() => {
const handleMessage = (event: MessageEvent) => {
const eventType = event.data?.type;
if (!eventType) {
return;
}
if (eventType === "light-flow-close") {
onClose();
}
};
window.addEventListener("message", handleMessage);
return () => {
window.removeEventListener("message", handleMessage);
};
}, [onClose]);
return (
<div
style={{
position: "fixed",
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: 9999,
}}
>
<iframe
src={url}
style={{ width: "100%", height: "100%", border: "none" }}
title="Flow"
/>
</div>
);
};
export default FlowIframe;
<!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="Flow"></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>
6. Verify customers are able to enroll
Test the enrollment flow
You can test the enrollment flow using the following data:
- Email: Use your own email address or any valid email format
- Credit Card:
4242 4242 4242 4242(Stripe's test card number) - Expiry Date: Any future date (e.g.,
12/25) - CVC: Any 3-digit number (e.g.,
123) - Billing Address: Any valid address information
- Service Address: Any valid address information
The sandbox environment uses Stripe's test mode, so no real payments are processed. The credit card number 4242 4242 4242 4242 is Stripe's standard test card that will always succeed for testing purposes.
Check enrollment
Now we can check to see if the customer is enrolled in the dashboard:
- Log in to the Light dashboard
- On the Apps page, go to the app you previously created
- Go to the Accounts page and select Enrolled
You should see an enrolled customer's details.
Next steps
Congratulations on completing the Light quickstart! You've completed all of the steps necessary to enroll new customers in a power plan. To launch the experience, just repeat the first step to make a live app and use that AppToken.
There are other experiences that are important to your customer's journey. Explore our guides to learn about billing, documents, renewal, service, and usage tracking.
FAQs
What's the difference with a sandbox and live app?
Sandbox apps are safe to use in development and testing. No power plans will actually take affect. So you are free to enroll, change details, and cancel service with sandbox credentials.
What if I don't have an account on the Light dashboard?
The Light dashboard currently requires that a teammate or Light invites you to join. Reach out to us if you're interested in partnering with Light.