Docs ← Back to dashboard
Get API key

Site Creation API

The Site Creation API queues a full website build for one business and lets you check on it until it finishes. It uses the same API keys and the same credit balance as the Lead Gen 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."


Create a site

route
POST /api/provision

A valid request queues the build, uses 1 site credit, and returns 202. You need at least 1 credit on your account.

Required fields

FieldTypeRules
businessNamestringMust not be blank.

Optional fields

FieldTypeRules and default
phonestringIf sent: at least 10 digits for a US business. For a business in Mexico, Guatemala, Peru, Colombia, Ecuador, Costa Rica or Argentina, 8 to 12 digits. For any other country, 7 to 15 digits.
addressstringFree text. A full street address such as 100 Main St, Springfield, IL 62701, or just a city or service area such as Springfield. Built from the fields below when you leave it out.
addressLine1, addressLine2stringStreet address and suite, unit or floor. Up to 200 characters each.
addressCity, addressRegion, addressPostalCodestringCity, state or region, and postal code.
countryCodestringTwo-letter country code such as US or GB. Any country.
hasPublicBusinessAddressbooleanDefault true. When false, the street lines and postal code are dropped and never appear on the site. City, region and country stay. Same as publicAddress.
googlePlaceIdstringThe business's Google Place ID. Kept with the site's business details.
lookstringclassic or bold. Default classic. An unknown value is built as classic.
themeIdstringSame as look. Send the themeId from GET /api/templates.
industrystringThe type of business, such as Plumbing.
emailstringThe business email.
businessWebsitestringMust start with http:// or https://.
aboutBusinessstringA description of the business.
servicesstring[]Services the business offers. The site shows up to 12.
serviceAreasstring[]Towns or areas the business serves. Up to 12.
businessHoursstringOpening hours as free text, or as a JSON-encoded string keyed by day, such as {"monday":{"open":"09:00","close":"17:00"},"sunday":"closed"}.
businessHoursModestringweekly, open_24_hours or do_not_display. Same as hoursMode (weekly, always_open, hidden).
businessHoursByDayobject[]Up to 7 entries. Each has day (mon to sun) and either open and close (such as "9:00 AM" or "17:00") or "closed": true.
logoUrlstringMust start with http:// or https://.
primaryColorstringSix-digit hex color such as #2F6B55. If you leave it out, a default color is used and a warning is added to the build.
secondaryColorstringSix-digit hex color.
backgroundThemestringlight or dark.
primaryLanguagestringen, es, fr, de, it, ro or tr. Default en. The site's content, page addresses, navigation and forms are written in this language. Any other value is rejected with a 400.
countrystringUp to 60 characters. Filled from countryCode when you leave it out.
customerModelstringvisit_business, travel_to_customers, hybrid or remote_online (or visit, travel, remote). Default travel_to_customers. visit_business and hybrid need a public address.
reviewsobject[]Up to 10. Each needs author, text and rating (a whole number from 1 to 5). source, date and url are optional.
skipImagesbooleanDefault false. When true, image generation is skipped and the build lists a warning.
priceToolbooleanAdds a price tool to the site. 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.
priceToolCalcIdstringOne of decks, fencing, gutters, home_construction, house_cleaning, hvac, landscaping, painting, pest_control, plumbing, windows_doors.
createServicePagesbooleanDefault true. false: no page for each service; the services are listed on the home page and the services page.
createServiceAreaPagesbooleanDefault true. Service-area pages are built for travel_to_customers and hybrid; false leaves them out.
createLocationPagesbooleanDefault true. Location pages are built for visit_business and hybrid; false leaves them out.
locationslistUp to 12, one page each: name (required), address, phone, email, hours, hoursMode, mapUrl, description, content. With none sent, the business address is the one location.

Example request

bash
curl -X POST "https://YOUR_DOMAIN/api/provision" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "businessName": "Example Plumbing",
    "industry": "Plumbing",
    "email": "owner@example.com",
    "phone": "(555) 010-0100",
    "address": "100 Main St, Springfield, IL 62701",
    "aboutBusiness": "Example Plumbing repairs and installs residential plumbing.",
    "services": ["Drain cleaning", "Water heater installation", "Leak repair"],
    "serviceAreas": ["Springfield", "Riverton", "Chatham"],
    "look": "classic",
    "primaryColor": "#2F6B55",
    "backgroundTheme": "light"
  }'

Response

Status 202:

json
{
  "slug": "example-plumbing",
  "siteId": "3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f",
  "previewUrl": null,
  "statusUrl": "/api/provision/3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f"
}

slug is made from the business name. If that slug is already taken, a number is added, such as example-plumbing-2. Keep siteId: you need it to check the build.

