# Async jobs
Source: https://docs.file.ai/api/async-jobs

> How long-running work is tracked in the fileAI API, and when to poll or use a callback.

Production

# Async jobs

Copy pageCopy page

How long-running work is tracked in the fileAI API, and when to poll or use a callback.

Copy pageCopy page

Most fileAI work takes longer than an HTTP request should: OCR, extraction, an agent’s answer, a forensics scan. The API accepts the work, hands you an id straight away, and lets you either poll that id or receive a callback when it settles. There are four kinds of long-running work, each with its own id and status values.

## 

[​

](#how-it-works)

How it works

Work

Started by

Id

Poll

Callback

[Upload processing](#uploads)

`POST /v1/files/upload` (and batch, multipart)

`uploadId`

`GET /v1/uploads/{uploadId}`

`callbackURL` ([payload](/deliver/callbacks))

[Document jobs](#document-jobs)

`POST /v1/extract`, `/v1/split`, `/v1/classify`

`job_…`

`GET /v1/jobs/{job_id}`

`callback_url` on the request

[Agent jobs](#agent-jobs)

`POST /v1/agent/sessions/{session_id}/ask`

`sajob_…`

`GET /v1/jobs/{job_id}`

The API key’s default callback URL

[Forensics runs](#forensics-runs)

`POST /v1/forensics`

`run_id`

`GET /v1/forensics/runs/{run_id}`

None: poll only

Submit calls for jobs and runs return `202 Accepted` with the id and a `poll_url`. `poll_url` is a URI reference: if it comes back without a scheme and host, resolve it against the host you called.

### 

[​

](#polling-or-callbacks)

Polling or callbacks

**Polling is the source of truth; a callback is a speed-up.** No callback is retried, so a callback your endpoint misses is gone, while the job or upload itself stays readable.

*   Use a callback to learn about settled work quickly.
*   Keep polling as a fallback for anything you have not heard back about.
*   Make your handler idempotent: a job or upload can be reported more than once.
*   Treat a callback as a prompt to fetch the job or upload with your API key, not as the result itself.

Upload callbacks and job callbacks are delivered differently:

Upload callbacks

Document job callbacks

Agent job callbacks

Where it goes

`callbackURL` on the upload; single and batch uploads fall back to the API key’s default callback URL, multipart uploads do not

`callback_url` on the request only

The API key’s default callback URL

When it is sent

Once per processing step

When the job settles

When the job settles, and again if a provisional failure resolves

Payload

Small step event ([Processing callbacks](/deliver/callbacks))

The job, as polling returns it ([below](#callbacks))

The job, as polling returns it ([below](#callbacks))

Attempts

One `POST`, never retried

One `POST`, never retried

One `POST`, never retried

Timeout

None set by fileAI

10 seconds

10 seconds

Signature

None

May carry `X-Signature`, which you cannot verify yet

May carry `X-Signature`, which you cannot verify yet

Forensics runs have no callback: poll them.

## 

[​

](#uploads)

Uploads

An upload is tracked by its `uploadId`. `GET /v1/uploads/{uploadId}` returns:

Field

Description

`statuses`

Processing steps so far, each with `step`, `status`, `timestamp` and, on failure, a human-readable `errorReason`.

`files`

The documents produced from the upload, in the same shape as `GET /v1/files`. Each has its own `status`.

`fileType`

The uploaded file’s type.

`aiProcessingProvider`

The engine that actually processed the file.

Each step has one of these statuses (step names are listed on [Processing callbacks](/deliver/callbacks#steps)):

Step `status`

Meaning

`waiting`

The step is queued.

`processing`

The step is running.

`completed`

The step finished. The upload is done when `processing_finished` is `completed`.

`error`

The step failed. `errorReason` says why, when it is known.

A ZIP upload returns one entry per extracted file in `files`, and answers `207` when some extracted files succeeded and others failed.

The `statuses` list is held for 10 minutes after the most recent step. After that it can come back empty. For a finished upload, read each document’s `status` in `files` (for example `processed` or `action_required`) instead.

## 

[​

](#document-jobs)

Document jobs

`POST /v1/extract`, `/v1/split` and `/v1/classify` each take one document and return a job with a `job_` id:

```
{
  "job_id": "job_4b7e8d4c1fa0b39f2c1a6d0e8b7f5a21",
  "status": "queued",
  "created_at": "2026-09-25T02:14:00.000Z",
  "poll_url": "https://api.orion.file.ai/prod/v1/jobs/job_4b7e8d4c1fa0b39f2c1a6d0e8b7f5a21"
}
```

Polling it returns `kind: "extraction"` and one of these statuses:

`status`

Meaning

`queued`

Not settled. Poll again.

`succeeded`

Final. `result` holds the output.

`failed`

Final. `error.code` and `error.detail` describe the failure.

`usage` (`pages`, `credits`) appears once the job has settled, and `client_ref` echoes the value you submitted. See [Extract, split and classify](/extract/split-classify) for request fields and result shapes. To get a callback, send `callback_url` with the request. The API key’s default callback URL is **not** used for document jobs; agent jobs use only that default.

## 

[​

](#agent-jobs)

Agent jobs

Each question asked in an [agent session](/ask/agent-sessions) is a job with a `sajob_` id, polled on the same `GET /v1/jobs/{job_id}` route. It returns `kind: "agent"` and uppercase statuses:

`status`

Meaning

`QUEUED`, `RUNNING`

Not ready. Poll again.

`COMPLETED`

Final. `result.answer` holds the answer.

`STOPPED`

Final. A turn stopped early; `result.answer` holds the partial answer.

`FAILED`

Final, except that `error.code` `SUPERAGENT_RUN_STALE` is provisional and can still move to `COMPLETED` or `STOPPED`.

`GET /v1/jobs/{job_id}` serves both kinds. Branch on `kind` before reading anything else: the statuses and `result` differ.

## 

[​

](#forensics-runs)

Forensics runs

A [fileForensics](/forensics/overview) run checks a file that is already stored in your workspace. It is not a job: it does not appear on `GET /v1/jobs/{job_id}`, and it has no callback.

`status`

Meaning

`queued`, `running`

In progress. Poll again.

`complete`

Final. Each detector’s result is under `forensics`.

`error`

Final. The run failed, or was replaced by a retry.

A run that is stuck can be re-run with `POST /v1/forensics/runs/{run_id}/retry`, which returns a **new** `run_id` to poll. `GET /v1/forensics/files/{file_id}` returns the newest run for a file, including runs started at upload. See [Run status](/verify/forensics#run-status) for details.

## 

[​

](#callbacks)

Callbacks

Document and agent job callbacks share one shape, mirroring what polling returns:

```
{
  "event": "extraction.job.settled",
  "job_id": "job_4b7e8d4c1fa0b39f2c1a6d0e8b7f5a21",
  "status": "succeeded",
  "created_at": "2026-09-25T02:14:00.000Z",
  "updated_at": "2026-09-25T02:14:09.000Z",
  "client_ref": "shipment-8812",
  "result": { "documents": [] },
  "error": null,
  "usage": { "pages": 6, "credits": 6 }
}
```

Document jobs

Agent jobs

`event`

`extraction.job.settled`

`superagent.job.settled`

`usage`

Included

Not included

Sent when

The job settles

The job settles, and again if a provisional `SUPERAGENT_RUN_STALE` failure later resolves

Delivery is a single `POST` with `Content-Type: application/json` and a 10-second timeout. It is not retried, whatever your endpoint returns.

Job callbacks may carry `X-Signature` and `X-Timestamp` headers. There is no per-key secret you can verify them with yet, so treat every callback as unauthenticated: fetch the job with your API key before acting on it.

## 

[​

](#related)

Related

## Processing callbacks

Step-by-step events for uploads.

## Extract, split and classify

Submit one document and poll its job.

## Agent sessions

Ask questions and poll `sajob_` jobs.

## Idempotent requests

Retry submits without creating duplicate work.

[Previous](/production)[

Errors

Read fileAI API errors: RFC 9457 problem documents, stable error codes and request ids.

Next

](/api/errors)

⌘I

## On this page

*   [How it works](#how-it-works)
    *   [Polling or callbacks](#polling-or-callbacks)
*   [Uploads](#uploads)
*   [Document jobs](#document-jobs)
*   [Agent jobs](#agent-jobs)
*   [Forensics runs](#forensics-runs)
*   [Callbacks](#callbacks)
*   [Related](#related)
