Jobs
Long-running operations answer 202 with a job id. Poll GET /jobs/{jobId} for progress and cancel with DELETE before the alias swap.
Operations that can take longer than a request — rebuilding an index, crawling a
documentation site, importing uploaded files, writing or restoring a snapshot —
never run inside the HTTP request. The endpoint validates the input, queues a job
and answers 202 Accepted. A scheduler worker claims the job under a lease; if
the process dies mid-job, the lease expires and the job is picked up again.
| Job type | Started by | Scope needed to read / cancel |
|---|---|---|
reindex | POST /indexes/{slug}/reindex | settings:write |
crawl | POST /indexes/{slug}/docsearch/preview | documents:write |
file_import | Running a file connector | settings:write |
snapshot | POST /indexes/{slug}/snapshots | settings:write |
restore | POST /indexes/{slug}/snapshots/{id}/restore | settings:write |
eval | POST /quality/sets/{setId}/run | settings:write |
reembed | POST /indexes/{slug}/reembed?all=true | settings:write (started with documents:write) |
The 202 response
curl -sS -X POST "$AAC_API/indexes/products/reindex" \
-H "Authorization: Bearer $AAC_KEY"{
"index": "products",
"job_id": "clx8f2k9q0001",
"status": "queued",
"status_url": "/api/v1/jobs/clx8f2k9q0001",
"request_id": "req_…"
}The snapshot endpoints return job_id (plus snapshot_id on create) in the same
spirit; see Snapshots.
GET /jobs/{jobId}
curl -sS "$AAC_API/jobs/clx8f2k9q0001" -H "Authorization: Bearer $AAC_KEY"{
"job": {
"id": "clx8f2k9q0001",
"type": "reindex",
"status": "running",
"phase": "loading",
"progress": 42,
"attempts": 1,
"index": "products",
"documents_processed": 7731,
"error": null,
"result": null,
"created_at": "2026-10-25T09:00:00.000Z",
"started_at": "2026-10-25T09:00:02.000Z",
"finished_at": null
},
"request_id": "req_…"
}| Field | Meaning |
|---|---|
status | queued · running · completed · partial · failed · cancelled |
phase | Step inside the job. Reindex: queued → loading → copying → swapping → done; crawl: crawling → done |
progress | 0–100 |
attempts | How many times a worker claimed it (a crash and retry increments it) |
result | Set when finished, by type (below) |
result by type:
| Type | result |
|---|---|
reindex | { documents, duration_ms, source, snapshot_kept } |
crawl | { pages, skipped, errors[], total, records[] } — the first 25 records, nothing written to the index |
file_import | { loaded, indexed, failed, skipped, ocr_pages, files[] } |
snapshot | { snapshot_id, documents, bytes } |
restore | { snapshot_id, documents, duration_ms, snapshot_kept } |
reembed | { documents, failed, restored, embed_model, embed_model_version, duration_ms } |
eval | none — read the metrics from GET /quality/runs/{runId} |
DELETE /jobs/{jobId}
Cancels a job that is queued or running and has not reached the alias
swap:
curl -sS -X DELETE "$AAC_API/jobs/clx8f2k9q0001" -H "Authorization: Bearer $AAC_KEY"Returns the job envelope with status: "cancelled". A job that finished or is
already swapping answers:
{
"error": {
"code": "JOB_NOT_CANCELLABLE",
"message": "The job has finished or already reached the alias swap",
"details": { "status": "running", "phase": "swapping" },
"request_id": "req_…"
}
}with status 409. Cancellations are written to the audit log.
What a cancel does depends on the job:
| Type | After the cancel |
|---|---|
reindex, restore | The worker stops between pages and drops the half-built collection; the live index is untouched |
snapshot | Nothing is published; partial objects are removed |
file_import, reembed | Stops between files / batches; what was already written stays |
crawl | The crawl finishes in the background, but its result is discarded |
eval | The run is closed as failed |
Isolation
A job id is always resolved inside the key's organization. A job of another
tenant — or, for an index-bound key, of another index — is 404 JOB_NOT_FOUND, never 403.
Conflicts
Only one rebuild per index runs at a time. Starting a reindex or a restore while
a reindex or restore is queued or running answers 409 JOB_CONFLICT with the
active job_id in details. The same applies to ?sync=true. Only one reembed
job per index runs at a time either.
Synchronous reindex for tests
POST /indexes/{slug}/reindex?sync=true keeps the old blocking behaviour and
answers 200 with { index, job_id, documents, duration_ms }. It exists for
acceptance test suites; do not use it in production — a large index holds the
request for minutes. POST /quality/sets/{setId}/run?sync=true likewise keeps the
old blocking evaluation.