Light AIDocs Beta Open Light AI

API reference

GETList published quotes

GET /v1/quotes: Drafts are never exposed.

GEThttps://api.light-ai.app/v1/quotes

Drafts are never exposed. With status or is_current a page may be short (or empty) while has_more is true: keep following next_cursor. With quotes:asset_links, assets.*.url are durable image links (as on GET /v1/quotes/{id}).

Scopequotes:read
CredentialAPI key: Authorization: Bearer lai_live_… (or lai_test_…). Partner keys add Light-AI-Organization.
Test modeWorks with test keys against simulated test objects.

Query parameters#

limitinteger#
Page size, 1–100 (default 25). 1–100.
cursorstring#
next_cursor from the previous page. At most 400 characters.
sortstring#
updated_asc pages objects in last-change order (for an initial or incremental sync with updated_since). A write that commits late can carry an earlier updated_at, so re-poll from your high-water mark minus 5 minutes and de-duplicate by id + updated_at; GET /v1/events?sort=sync_asc is the gapless change feed. One of: created_desc, updated_asc.
project_idstring#
Id prefix prj_.
statusstring#
One of: sent, approved, declined, expired, superseded, disabled.
is_currentstring#
One of: true, false.
created_aftertimestamp#
Only quotes created after this time.
created_beforetimestamp#
Only quotes created before this time.
updated_sincetimestamp#
Only objects updated after this time (alias: updated_after). Overlap polls by a few minutes: see sort.
updated_aftertimestamp#
Alias of updated_since.
external_refstring#
<system>:<id> in your own namespace, e.g. jobber:Z2lk123. At most 400 characters.
external_ref_namespacestring#
At most 120 characters.

Headers#

