API reference
POSTSubscribe a webhook endpoint
POST /v1/webhook_endpoints: REST-hook compatible (Zapier, Make, n8n).
https://api.light-ai.app/v1/webhook_endpointsREST-hook compatible (Zapier, Make, n8n). Returns the signing secret once (secret). Subscribing the same URL and events again returns the same endpoint with a freshly rotated secret (HTTP 200); the previous secret keeps working for 24 hours. A re-subscribe also applies the static_header (e.g. a rotated n8n credential), exclude_own_origin and description it sends; fields it omits keep their stored values. The organization's owners are notified of every endpoint created through the API. Partner keys create an endpoint for one connected organization (send Light-AI-Organization); a partner-wide endpoint (every connected organization, with per-organization lanes and optional grant filters) is created by the partner owner in Settings → Developers with a second factor, never with a key, so a leaked key can never open a channel to every contractor at once. While the organization has disabled one of your endpoints to a receiver (status_reason disabled_by_organization), creating another to that receiver answers 409 stale_state.
| Scope | webhooks:manage |
|---|---|
| Credential | API key: Authorization: Bearer lai_live_… (or lai_test_…). Partner keys add Light-AI-Organization. |
| Test mode | Works with test keys (test objects only). |
| Idempotency | Idempotency-Key supported. See Idempotency. |
Headers#
org_…). Organization keys may omit it. Id prefix org_.2026-11-01.Idempotent-Replayed: true). 8–128 characters.Request body#
Response 200#
Re-subscribed: same endpoint, rotated secret, the sent static_header, exclude_own_origin and description applied.
we_.webhook_endpoint.lead.created, lead.touched, lead.updated, lead.mockup_ready, client.created, client.updated, client.deleted, project.created, project.stage_changed, quote.published, quote.viewed, quote.external_link_clicked, quote.change_requested, quote.approved, quote.declined, quote.expired, quote.link_disabled, quote.link_enabled, quote.superseded, mockup.completed, mockup.failed, organization.entitlement_changed, grant.created, grant.revoked, api_key.expiring, webhook_endpoint.disabled, ping.lead.created, lead.touched, lead.updated, lead.mockup_ready, client.created, client.updated, client.deleted, project.created, project.stage_changed, quote.published, quote.viewed, quote.external_link_clicked, quote.change_requested, quote.approved, quote.declined, quote.expired, quote.link_disabled, quote.link_enabled, quote.superseded, mockup.completed, mockup.failed, organization.entitlement_changed, grant.created, grant.revoked, api_key.expiring, webhook_endpoint.disabled, ping.enabled, disabled, disabled_by_system, disabled_by_revocation, suspended.disabled_by_organization: the contractor disabled it in Settings → Developers. Until they enable it there (it then returns to the state it had before their disable) or remove it there, the API cannot enable, re-point or delete it, nor create or point another endpoint at the same receiver (the same host, port and path; query string, case, repeated or trailing slashes and :443 ignored): each answers 409 stale_state with current_state disabled_by_organization. A partner's partner-level endpoints at that receiver receive none of that contractor's events meanwhile (its organization.entitlement_changed included; grant notices addressed to the partner still arrive). A different path or host is a different receiver. This stops deliveries, not access: a partner's key still reads through its grant (the contractor suspends or revokes the grant to stop the partner). gone / circuit_breaker: Light AI stopped it (410, or 72 hours of failures). grant_suspended, grant_revoked, key and security reasons: access was suspended or revoked.leads:read, leads:write, clients:read, clients:write, projects:read, projects:write, quotes:read, quotes:write, quotes:share_link, quotes:asset_links, webhooks:manage, events:read, mockups:read, mockups:write, forms:read, forms:write.organization, partner.… plus the last 4 characters of a value of 12 or more characters; … alone for a shorter value.api_key, user.normal, degraded.Response 201#
Endpoint created (with its secret).
we_.webhook_endpoint.lead.created, lead.touched, lead.updated, lead.mockup_ready, client.created, client.updated, client.deleted, project.created, project.stage_changed, quote.published, quote.viewed, quote.external_link_clicked, quote.change_requested, quote.approved, quote.declined, quote.expired, quote.link_disabled, quote.link_enabled, quote.superseded, mockup.completed, mockup.failed, organization.entitlement_changed, grant.created, grant.revoked, api_key.expiring, webhook_endpoint.disabled, ping.lead.created, lead.touched, lead.updated, lead.mockup_ready, client.created, client.updated, client.deleted, project.created, project.stage_changed, quote.published, quote.viewed, quote.external_link_clicked, quote.change_requested, quote.approved, quote.declined, quote.expired, quote.link_disabled, quote.link_enabled, quote.superseded, mockup.completed, mockup.failed, organization.entitlement_changed, grant.created, grant.revoked, api_key.expiring, webhook_endpoint.disabled, ping.enabled, disabled, disabled_by_system, disabled_by_revocation, suspended.disabled_by_organization: the contractor disabled it in Settings → Developers. Until they enable it there (it then returns to the state it had before their disable) or remove it there, the API cannot enable, re-point or delete it, nor create or point another endpoint at the same receiver (the same host, port and path; query string, case, repeated or trailing slashes and :443 ignored): each answers 409 stale_state with current_state disabled_by_organization. A partner's partner-level endpoints at that receiver receive none of that contractor's events meanwhile (its organization.entitlement_changed included; grant notices addressed to the partner still arrive). A different path or host is a different receiver. This stops deliveries, not access: a partner's key still reads through its grant (the contractor suspends or revokes the grant to stop the partner). gone / circuit_breaker: Light AI stopped it (410, or 72 hours of failures). grant_suspended, grant_revoked, key and security reasons: access was suspended or revoked.leads:read, leads:write, clients:read, clients:write, projects:read, projects:write, quotes:read, quotes:write, quotes:share_link, quotes:asset_links, webhooks:manage, events:read, mockups:read, mockups:write, forms:read, forms:write.organization, partner.… plus the last 4 characters of a value of 12 or more characters; … alone for a shorter value.api_key, user.normal, degraded.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 |