A processing callback is a POST that fileAI sends to your callback URL as an upload moves through processing. It tells you which step finished, whether it succeeded, and, once the upload has been split into documents, the fileId of each document, so you can fetch values without polling. This page is the payload reference. To choose between callbacks and polling, and for extract, split, classify and agent job callbacks, see Async jobs. For signed events about files, uploads, folders and File Agents, set up webhooks.
Upload callbacks are sent once and not retried. If your endpoint is down or returns an error, that event is lost. Keep polling GET /v1/uploads/{uploadId} as a fallback. See Async jobs.

How it works

Where the callback goes

You set callbackURL when you request the upload, or rely on your API key’s default callback URL. Multipart uploads do not fall back to the key’s default. The full rules are under Upload options. Files added in the fileAI app or by email use your organization’s file-processing callback URL, if one is set. Use an HTTPS URL that accepts POST with a JSON body. Any #fragment on the URL is dropped before sending.

What gets sent

Each event is a single POST with Content-Type: application/json. There are no other custom headers: no signature, no timestamp, no event id. fileAI logs your response status but does not act on it, and sets no client timeout of its own. A typical successful upload sends events for these steps, in roughly this order: processing_started usually arrives twice: first with waiting, then with completed. Not every upload passes through every step, and the order is not guaranteed: key your logic on step and status, not on position. fileIds first appears on split_classify, and again on processing_finished. An upload that fails sends processing_failed with status error and an errorReason.
Reprocessing a document (for example, replacing its file) can send another round of events for the same uploadId, including beethoven_ocr or ai_form_filling with status processing and a further processing_finished. Make your handler safe to run more than once.

Handle callbacks safely

Upload callbacks are not signed, so anyone who learns your callback URL can send a request that looks like one. Treat a callback as a signal to check, not as proof:
1

Put a token in the callback URL

Add an unguessable value to the query string of each upload’s callbackURL, for example https://example.com/fileai/callback?token=8f3c…, and reject requests without it. fileAI keeps the query string and drops only a #fragment. This stops requests from anyone who doesn’t know the URL; it is not a signature.
2

Confirm the state with the API

Before anything consequential (paying, approving, releasing a claim), fetch the upload with your API key: GET /v1/uploads/{uploadId}. Act on the status of each document in files (for example processed), not on the callback body. See Uploads in Async jobs.
3

Make the handler safe to repeat

The same uploadId can send processing_finished more than once (see reprocessing above). Record which uploadId and fileIds you have already handled and skip repeats.
4

Keep a polling fallback

Callbacks are not retried. For any upload that hasn’t reached processing_finished in the time you expect, poll GET /v1/uploads/{uploadId}, or pull changes on a schedule with incremental loading.

Example

A successful upload that produced two documents ends with:
A failed upload sends:
A minimal receiver checks the token, acknowledges fast, and hands the upload to a worker. The worker calls GET /v1/uploads/{uploadId} and uses only documents whose status is processed. fileIds is one comma-joined string, not an array, so split it before you record which documents you have handled.

Reference

Payload fields

There is no timestamp field. Record the time you received the event if you need one; GET /v1/uploads/{uploadId} returns a timestamp per step.

Statuses

Steps

Async jobs

Upload status polling, and callbacks for extract, split, classify and agent jobs.

Uploads

Single, batch and multipart uploads, where you set callbackURL.

Incremental loading

Pull new and changed files on a schedule instead of reacting to events.

API quickstart

Upload a file and read its values end to end.