Syncing Integrations via API
The sync endpoint lets you trigger an integration sync on demand — a fresh pull of an app's accounts and entitlements into Lumos — from a script, a CI pipeline, or a scheduler. You don't need to manage the integration's connection through the API to use it: it works for integrations connected in the Lumos UI, via the Integrations API, or via Terraform.
Overview
A sync is how Lumos pulls an integration's current data - accounts, groups, and entitlements - so what you see in Lumos matches what's in the app. Lumos already syncs every connected integration on a regular schedule, and connecting or reconnecting an integration triggers a sync automatically.
The sync endpoint covers the moments in between: when you've just made changes in the app and want them reflected in Lumos now, rather than at the next scheduled sync. Typical triggers:
- Right after automation finishes a change in the app - an offboarding wave, a role migration, a department reorg.
- Right after
terraform applyconnects an integration, from the same CI pipeline. - Before kicking off an access review, so reviewers see current data.
- On your own schedule, if you want a specific integration refreshed more often.
Before you start
You need:
- An API token. Create one in the Lumos UI under Settings → API Tokens. The token is shown once - copy it somewhere safe. Examples below read it from a
LUMOS_API_TOKENenvironment variable. - Permission to manage integrations. A token acts as the user who created it, so that user must be an admin with permission to manage integrations. Without it, calls return
403. - A connected integration. Connected in the Lumos UI, via the API, or via Terraform — any of them works.
- The base URL
https://api.lumos.com. All paths below are relative to it.
Authentication
Send your token as a bearer token in the Authorization header on every request:
curl -s https://api.lumos.com/v1/apps \
-H "Authorization: Bearer $LUMOS_API_TOKEN"A request with a missing or invalid token returns 401.
Concept-to-endpoint map
| I want to... | Endpoint | Notes |
|---|---|---|
Find the integration's id | GET /v1/apps | Paginated; ?disconnected=false narrows to connected apps. |
| Trigger a sync on demand | POST /v1/apps/{id}/sync | Runs a full sync. 409 while one is already running. |
Core workflow
1. Find the integration's id
Syncs are triggered by the integration's id (a UUID). List your apps and pick the one you want — ?disconnected=false narrows the list to connected ones:
curl -s "https://api.lumos.com/v1/apps?disconnected=false" \
-H "Authorization: Bearer $LUMOS_API_TOKEN"{
"items": [
{
"id": "7d3b1c2e-8f4a-4c1d-9b2e-1a2b3c4d5e6f",
"app_class_id": "okta.com",
"instance_id": "your-org.okta.com",
"disconnected": false
}
],
"total": 1,
"page": 1,
"size": 50,
"pages": 1
}(Response trimmed to the relevant fields.)
If you connected the integration programmatically you already have this id: it's the id returned by the connect call, and the id attribute of the lumos_app Terraform resource (terraform state show lumos_app.okta).
2. Trigger the sync
Call the sync endpoint with the sync_type you want. Today the only supported value is full_sync — a full re-pull of the integration's accounts, groups, and entitlements:
curl -s -X POST https://api.lumos.com/v1/apps/$INTEGRATION_ID/sync \
-H "Authorization: Bearer $LUMOS_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "sync_type": "full_sync" }'Precondition: the integration is connected (or its last sync failed — retrying after a failure is allowed).
A 202 Accepted confirms the sync was launched:
{
"app_id": "7d3b1c2e-8f4a-4c1d-9b2e-1a2b3c4d5e6f",
"sync_type": "full_sync",
"status": "SYNCING"
}sync_type is required even though there's one value today — new sync kinds will be added as additional values, so your request shape won't change.
3. Understand what happens next
The sync runs asynchronously — the 202 means it was launched, not that it finished. How long it takes depends on the integration and the amount of data; when it completes, the refreshed accounts and entitlements are visible in Lumos.
Only one sync runs at a time per integration. If a sync is already in progress — including a scheduled one Lumos started — the call returns 409 Conflict:
{
"detail": "A sync is currently running for this app. Wait for it to finish, then retry.",
"type": "conflict",
"code": "conflict",
"errors": []
}Wait for the running sync to finish, then retry. Since the running sync is already pulling the app's current data, a 409 usually means the refresh you wanted is underway anyway.
Handling errors
Errors return the relevant HTTP status and a JSON body with a human-readable detail, plus machine-readable type and code fields your automation can branch on.
| Status | Cause | What to do |
|---|---|---|
400 Bad Request | The request body failed validation — a missing or unsupported sync_type. | Send {"sync_type": "full_sync"}; the errors[] list names the offending field. |
401 Unauthorized | Missing or invalid API token. | Send a valid Authorization: Bearer token. |
403 Forbidden | Your user can't manage integrations. | Use a token for an admin with integration permissions. |
404 Not Found | No integration with that id in your domain. | Check the id against GET /v1/apps. |
409 Conflict | A sync is already running; or the integration isn't connected yet; or its first sync is deferred pending an admin review in the Lumos UI. | Wait and retry; connect the integration first; or complete the review in the Lumos UI. |
422 Unprocessable Entity | The app is a manual/CSV app, which can't be synced via the API. | Manual/CSV apps are updated by uploading data instead. |
502 Bad Gateway | The sync failed to launch downstream. | Retry; if it persists, contact support. |
Next steps
- Connect and manage integrations programmatically with the Integrations API or Terraform.
- See the full API reference at https://developers.lumos.com.
Updated about 23 hours ago