Light-AI-Organizationstring#
Partner keys: the connected organization to act for (org_…). Organization keys may omit it. Id prefix org_.
Light-AI-Versionstring#
Pin a dated API version (defaults to the key's version). One of: 2026-11-01.

Response 200#

A page of quotes.

objectstringrequired#
Always list.
dataobject[]required#
data[].idstringrequired#
Id prefix qt_.
data[].objectstringrequired#
Always quote.
data[].livemodebooleanrequired#
false for objects created with a test key.
data[].statusstringrequired#
One of: sent, approved, declined, expired, superseded, disabled.
data[].is_currentbooleanrequired#
data[].superseded_bystring | nullrequired#
Id prefix qt_.
data[].replaces_quote_idstring | nullrequired#
Id prefix qt_.
data[].external_refsobject[]required#
The ids integrations wrote back on this quote (PUT /v1/quotes/{id}/external_refs/{system}).
data[].external_refs[].systemstringrequired#
data[].external_refs[].namespacestring | nullrequired#
data[].external_refs[].idstringrequired#
data[].external_refs[].ownerstringrequired#
self: written by your integration (editable); others are read-only. One of: self, organization, partner.
data[].external_refs[].read_onlybooleanrequired#
data[].truncatedboolean#
Webhook payloads only: present (true) when the quote was too large for one delivery (256 KB). line_items is then empty; read the full quote with GET /v1/quotes/{id}. Never present on API responses. Always true.
data[].projectobjectrequired#
data[].project.idstringrequired#
Id prefix prj_.
data[].project.pipeline_stagestring | nullrequired#
One of: request, quote_drafted, quote_sent, approved, completed, closed_lost.
data[].project.external_refsobject[]required#
data[].leadobject | nullrequired#
data[].lead.idstringrequired#
Id prefix lead_.
data[].lead.sourcestring | nullrequired#
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.
data[].lead.external_refsobject[]required#
data[].clientobject | nullrequired#
Contact details need clients:read; otherwise only the id.
data[].client.idstringrequired#
Id prefix cli_.
data[].client.first_namestring | null#
data[].client.last_namestring | null#
data[].client.emailstring | null#
data[].client.phonestring | null#
E.164, or null when the stored number could not be normalized (see phone_raw).
data[].client.phone_rawstring | null#
The number as stored in Light AI.
data[].client.external_refsobject[]#
data[].propertyobject | null#
data[].property.idstringrequired#
Id prefix prop_.
data[].property.addressobject | null#
data[].assigned_repobject | null#
data[].assigned_rep.idstringrequired#
data[].assigned_rep.namestring | nullrequired#
data[].assigned_rep.emailstring | nullrequired#
data[].titlestring | nullrequired#
data[].messagestring | nullrequired#
data[].termsstring | nullrequired#
data[].disclaimerstring | null#
data[].revisionobject#
data[].revision.idstringrequired#
Id prefix rev_.
data[].revision.numberintegerrequired#
data[].revision.published_attimestamprequired#
RFC 3339 timestamp (UTC, milliseconds).
data[].revision.evidence_hashstringrequired#
data[].approval_modestring | nullrequired#
One of: light-ai, external, view-only.
data[].allow_selectionsbooleanrequired#
data[].currencystringrequired#
Always USD.
data[].line_itemsobject[]required#
data[].line_items[].idstringrequired#
data[].line_items[].item_keystringrequired#
The line item id in the published document.
data[].line_items[].codestring | nullrequired#
Stable catalog code (template line item); null for custom lines.
data[].line_items[].namestring | nullrequired#
data[].line_items[].descriptionstring | nullrequired#
data[].line_items[].measurementstring | nullrequired#
data[].line_items[].quantitynumber | nullrequired#
The measured quantity (decimal for feet and square feet, whole for counted items); null for an unmeasured line.
data[].line_items[].unitstring | nullrequired#
One of: ft, sqft, each, set.
data[].line_items[].unit_priceMoney | nullrequired#
Set when quantity × unit_price equals amount to the cent; otherwise null (e.g. mini lights priced by the set) and amount is the line total.
data[].line_items[].unit_price_centsinteger | nullrequired#
data[].line_items[].amountMoneyrequired#
data[].line_items[].total_centsintegerrequired#
data[].line_items[].bulbstring | nullrequired#
One of: c9, mini.
data[].line_items[].colorsstring[]required#
data[].line_items[].patternstring | nullrequired#
data[].line_items[].requiredbooleanrequired#
data[].line_items[].selectedbooleanrequired#
data[].line_items[].taxablenullrequired#
data[].discountobject | null#
data[].discount.typestringrequired#
One of: percentage, fixed.
data[].discount.valuenumberrequired#
data[].discount.labelstring#
The discount line's name on the customer quote, e.g. "Black Friday offer" (a website request's offer); absent for a plain discount.
data[].totalsobjectrequired#
data[].totals.subtotalMoneyrequired#
data[].totals.discountMoneyrequired#
data[].totals.taxnullrequired#
data[].totals.totalMoneyrequired#
data[].totals.depositobjectrequired#
data[].selected_item_idsstring[]#
data[].assetsobjectrequired#
data[].assets.mockupsobject[]required#
data[].assets.schematicsobject[]required#
data[].engagementobjectrequired#
data[].engagement.availablebooleanrequired#
data[].engagement.first_viewed_attimestamp | null#
RFC 3339 timestamp (UTC, milliseconds).
data[].engagement.last_viewed_attimestamp | null#
RFC 3339 timestamp (UTC, milliseconds).
data[].engagement.view_countinteger#
data[].engagement.active_secondsnumber#
data[].approvalobject | nullrequired#
data[].approval.sourcestringrequired#
One of: light_ai, legacy_portal, external.
data[].approval.signed_bystring | null#
data[].approval.accepted_attimestamp | null#
RFC 3339 timestamp (UTC, milliseconds).
data[].approval.selected_item_idsstring[] | null#
data[].approval.evidence_hashstring | null#
data[].approval.external_refobject | null#
data[].declineobject | null#
data[].decline.sourcestringrequired#
Always external.
data[].decline.reasonstring | nullrequired#
data[].decline.declined_attimestamp | nullrequired#
RFC 3339 timestamp (UTC, milliseconds).
data[].decline.external_refobject | nullrequired#
data[].sent_attimestamp | nullrequired#
RFC 3339 timestamp (UTC, milliseconds).
data[].approved_attimestamp | nullrequired#
RFC 3339 timestamp (UTC, milliseconds).
data[].declined_attimestamp | nullrequired#
RFC 3339 timestamp (UTC, milliseconds).
data[].expires_attimestamp | nullrequired#
RFC 3339 timestamp (UTC, milliseconds).
data[].created_attimestamprequired#
RFC 3339 timestamp (UTC, milliseconds).
data[].updated_attimestamprequired#
RFC 3339 timestamp (UTC, milliseconds).
data[].fixtureboolean#
Always true.
has_morebooleanrequired#
next_cursorstring | nullrequired#
Pass as cursor to fetch the next page.

Errors#

StatusMeaning
400Bad request. bad_request, test_mode_mismatch, test_mode_unsupported, unsupported_api_version
401Missing or invalid credential. authentication_required, invalid_api_key, api_key_revoked, api_key_expired, api_key_suspended
403Not allowed. insufficient_scope, plan_upgrade_required, organization_paused, organization_off_season, api_disabled, api_access_not_enabled, ip_not_allowed, forbidden
404Not found (also for objects of other organizations and for organizations without an active grant).
422Validation failed. idempotency_key_reused
429Rate limited or daily cap reached. See Retry-After and the RateLimit headers. rate_limited, daily_cap_reached
500Unexpected server error. Safe to retry with exponential backoff; quote the Request-Id to support. internal_error
503Temporarily unavailable. Retry with exponential backoff. service_unavailable