Lead Gen API
The Lead Gen API takes a list of businesses and builds a preview site for each one. You send the list as one batch, then read the batch back to get each row's link. It uses the same API keys and the same credit balance as the Site Creation API.
Base URL
Send requests to the same domain you use for your dashboard. Every path on this page is relative to it.
Authentication
Send your API key as a bearer token on every request:
Authorization: Bearer YOUR_API_KEY
Keys start with lgen_. To create one, open API Keys in your dashboard, type a name in the Key label box (up to 64 characters), and click + Create New Key. The full key is shown once, in the Your new API key window. Copy it before you click Done. If you lose it, revoke it and create a new one.
A missing, unknown or revoked key gets 401 with "Missing or invalid bearer API key."
Batches belong to the key that created them. Reading, listing and updating batches only shows batches made with the key you send.
Credits
A batch costs 1 credit per row, with a minimum of 5. The cost is taken when the batch is created.
| Rows | Credits |
|---|---|
| 1 | 5 |
| 5 | 5 |
| 40 | 40 |
| 500 | 500 |
If your balance is lower than the cost, the request fails with 403 and nothing is created. A request that fails validation uses no credits. If every row in a batch fails and none completes, the full cost is returned to your account.
Create a batch
POST /api/lead-gen/batches
Most fields accept a camelCase name or a snake_case name, such as primaryColor or primary_color.
Batch fields
These apply to every row in the batch.
| Field | Type | Required | Rules and default |
|---|---|---|---|
rows | object[] | Yes | 1 to 500 rows. |
industry | string | No | Default Home Services. |
templateKey / template_key | string | No | ultimate (default) or river (Waterline). template7 means river. Any other value is built as ultimate. |
look | string | No | classic (default) or bold. Applies to ultimate. A river batch is always classic. |
primaryColor / primary_color | string | No | Six-digit hex color. Default #0B1F3A. |
backgroundTheme / background_theme | string | No | light (default) or dark. |
logoSizePx / logo_size_px | integer | No | 48 to 160. Default 88. |
contactMode / contact_mode | string | No | form (default) or scheduler. schedule, booking and survey also mean scheduler. Any other value is treated as form. |
businessHours / business_hours | string | No | Free text, cut to 200 characters. Used for every row that does not set its own. |
priceTool / price_tool | boolean | No | Adds a price tool to the sites. On by default when priceToolCalcId is set or the industry matches a trade that has a price tool. Send false to leave it off. See Price tools. |
priceToolCalcId / price_tool_calc_id | string | No | One of decks, fencing, gutters, home_construction, house_cleaning, hvac, landscaping, painting, pest_control, plumbing, windows_doors. |
Row fields
| Field | Type | Required | Rules |
|---|---|---|---|
businessName / business_name | string | Yes | Must not be blank. |
phone | string | No | |
email | string | No | |
address | string | No | A street address or a town. |
logoUrl / logo_url | string | No | A link to the logo image. |
websiteUrl / website_url | string | No | The business's current website. When logoUrl is empty, the build looks for a logo there. |
serviceAreas / service_areas | string | No | Towns served, separated by |, such as Springfield|Riverton. |
businessHours / business_hours | string | No | Replaces the batch value for this row. |
primaryColor / primary_color | string | No | Six-digit hex color. Replaces the batch value for this row. |
backgroundTheme / background_theme | string | No | light or dark. Replaces the batch value for this row. |
contactMode / contact_mode | string | No | Same values as the batch field. Replaces the batch value for this row. |
A row must not contain industry, a template field (templateKey, template_key, templateName, template_name) or a price tool field (priceTool, price_tool, priceToolCalcId, price_tool_calc_id). These are set once per batch. A row that has one is rejected with 400.
Example request
curl -X POST "https://YOUR_DOMAIN/api/lead-gen/batches" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"industry": "Plumbing",
"templateKey": "ultimate",
"look": "classic",
"primaryColor": "#0B1F3A",
"backgroundTheme": "light",
"rows": [
{
"businessName": "Example Plumbing",
"phone": "(555) 010-0100",
"address": "100 Main St, Springfield, IL 62701",
"websiteUrl": "https://example.com"
},
{
"businessName": "Sample Drain Co",
"email": "[email protected]",
"address": "Riverton",
"serviceAreas": "Riverton|Chatham"
}
]
}'
Response
Status 200:
{
"ok": true,
"batchId": "8d1e6f2a-4c3b-4a5e-9f70-2b1c0d9e8a7f",
"batch": {
"id": "8d1e6f2a-4c3b-4a5e-9f70-2b1c0d9e8a7f",
"status": "pending",
"industry": "Plumbing",
"template_key": "ultimate",
"look": "classic",
"primary_color": "#0B1F3A",
"background_theme": "light",
"logo_size_px": 88,
"contact_mode": "form",
"total_count": 2,
"credits_reserved": 5,
"price_tool": 1,
"error": null,
"created_at": "2026-10-01T15:00:00.000Z",
"updated_at": "2026-10-01T15:00:00.000Z"
},
"creditsReserved": 5,
"creditsRemaining": 95
}
The batch object also carries a few internal fields not shown here. The batch is queued for building as soon as it is created. You do not need to start it.
Get a batch
GET /api/lead-gen/batches/{batchId}
Returns the batch and its rows in items, in the order they were created.
curl "https://YOUR_DOMAIN/api/lead-gen/batches/8d1e6f2a-4c3b-4a5e-9f70-2b1c0d9e8a7f" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"ok": true,
"batch": {
"id": "8d1e6f2a-4c3b-4a5e-9f70-2b1c0d9e8a7f",
"status": "completed",
"industry": "Plumbing",
"total_count": 2,
"credits_reserved": 5
},
"items": [
{
"id": "c2b7e4d1-9a0f-4e3c-8b5d-6f1a2e3d4c5b",
"status": "completed",
"business_name": "Example Plumbing",
"slug": "example-plumbing",
"site_url": "https://example-plumbing.example.com/",
"public_url": null,
"error": null
}
]
}
Both objects above are shortened. Each item also returns the row values you sent.
Statuses
| Object | Values |
|---|---|
Batch status | pending, queued, processing, completed, failed. completed and failed are final. |
Item status | pending, completed, failed. A failed item has the reason in error. |
A completed item has its link in site_url or, if that is empty, public_url.
List batches
GET /api/lead-gen/batches
Returns { "ok": true, "batches": [...] } with up to 50 of your most recent batches, newest first. Rows are not included. Use Get a batch for those.
Change batch design defaults
PATCH /api/lead-gen/batches/{batchId}
Send one or more of primaryColor / primary_color, backgroundTheme / background_theme and logoSizePx / logo_size_px. The same rules as on create apply.
A new color or background only reaches rows that did not set their own. The logo size reaches every row.
curl -X PATCH "https://YOUR_DOMAIN/api/lead-gen/batches/8d1e6f2a-4c3b-4a5e-9f70-2b1c0d9e8a7f" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "primaryColor": "#173B57", "backgroundTheme": "dark" }'
{
"ok": true,
"batchId": "8d1e6f2a-4c3b-4a5e-9f70-2b1c0d9e8a7f",
"primaryColor": "#173B57",
"backgroundTheme": "dark",
"logoSizePx": 88,
"updatedCount": 2,
"logoUpdatedCount": 0,
"logoSkippedCount": 0,
"colorUpdatedCount": 2,
"colorSkippedCount": 0,
"backgroundUpdatedCount": 2,
"backgroundSkippedCount": 0
}
The ...UpdatedCount values count rows that take the new value. The ...SkippedCount values count rows that keep their own. updatedCount is the number of rows that changed in any way.
Check a batch is queued
POST /api/lead-gen/batches/{batchId}/process
You do not need to call this. A batch is queued when it is created. This route reports the batch's state and never starts a build a second time. A pending batch is marked queued; any other status is returned unchanged.
{
"ok": true,
"batchId": "8d1e6f2a-4c3b-4a5e-9f70-2b1c0d9e8a7f",
"queued": true,
"status": "queued",
"message": "The dedicated Lead Gen worker owns batch processing."
}
Errors
Error responses have "ok": false and an error string. Validation errors also have a details list with one line per problem.
{
"ok": false,
"error": "Invalid lead-gen batch rows",
"details": [
"Row 2 must include business_name.",
"Row 3 must not set industry; industry is batch-level only."
]
}
| Status | error | When |
|---|---|---|
| 400 | Invalid lead-gen batch rows | Creating a batch: the body is not valid JSON, or a field or row is invalid. See details. |
| 400 | Send at least one supported setting. | Changing defaults: none of the three fields was sent. |
| 400 | Invalid batch settings | Changing defaults: a value is invalid. See details. |
| 400 | Request body must be valid JSON. | Changing defaults: the body is not valid JSON. |
| 401 | Missing or invalid bearer API key. | The key is missing, unknown or revoked. |
| 403 | Not enough Lead Gen credits. | Your balance is lower than the batch cost. |
| 404 | Batch not found. | The ID is unknown, or another key created the batch. |