Concepts
Pagination & sync
Cursor pagination, initial and incremental syncs with updated_since, and the gapless events feed.
List endpoints return { "data": [...], "has_more": true, "next_cursor": "…" }. Pass next_cursor back as cursor until has_more is false. limit is 1–100 (default 25).
curl "https://api.light-ai.app/v1/leads?limit=100" \
-H "Authorization: Bearer $LIGHT_AI_API_KEY"const response = await fetch('https://api.light-ai.app/v1/leads?limit=100', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.LIGHT_AI_API_KEY}`,
},
});
const data = await response.json();import os, requests
response = requests.get(
"https://api.light-ai.app/v1/leads?limit=100",
headers={
"Authorization": f"Bearer {os.environ['LIGHT_AI_API_KEY']}",
},
)
data = response.json()Initial sync#
Page through leads, clients, projects and quotes with sort=updated_asc. Store the highest updated_at you saw (your high-water mark).
curl "https://api.light-ai.app/v1/clients?sort=updated_asc&limit=100" \
-H "Authorization: Bearer $LIGHT_AI_API_KEY"const response = await fetch('https://api.light-ai.app/v1/clients?sort=updated_asc&limit=100', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.LIGHT_AI_API_KEY}`,
},
});
const data = await response.json();import os, requests
response = requests.get(
"https://api.light-ai.app/v1/clients?sort=updated_asc&limit=100",
headers={
"Authorization": f"Bearer {os.environ['LIGHT_AI_API_KEY']}",
},
)
data = response.json()Incremental sync#
Poll with sort=updated_asc&updated_since=<high-water mark minus 5 minutes> and de-duplicate by id + updated_at: a write that commits late can carry an earlier timestamp.
Gapless events feed#
For a change feed that never misses anything, poll GET /v1/events?sort=sync_asc. Store next_cursor and pass it back as cursor: every event appears exactly once, even for slow transactions. Events are kept for 30 days. Filter with type or types (comma-separated).
curl "https://api.light-ai.app/v1/events?sort=sync_asc&types=lead.created,quote.approved&limit=100" \
-H "Authorization: Bearer $LIGHT_AI_API_KEY"const response = await fetch('https://api.light-ai.app/v1/events?sort=sync_asc&types=lead.created,quote.approved&limit=100', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.LIGHT_AI_API_KEY}`,
},
});
const data = await response.json();import os, requests
response = requests.get(
"https://api.light-ai.app/v1/events?sort=sync_asc&types=lead.created,quote.approved&limit=100",
headers={
"Authorization": f"Bearer {os.environ['LIGHT_AI_API_KEY']}",
},
)
data = response.json()Webhooks or polling?#
| Webhooks | Events feed | |
|---|---|---|
| Latency | Seconds | Your poll interval |
| Needs a public URL | Yes | No |
| Ordering | Not guaranteed | Exactly once, in commit order |
| Good for | Real-time CRM updates | Batch jobs, firewalled servers, catch-up after downtime |
History before you enabled the API is not replayed as events: read it with the list endpoints.