Docs ← Back to dashboard
Get API key

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:

text
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.

RowsCredits
15
55
4040
500500

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

route
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.

FieldTypeRequiredRules and default
rowsobject[]Yes1 to 500 rows.
industrystringNoDefault Home Services.
templateKey / template_keystringNoultimate (default) or river (Waterline). template7 means river. Any other value is built as ultimate.
lookstringNoclassic (default) or bold. Applies to ultimate. A river batch is always classic.
primaryColor / primary_colorstringNoSix-digit hex color. Default #0B1F3A.
backgroundTheme / background_themestringNolight (default) or dark.
logoSizePx / logo_size_pxintegerNo48 to 160. Default 88.
contactMode / contact_modestringNoform (default) or scheduler. schedule, booking and survey also mean scheduler. Any other value is treated as form.
businessHours / business_hoursstringNoFree text, cut to 200 characters. Used for every row that does not set its own.
priceTool / price_toolbooleanNoAdds 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_idstringNoOne of decks, fencing, gutters, home_construction, house_cleaning, hvac, landscaping, painting, pest_control, plumbing, windows_doors.

Row fields

FieldTypeRequiredRules
businessName / business_namestringYesMust not be blank.
phonestringNo
emailstringNo
addressstringNoA street address or a town.
logoUrl / logo_urlstringNoA link to the logo image.
websiteUrl / website_urlstringNoThe business's current website. When logoUrl is empty, the build looks for a logo there.
serviceAreas / service_areasstringNoTowns served, separated by |, such as Springfield|Riverton.
businessHours / business_hoursstringNoReplaces the batch value for this row.
primaryColor / primary_colorstringNoSix-digit hex color. Replaces the batch value for this row.
backgroundTheme / background_themestringNolight or dark. Replaces the batch value for this row.
contactMode / contact_modestringNoSame 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

bash
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:

json
{
  "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

route
GET /api/lead-gen/batches/{batchId}

Returns the batch and its rows in items, in the order they were created.

bash
curl "https://YOUR_DOMAIN/api/lead-gen/batches/8d1e6f2a-4c3b-4a5e-9f70-2b1c0d9e8a7f" \
  -H "Authorization: Bearer YOUR_API_KEY"
json
{
  "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

ObjectValues
Batch statuspending, queued, processing, completed, failed. completed and failed are final.
Item statuspending, 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

route
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

route
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.

bash
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" }'
json
{
  "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

route
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.

json
{
  "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.

json
{
  "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."
  ]
}
StatuserrorWhen
400Invalid lead-gen batch rowsCreating a batch: the body is not valid JSON, or a field or row is invalid. See details.
400Send at least one supported setting.Changing defaults: none of the three fields was sent.
400Invalid batch settingsChanging defaults: a value is invalid. See details.
400Request body must be valid JSON.Changing defaults: the body is not valid JSON.
401Missing or invalid bearer API key.The key is missing, unknown or revoked.
403Not enough Lead Gen credits.Your balance is lower than the batch cost.
404Batch not found.The ID is unknown, or another key created the batch.