API reference
PATCHUpdate a lead
PATCH /v1/leads/{lead_id}: Change the status (new, archived, spam), notes or reason, or add the street address of a lead that has none yet (no address, or only a ZIP or city): it then converts to a project and lead.updated reports the address.
https://api.light-ai.app/v1/leads/{lead_id}Change the status (new, archived, spam), notes or reason, or add the street address of a lead that has none yet (no address, or only a ZIP or city): it then converts to a project and lead.updated reports the address. Archiving with reason test also archives its untouched intake project; nothing is ever deleted. Without leads:read only leads your own credential created can be changed, and the answer is a receipt. Intake-only keys: address the request by the receipt id POST /v1/leads answered with (/v1/leads/rcpt_…) to add the address later; a receipt id only takes address (and source_system) and only changes a lead your credential created. Without leads:read every receipt answer is the same 200 receipt (also when the request was folded into someone else's lead, which is never changed, or the lead already has its street address).
| Scope | leads:write |
|---|---|
| Credential | API key: Authorization: Bearer lai_live_… (or lai_test_…). Partner keys add Light-AI-Organization. |
| Test mode | Works with test keys against simulated test objects. |
| Idempotency | Idempotency-Key supported. See Idempotency. |
Path parameters#
lead_…), or the receipt id (rcpt_…) your own credential's request was answered with.Headers#
org_…). Organization keys may omit it. Id prefix org_.2026-11-01.Idempotent-Replayed: true). 8–128 characters.Request body#
archived with reason test also archives the untouched intake project; new reopens a spam or archived lead. One of: new, archived, spam.TX. At most 120 characters.Response 200#
The updated lead (or a receipt without leads:read).
lead_.lead.new, converted, spam, archived, duplicate.website_widget, api, google_ads_lead_form, google_lsa, meta_lead_ad, highlevel, hubspot, jobber, service_autopilot, realgreen, sweepandgo, deeplawn, zapier, n8n, make, crm_import, other, manual.christmas_lights, permanent_lighting, landscape_lighting, custom.cli_.prop_.cli_.prj_.intake, measuring, mockup, quote, approved, completed, archived.request, quote_drafted, quote_sent, approved, completed, closed_lost.form_.not_requested, pending, ready, failed, skipped.surfaces, primary_color, tree_count, custom_…).lighting, trees (trees & bushes), decor (wreaths & garland), details or custom (the contractor's own questions). More groups may be added.color, choice, multi_choice, toggle, text.Yes or No; text: the text).warm_white) of the request's instant preview: an array with at most one item (one AI mockup per request; leads sent before October 2026 may list up to 3, in order). Empty when there is no preview.label is "20% off", "$150 off" or empty (a headline-only offer). When the request becomes a project, the quote builder pre-fills the quote discount from it once (the contractor can change or remove it); the published quote shows it as discount with a label such as "Black Friday offer".classic, early_bird, black_friday, last_chance.percent, amount.look). GET, list and search answers carry 60-minute signed URLs; webhook payloads and the events feed carry the ids with url null (fetch the lead for fresh links).lph_… photo, mk_… preview image).lph_… photo, mk_… preview image).warm_white, cool_white, multi, candy_cane, red_green, red_white_green, red, green, blue or blue_white (more may be added). The preview uses the color the homeowner picked (one per request; older leads may have up to 3). Null when unknown.self: written by your integration (editable); others are read-only. One of: self, organization, partner.true.true.Errors#
| Status | Meaning |
|---|---|
400 | Bad request. bad_request, test_mode_mismatch, test_mode_unsupported, unsupported_api_version |
401 | Missing or invalid credential. authentication_required, invalid_api_key, api_key_revoked, api_key_expired, api_key_suspended |
403 | Not allowed. insufficient_scope, plan_upgrade_required, organization_paused, organization_off_season, api_disabled, api_access_not_enabled, ip_not_allowed, forbidden |
404 | Not found (also for objects of other organizations and for organizations without an active grant). |
409 | Conflict. stale_state, conflict, idempotency_in_progress, idempotency_scope_mismatch, quote_already_decided, quote_not_current, billing_review_required |
413 | Request bodies are limited to 256 KB. |
415 | The body is not JSON: send Content-Type: application/json. unsupported_media_type |
422 | Validation failed. idempotency_key_reused |
429 | Rate limited or daily cap reached. See Retry-After and the RateLimit headers. rate_limited, daily_cap_reached |
500 | Unexpected server error. Safe to retry with exponential backoff; quote the Request-Id to support. internal_error |
503 | Temporarily unavailable. Retry with exponential backoff. service_unavailable |