API reference
POSTMove a project to another pipeline stage
POST /v1/projects/{project_id}/stage: Exactly the manual move a team member can make in the pipeline: a display stage, never an approval (use mark_approved for that).
POST
https://api.light-ai.app/v1/projects/{project_id}/stageExactly the manual move a team member can make in the pipeline: a display stage, never an approval (use mark_approved for that). expected_stage protects against overwriting a newer change (409 stale_state).
| Scope | projects: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#
The project id (
prj_…). Id prefix prj_.Headers#
Partner keys: the connected organization to act for (
org_…). Organization keys may omit it. Id prefix org_.Pin a dated API version (defaults to the key's version). One of:
2026-11-01.Retry-safe writes: the same key and body replay the first response for 24 hours (
Idempotent-Replayed: true). 8–128 characters.Request body#
The stage you believe the project is in (409 stale_state otherwise). One of:
request, quote_drafted, quote_sent, approved, completed, closed_lost.A display stage.
approved is reserved for an actual approval (mark_approved). One of: request, quote_drafted, quote_sent, completed, closed_lost.null or "": none. At most 200 characters.
The system that caused this write (shown as origin.source_system on the resulting events, for loop prevention).
Response 200#
The project after the move.
Id prefix
prj_.Always
project.false for objects created with a test key.
One of:
intake, measuring, mockup, quote, approved, completed, archived.The pipeline column; null for an archived project. One of:
request, quote_drafted, quote_sent, approved, completed, closed_lost.Id prefix
cli_.Id prefix
prop_.Id prefix
lead_.One of:
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.self: written by your integration (editable); others are read-only. One of: self, organization, partner.Id prefix
qt_.The offer of the website request this project came from, as the request kept it (the same object as lead.offer); null otherwise. The quote builder pre-fills the quote discount from it once; the published quote shows it as
discount.label.The Light AI campaign template that filled the offer; null or absent for the contractor's own. One of:
classic, early_bird, black_friday, last_chance.One of:
percent, amount.self: written by your integration (editable); others are read-only. One of: self, organization, partner.RFC 3339 timestamp (UTC, milliseconds).
Last change of the project or of what the API derives for it (pipeline_stage, current_quote_id): updated_since sees a decline or a republish.
Always
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 |