> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ingestly.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Polling a run

> Submit a document, follow its run to the end and collect the result.

Ingestly processes documents asynchronously. The trigger answers as soon as the document is stored, and you follow the run with read requests until it finishes. Every step below uses an API key with the [scope](/api-reference/authentication#scopes) it names.

## 1. Submit the document

[Trigger the workflow](/api-reference/trigger-webhook) (`workflows:trigger`). Send a `reference` so you can match the result to your own record later:

```bash theme={null}
curl -X POST "https://api.ingestly.ai/workflows/{workflowId}/trigger" \
  -H "X-Api-Key: ing_prod_your_api_key_here" \
  -H "Idempotency-Key: 3f2504e0-4f89-41d3-9a0c-0305e82c3301" \
  -F "file=@po-1182.pdf" \
  -F "reference=PO-1182"
```

```json theme={null}
{
  "documentId": "0199a6c2-3f1e-7b2a-9c4d-5e6f7a8b9c0d",
  "runId": "0199a6c2-4b7d-7e01-8f3a-2c4d6e8f0a1b",
  "status": "queued",
  "reference": "PO-1182"
}
```

Store both ids. When `status` is `held`, `runId` is `null`: the document waits until someone runs it. Find its run later with [list the runs of a document](/api-reference/list-document-runs) (`runs:read`), which returns the document's runs newest first.

## 2. Poll the run

[Get the run](/api-reference/get-run) (`runs:read`) until its `status` is final:

```bash theme={null}
curl "https://api.ingestly.ai/runs/0199a6c2-4b7d-7e01-8f3a-2c4d6e8f0a1b" \
  -H "X-Api-Key: ing_prod_your_api_key_here"
```

| `status` | Meaning | Final |
| - | - | - |
| `queued` | The run is waiting to start | No |
| `running` | Nodes are executing | No |
| `awaiting_children` | The run waits for the child runs a split or loop started | No |
| `review` | The run waits for a person to finish a [review task](#3-follow-review-tasks) | No |
| `waiting` | The run is parked on a [Wait](/nodes/wait) node | No |
| `completed` | Every step finished | Yes |
| `failed` | The run stopped on an error; `error.code` and `error.message` say why | Yes |
| `cancelled` | The run was cancelled; `error.code` says by whom or why | Yes |

Poll every few seconds and back off for long runs: a run in `review` or `waiting` can take hours. Polling counts against the plan's [read limit](/api-reference/rate-limits), not the trigger limit, and costs no credits.

<Note>
  A `runId` from the trigger can answer `404 Not Found` for a moment before the run is created, and stays `404` if the run never starts, for example when the workflow stops running automatically before the document is processed. [Get the document](/api-reference/get-document) (`documents:read`): its `status` (such as `failed`, `cancelled` or `held`) tells you what happened.
</Note>

## 3. Follow review tasks

While a run is in `review`, [list review tasks](/api-reference/list-review-tasks) (`reviews:read`) filtered by `runId`. The filter also matches tasks of [reusable sections](/guides/reusable-sections) the run called:

```bash theme={null}
curl "https://api.ingestly.ai/review-tasks?runId=0199a6c2-4b7d-7e01-8f3a-2c4d6e8f0a1b&status=pending" \
  -H "X-Api-Key: ing_prod_your_api_key_here"
```

The list is paged: pass `page` (from 1) and `pageSize` (default 20, at most 100). The response carries `count` (total items), `pages` (total pages) and `data`. A task's `decision` is `approved` or `rejected` once a person finished it; reviews themselves happen in the [review queue](/reviews/queue).

## 4. Collect the output

When the run is `completed`, [get its output](/api-reference/get-run-output) (`runs:read`). The output is what the workflow's [Download Output](/nodes/download-output) node captured:

```json theme={null}
{
  "contentType": "application/json",
  "filename": "invoice-parser-po-1182-pdf-0199a6c2.json",
  "isBase64": false,
  "output": { "poNumber": "PO-1182", "total": 1250.0 }
}
```

* JSON output arrives as a JSON value, text formats (CSV, XML, YAML, plain text) as a string, and binary formats as a base64 string with `isBase64` set to `true`.
* With several Download Output nodes, pass `nodeId` to choose one; without it, the most recently started one answers. A `nodeId` that is not a node of the graph the run executed returns `404 Not Found`.
* `409 Conflict` means the run has not completed or captured no output. `413 Content Too Large` means the output exceeds the 10 MB that can be returned inline; download it from the run in the dashboard instead.

To fetch the file you submitted, [download the document's original file](/api-reference/get-document-original) (`documents:read`). It returns a `url` valid for 5 minutes (until `expiresOn`); request a new one after it expires.

## Reading responses safely

* Errors are [RFC 7807 problems](/api-reference/introduction#error-response) served as `application/problem+json`; branch on the HTTP status and log the `detail`.
* Ignore fields you do not recognize, and treat an unknown `status` or enum value as "not final yet". New fields and values can appear without notice.
* All timestamps are UTC (ISO 8601).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.