When builds are paused

Sometimes a valid request is not queued. You then get status 200 with "paused": true and a message. No site is queued and no credit is used. Try again later.

json
{
  "ok": true,
  "paused": true,
  "message": "Today's free builds are used up — try again tomorrow."
}

The message is either "Today's free builds are used up — try again tomorrow.", which applies to accounts that have only ever had signup credits, or "Free tests are paused right now — check back soon."


Check a build

route
GET /api/provision/{siteId}

Only the key that created the build can read it. Any other key gets the same 404 as an unknown ID.

bash
curl "https://YOUR_DOMAIN/api/provision/3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f" \
  -H "Authorization: Bearer YOUR_API_KEY"
json
{
  "status": "complete",
  "currentStep": "Complete",
  "progressPct": 100,
  "previewUrl": "https://example-plumbing.example.com/",
  "adminUrl": "https://example-plumbing.example.com/wp-admin/",
  "warnings": [],
  "error": null,
  "liveAt": "2026-10-01T15:04:10.000Z",
  "enhancingStartedAt": "2026-10-01T15:04:11.000Z",
  "completedAt": "2026-10-01T15:06:30.000Z",
  "enhancementError": null,
  "creditRefunded": false
}

Response fields

FieldMeaning
statusOne of queued, provisioning, live, enhancing, complete, failed. complete and failed are final. The preview link works from live: the main pages are published first, and the other pages and the photos are added during enhancing.
currentStepA short description of the step in progress.
progressPctProgress from 0 to 100.
previewUrlThe site's address. null until the build reports it.
adminUrlThe site's WordPress admin address.
warningsA list of strings. Each one names a value that was defaulted, ignored or skipped.
errorWhy the build failed, or null.
liveAtWhen the build first reached live.
enhancingStartedAtWhen the build first reached enhancing.
completedAtWhen the build reached complete or failed.
enhancementErrorAn error from the enhancing step, or null. The site stays live and the build still ends complete; no credit is returned.
creditRefundedtrue when a failed build's credit has been returned to your account. A failed build returns its credit once, on its own.

There is no endpoint that lists your sites. Keep the siteId of each build you create.


List templates

route
GET /api/templates

Returns the templates a new site can use, as a JSON list. No key is needed; a key that is sent must be valid. Send a template's templateId (and its themeId, when it has one) to POST /api/provision.

json
[
  { "id": "classic", "templateId": "template6", "themeId": "classic", "name": "Classic",
    "description": "Clean and modern, our standard look", "version": "2.0.0",
    "hasServices": true, "hasServiceAreas": true,
    "featureImage": "/img/look-picker/classic.jpg", "previewUrl": "/templates/ultimate?look=classic" }
]

Check a build from a workflow

route
POST /api/integrations/site-status

For workflow tools that can only send POST. Send {"siteId": "..."} with the same key. The answer is the same as GET /api/provision/{siteId}, plus ok, siteId and statusUrl. Same 401 and 404 rules.


White-label agency API

For agencies that take site requests from their own clients. Agency keys start with sf_agency_: on the API Keys page, pick Agency key before you click + Create New Key. Agency keys work only on the three routes below, and account keys do not work on them.

Templates

route
GET /api/agency/v1/templates

Returns templates (the same list as GET /api/templates) and themes (the themeId values you can send).

Create a site request

route
POST /api/agency/v1/site-requests

Takes every field of POST /api/provision, plus:

FieldTypeDescription
emailstringRequired. Your client's email. It is saved as the business email. We do not send it anything.
autoApprovebooleanWhen true, the build starts now and uses 1 site credit, with the same 403 and paused answers as POST /api/provision. Otherwise the request waits under Agency site requests on the API Keys page, and the credit is used when you click Approve.
themeIdstringSame as look.

Check a site request

route
GET /api/agency/v1/site-requests/{requestId}

Any agency key on your account can read your requests. The answer has requestId, approvalStatus (pending, approved or rejected), status (the build status, or awaiting_approval / rejected before a build exists), siteId, siteUrl, previewUrl, adminUrl, progressPct, warnings and error.


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 provision request",
  "details": ["phone: must contain at least 10 digits"]
}
StatuserrorWhen
400Invalid provision requestThe body is not valid JSON, or a field is missing or invalid. See details. No credit is used.
401Missing or invalid bearer API key.The key is missing, unknown or revoked.
403No site credits remain.Your account has no credits left.
404Site not found.Checking a build: the ID is unknown, or another key created it.
500Provisioning hit a transient storage error. No job was created and no credit was used. Please retry.Creating a site failed on our side. Send the request again.
503New site generation is temporarily in maintenance mode.Site creation is paused for maintenance.