API Reference
Access your Lighthouse data from your own app. Pull email lists, add signups, manage subscribers -- all from your own backend.
Quick start in 3 steps
- Generate an API key from your dashboard (requires Pro plan)
- Copy the key -- it is shown only once
- Make your first request:
curl "https://lighthouse.build/api/v1/waitlists/YOUR_WAITLIST_ID/signups" \ -H "Authorization: Bearer lh_your_api_key"
Get Your API Key
Go to API Keys page
Navigate to Dashboard → API Keys or click the "API Keys" button in your dashboard header.
Generate a key
Enter a label (e.g. "Production" or "Dev") and click Generate. Your full key starts with lh_ and is shown only once.
Copy and store it securely
Save it in your environment variables. Never commit it to version control or share it publicly.
Authentication
Include your API key in the Authorization header of every request:
Authorization: Bearer lh_your_api_key
Keys are hashed with SHA-256 before storage. We never store your raw key. If you lose it, delete it and generate a new one.
Base URL
https://lighthouse.build/api/v1Tier Access
| Feature | Pro ($29) |
|---|---|
| API key management | Yes |
| Add signups / subscribers | Yes |
| View counts | Yes |
| View individual emails | Yes |
| Project email list | Yes |
| Fetch survey questions | Yes |
| Submit survey responses | Yes |
| View survey response data | Yes |
Error Codes
All errors return JSON with an error field:
{ "error": "Invalid API key" }| Status | Meaning |
|---|---|
400 | Bad request (invalid input or missing fields) |
401 | Missing or invalid API key |
403 | Your plan does not include this feature |
404 | Resource not found or not owned by you |
409 | Duplicate (email already exists in this list) |
500 | Server error |
Pagination
All list endpoints support pagination via query parameters:
| Param | Default | Max | Description |
|---|---|---|---|
limit | 1000 | 5000 | Number of results per page |
offset | 0 | -- | Number of results to skip |
Responses include total, limit, offset, and has_more to help you paginate.
// Page 1
GET /api/v1/projects/{id}/emails?limit=100&offset=0
// Page 2
GET /api/v1/projects/{id}/emails?limit=100&offset=100Waitlists
/waitlists/{id}/signupsProList signups for a waitlist with their emails, notes, and survey answers.
Example
curl "https://lighthouse.build/api/v1/waitlists/WAITLIST_ID/signups" \ -H "Authorization: Bearer lh_your_api_key"
Response
{
"waitlist_id": "abc-123",
"name": "Beta Launch",
"data": [
{ "email": "alice@example.com", "note": "Building a dev tool", "created_at": "2026-05-18T12:00:00Z" }
],
"total": 87,
"limit": 1000,
"offset": 0,
"has_more": false
}/waitlists/{id}/signupsPro+Add a signup to a waitlist from your own SaaS or app.
Request body
{
"email": "bob@example.com",
"note": "Optional free-text (max 5000 chars)",
"survey_answers": {
"<question_id>": "answer",
"<question_id>": ["multiple", "choices"]
}
}| Field | Required | Description |
|---|---|---|
email | Yes | The signup email. May also be passed as a query param (?email=). |
note | No | Optional free text, max 5000 chars. May also be passed as a query param (?note=). |
survey_answers | No | Object keyed by survey question id, one value per question (see the value formats below). Must be sent in the JSON body. |
Where to find a question id
- Survey builder: every question shows an
API idwith a copy button (open the waitlist and edit its survey). - Response breakdown: click the "Copy question id for API" button next to a question.
Answer value by question type
| Question type | Value | Example |
|---|---|---|
| Short text | string | "Building a CRM" |
| Single choice | string (the chosen option) | "Founder" |
| Multiple choice | array of strings | ["Analytics", "API"] |
| Rating (1-5) | the number as a string | "4" |
Example: simple signup
curl -X POST "https://lighthouse.build/api/v1/waitlists/WAITLIST_ID/signups" \ -H "Authorization: Bearer lh_your_api_key" \ -H "Content-Type: application/json" \ -d '{"email": "bob@example.com", "note": "Building a dev tool"}'
Example: signup with survey answers
curl -X POST "https://lighthouse.build/api/v1/waitlists/WAITLIST_ID/signups" \ -H "Authorization: Bearer lh_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "email": "bob@example.com", "survey_answers": { "q_role": "Founder", "q_features": ["Analytics", "API"], "q_rating": "4" } }'
Response (201)
{
"id": "f1e2d3c4-...",
"email": "bob@example.com",
"note": "Building a dev tool",
"survey_answers": { "q_role": "Founder" },
"created_at": "2026-05-28T12:00:00Z",
"waitlist_id": "abc-123"
}Newsletters
/newsletters/{id}/subscribersProList active subscribers for a newsletter with their emails and source.
Example
curl "https://lighthouse.build/api/v1/newsletters/NEWSLETTER_ID/subscribers" \ -H "Authorization: Bearer lh_your_api_key"
Response
{
"newsletter_id": "def-456",
"name": "Weekly Updates",
"data": [
{ "email": "carol@example.com", "subscribed_at": "2026-05-18T12:00:00Z", "source": "manual" }
],
"total": 53,
"limit": 1000,
"offset": 0,
"has_more": false
}/newsletters/{id}/subscribersPro+Add a subscriber to a newsletter from your own SaaS or app.
Request body
{ "email": "dave@example.com" }Example
curl -X POST "https://lighthouse.build/api/v1/newsletters/NEWSLETTER_ID/subscribers" \ -H "Authorization: Bearer lh_your_api_key" \ -H "Content-Type: application/json" \ -d '{"email": "dave@example.com"}'
Response (201)
{ "email": "dave@example.com", "newsletter_id": "def-456" }Surveys
Use the survey API to power in-app onboarding flows, gather user preferences, or run research. Fetch the questions, render your own UI, and collect answers step by step.
/surveys/{id}Pro+Fetch a survey and its questions. Use this to render the survey in your own app.
Example
curl "https://lighthouse.build/api/v1/surveys/SURVEY_ID" \ -H "Authorization: Bearer lh_your_api_key"
Response
{
"survey_id": "abc-123",
"name": "Onboarding",
"collect_email": true,
"questions": [
{
"id": "q1",
"type": "text",
"label": "What's your role?",
"required": true
},
{
"id": "q2",
"type": "select",
"label": "Company size?",
"options": ["1-10", "11-50", "50+"],
"required": true
},
{
"id": "q3",
"type": "multi_select",
"label": "What are your goals?",
"options": ["Growth", "Analytics", "Automation"],
"required": false
},
{
"id": "q4",
"type": "rating",
"label": "Experience level?",
"required": true
}
]
}Question types
| Type | Answer format | Example |
|---|---|---|
text | String | "Product Manager" |
select | String (one of options) | "11-50" |
multi_select | Array of strings | ["Growth", "Analytics"] |
rating | Number (1-5) | 4 |
/surveys/{id}/responsesPro+Submit a survey response. Answers are keyed by question ID. Supports gradual submission.
Request body
{
"answers": {
"<question_id>": "answer", // text or single choice
"<question_id>": ["multiple", "choices"], // multiple choice
"<question_id>": 4 // rating (1-5)
},
"email": "user@example.com"
}| Field | Required | Description |
|---|---|---|
answers | Yes | Object keyed by question id, one value per question. Match the value to the type (see Question types above): text/select use a string, multi_select an array of strings, rating a number 1-5. |
email | Conditional | Required only if the survey has collect_email enabled. When provided, repeat calls merge into the same response (gradual submission). |
Where to find a question id
- Call
GET /surveys/{id}to get the questions with their ids. - Survey builder: every question shows an
API idwith a copy button. - Response breakdown: click the "Copy question id for API" button next to a question.
email is provided and a response already exists for that email, the new answers are merged into the existing response. This lets you collect data step-by-step (e.g. onboarding flows).Example: step-by-step onboarding
# Step 1: user signs up, you collect role curl -X POST "https://lighthouse.build/api/v1/surveys/SURVEY_ID/responses" \ -H "Authorization: Bearer lh_your_api_key" \ -H "Content-Type: application/json" \ -d '{"email": "user@example.com", "answers": {"q1": "Product Manager"}}' # Step 2: next screen, collect company size curl -X POST "https://lighthouse.build/api/v1/surveys/SURVEY_ID/responses" \ -H "Authorization: Bearer lh_your_api_key" \ -H "Content-Type: application/json" \ -d '{"email": "user@example.com", "answers": {"q2": "11-50"}}' # Step 3: collect goals curl -X POST "https://lighthouse.build/api/v1/surveys/SURVEY_ID/responses" \ -H "Authorization: Bearer lh_your_api_key" \ -H "Content-Type: application/json" \ -d '{"email": "user@example.com", "answers": {"q3": ["Growth", "Analytics"]}}'
All three calls merge into a single response. The final stored answers: {"q1": "Product Manager", "q2": "11-50", "q3": ["Growth", "Analytics"]}
Response (201 -- new response)
{
"response_id": "resp-789",
"survey_id": "abc-123"
}Response (200 -- answers added to existing response)
{
"response_id": "resp-789",
"survey_id": "abc-123",
"updated": true
}Validation
- Required questions are only enforced when submitting all at once (not on partial updates)
selectvalues must match one of the defined optionsmulti_selectvalues must all be valid optionsratingmust be a number between 1 and 5
/surveys/{id}/responsesPro+List responses for a survey with full answer data.
Example
curl "https://lighthouse.build/api/v1/surveys/SURVEY_ID/responses?limit=100" \ -H "Authorization: Bearer lh_your_api_key"
Response
{
"survey_id": "abc-123",
"name": "Onboarding",
"data": [
{
"id": "resp-789",
"answers": {
"q1": "Product Manager",
"q2": "11-50",
"q3": ["Growth", "Analytics"],
"q4": 4
},
"email": "user@example.com",
"created_at": "2026-05-18T12:00:00Z"
}
],
"total": 42,
"limit": 100,
"offset": 0,
"has_more": false
}Feedback
Collect open-ended feedback from users. Embed in your app via API or share the public page. Supports ratings, categories, status tracking, replies, and closing-the-loop emails.
/feedback/{id}Pro+Get a collector's settings (rating mode, categories, email mode). Use this to build your own feedback UI.
Example
curl "https://lighthouse.build/api/v1/feedback/COLLECTOR_ID" \ -H "Authorization: Bearer lh_your_api_key"
Response
{
"collector_id": "abc-123",
"name": "App Feedback",
"rating_mode": "stars",
"categories": ["Bug", "Feature", "Praise", "Other"],
"email_mode": "optional"
}Rating modes
| Mode | Values | Description |
|---|---|---|
none | -- | No rating, text only |
thumbs | 0 or 1 | Thumbs down / thumbs up |
stars | 1 to 5 | Star rating |
Categories
Categories are set per collector in the dashboard. When submitting feedback, the category value must match one of the collector's categories exactly. If the collector has no categories configured, omit the field.
Email modes
| Mode | Description |
|---|---|
none | Email field is hidden |
optional | User can optionally provide an email |
required | Email must be provided with each submission |
/feedback/{id}/submissionsPro+Submit feedback from your own SaaS or app.
Request body (stars rating)
{
"text": "The onboarding is confusing",
"rating": 3,
"category": "Feature",
"email": "user@example.com",
"context": { "page": "/settings", "device": "iOS" }
}Request body (thumbs rating)
{
"text": "Love the new dashboard!",
"rating": 1,
"category": "Praise",
"email": "user@example.com"
}The rating value depends on the collector's rating mode. The backend validates it automatically:
- Stars -- send
1to5(integer) - Thumbs -- send
1(up) or0(down) - None -- omit the field, rating is not accepted
Only text is required. All other fields are optional (unless email_mode is required). Use context to attach extra info like the page or device.
Example
curl -X POST "https://lighthouse.build/api/v1/feedback/COLLECTOR_ID/submissions" \ -H "Authorization: Bearer lh_your_api_key" \ -H "Content-Type: application/json" \ -d '{"text": "Love the new dashboard!", "rating": 5, "category": "Praise", "email": "user@example.com"}'
Response (201)
{ "id": "sub-789", "created_at": "2026-05-19T12:00:00Z" }/feedback/{id}/submissionsPro+Get the actual feedback users have submitted. Filter by status, category, or email.
Query parameters
| Param | Description |
|---|---|
status | Filter: new, read, triaged, shipped |
category | Filter by category (e.g. Bug) |
has_email | Set to true to only show submissions with email |
limit | Max results (default 100, max 1000) |
offset | Pagination offset |
Example
curl "https://lighthouse.build/api/v1/feedback/COLLECTOR_ID/submissions?status=new&limit=50" \ -H "Authorization: Bearer lh_your_api_key"
Response
{
"data": [
{
"id": "sub-789",
"text": "The onboarding is confusing",
"rating": 3,
"category": "Feature",
"email": "user@example.com",
"status": "new",
"context": { "page": "/settings", "device": "iOS" },
"created_at": "2026-05-19T12:00:00Z"
}
],
"total": 24,
"limit": 50,
"offset": 0,
"has_more": false
}The id of each submission (e.g. sub-789) is the subId you pass to the status and reply endpoints below.
/feedback/{id}/submissions/{subId}Pro+Update a submission's status.
SUB_ID (the {subId} path segment) is a submission id from GET /feedback/{id}/submissions.
Request body
{
"status": "shipped",
"shipped_message": "We just redesigned the onboarding!"
}Statuses
| Status | Description |
|---|---|
new | Default status when submitted |
read | You've seen it |
triaged | Acknowledged and prioritized |
shipped | Done -- sends email to submitter (see below) |
shipped and the submitter provided their email, Lighthouse automatically sends them a "we built it" email with your shipped_message. The response includes email_sent so you know if the email went out.Example
curl -X PATCH "https://lighthouse.build/api/v1/feedback/COLLECTOR_ID/submissions/SUB_ID" \ -H "Authorization: Bearer lh_your_api_key" \ -H "Content-Type: application/json" \ -d '{"status": "shipped", "shipped_message": "Fixed in v2.1!"}'
Response
{ "id": "sub-789", "status": "shipped", "email_sent": true }/feedback/{id}/submissions/{subId}/replyPro+Send an email reply directly to a feedback submitter.
SUB_ID is a submission id from GET /feedback/{id}/submissions.
Request body
{ "body": "Thanks for the feedback! We're working on it." }The submitter must have provided their email. Returns 400 if the submission has no email address.
Example
curl -X POST "https://lighthouse.build/api/v1/feedback/COLLECTOR_ID/submissions/SUB_ID/reply" \ -H "Authorization: Bearer lh_your_api_key" \ -H "Content-Type: application/json" \ -d '{"body": "Thanks! This is on our roadmap for next week."}'
Response (201)
{ "reply_id": "rep-456", "sent_at": "2026-05-19T12:30:00Z" }Email List
/projects/{projectId}/emailsProGet all unique emails across every waitlist and newsletter in a project, deduplicated.
Query parameters
| source | Filter: waitlist or newsletter |
| limit | Max results (default 1000, max 5000) |
| offset | Pagination offset (default 0) |
Example
curl "https://lighthouse.build/api/v1/projects/PROJECT_ID/emails?source=waitlist&limit=50" \ -H "Authorization: Bearer lh_your_api_key"
Response
{
"data": [
{
"email": "alice@example.com",
"source": "waitlist",
"source_name": "Beta Launch",
"source_id": "abc-123",
"created_at": "2026-05-18T12:00:00Z"
}
],
"total": 142,
"limit": 50,
"offset": 0,
"has_more": true
}Rate Limits
The API allows up to 60 requests per minute per API key. If you exceed this, you'll receive a 429 Too Many Requests response.
| Header | Description |
|---|---|
X-RateLimit-Limit | Max requests per minute (60) |
X-RateLimit-Remaining | Requests left in the current window |
Retry-After | Seconds to wait before retrying (only on 429) |
// 429 response
{
"error": "Rate limit exceeded. Try again in 42 seconds."
}Need help? Contact support
Manage API Keys