> This page is for Model APIs.

> Sarvam Voice Agents (Samvaad) is a voice AI agent platform for Indian languages: build, test and deploy AI calling agents on your own phone numbers, from ₹3 a minute. Start here: https://docs.sarvam.ai/voice-agents/why-voice-agents.
> For clean Markdown of any page, append `.md` to the page URL.
> For a complete documentation index, see https://docs.sarvam.ai/llms.txt. For a section index, append `/llms.txt` to any section URL (for example https://docs.sarvam.ai/voice-agents/llms.txt).
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.sarvam.ai/_mcp/server.

# Jobs & Errors

> How Document AI jobs work: states, polling, status responses, error handling, and error codes shared by Parse, Extract, Split, and Classify.

Document AI jobs are asynchronous. You submit a job, wait for it to finish, then fetch the output. The same three steps apply to Parse, Extract, Split, and Classify.

#### Submit

Call `parse()`, `extract()`, `split()`, or `classify()`. One call creates and submits the job, and returns a `job_id` with an initial status.

#### Poll

Call `get_status()` with the `job_id` until the job reaches a [terminal state](#job-states).

#### Fetch

Call `get_results()` for structured data, or `get_download_url()` for the output file (Parse and Extract only). See [Fetch the output](#fetch-the-output).

## Job states

| State                 | Description                                                     |
| --------------------- | --------------------------------------------------------------- |
| `pending`             | Job created, queued for processing                              |
| `running`             | Job is being processed                                          |
| `completed`           | All pages processed successfully                                |
| `partially_completed` | Some pages succeeded, some failed                               |
| `failed`              | All pages failed or a job-level error occurred                  |
| `rejected`            | Job rejected before processing (e.g. validation or entitlement) |

Split and Classify jobs report `accepted` when created and `completed` when finished. Their status includes `type` (`split` or `classify`), `phase`, and `progress`, and `usage` has `pages_processed` and `pages_source`.

Terminal states are `completed`, `partially_completed`, `failed`, and `rejected`.

## Status response

```json
{
  "job_id": "019fb81e-2543-70bd-a737-b5a2d62a3bb7",
  "status": "completed",
  "pipeline": "parse",
  "usage": {
    "pages_total": 1,
    "pages_processed": 1,
    "pages_succeeded": 1,
    "pages_failed": 0
  },
  "created_at": "2026-07-31T12:20:11Z",
  "updated_at": "2026-07-31T12:20:15Z"
}
```

## Fetch the output

Each operation returns its output through a different call:

| Operation | Fetch with           | You get                                                                    |
| --------- | -------------------- | -------------------------------------------------------------------------- |
| Parse     | `get_download_url()` | A link to a ZIP with the primary file, per-page metadata, and a manifest   |
| Extract   | `get_results()`      | The field values you defined. `get_download_url()` returns the output file |
| Split     | `get_results()`      | The child documents (`segments`)                                           |
| Classify  | `get_results()`      | The decision, or one per page                                              |

Calling either before the job reaches a terminal state returns `409`.

## What to do in each terminal state

| State                 | What to do                                                                                                                           |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `completed`           | Fetch the output. For Split and Classify, also check `review_required` before accepting the result automatically                     |
| `partially_completed` | Fetch the output, then check `usage.pages_failed` to see how many pages are missing, and resubmit those pages if you need them       |
| `failed`              | There is no output to fetch. Check the error, fix the cause, and submit again                                                        |
| `rejected`            | The job never started processing, usually because of validation or entitlement. Fix the request or your plan access and submit again |

Poll every few seconds (the examples use 5) and read `usage` in the status response to show progress on long documents.

## Error Handling

#### Error Handling Code Example

```python
import json, os
from sarvamai import SarvamAI
from sarvamai.core.api_error import ApiError

client = SarvamAI(api_subscription_key=os.environ["SARVAM_API_KEY"])

try:
    with open("./insurance-policy.pdf", "rb") as f:
        job = client.doc_ai.extract(
            file=[("insurance-policy.pdf", f, "application/pdf")],
            schema=json.dumps({
                "type": "object",
                "properties": {
                    "policy_number": {"type": "string", "description": "Insurance policy number"},
                },
            }),
            output_format="json",
        )

    # ... poll get_status() until terminal ...

    results = client.doc_ai.get_results(job_id=job.job_id)
    print(results.result)

except ApiError as e:
    if e.status_code == 400:
        print(f"Bad request or invalid schema: {e.body}")
    elif e.status_code in (402, 403):
        print("Billing or entitlement error")
    elif e.status_code == 409:
        print("Results requested before the job reached a terminal state")
    elif e.status_code == 413:
        print("File too large")
    elif e.status_code == 429:
        print("Rate limit exceeded")
    else:
        print(f"Error {e.status_code}: {e.body}")
except FileNotFoundError:
    print("Document file not found: ./insurance-policy.pdf")
```

### Error Codes

The full error-code table, retry guidance, and SDK exception reference live on the central [Errors & Troubleshooting](/api/getting-started/errors-troubleshooting) page. Errors specific to this API:

| HTTP Status   | Description                                                                                                                           |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `400`         | Invalid request or schema (includes documents exceeding the page limit)                                                               |
| `402` / `403` | Billing or entitlement error                                                                                                          |
| `404`         | Resource unavailable (e.g. job not found)                                                                                             |
| `409`         | Results or download requested before the job reached a terminal state                                                                 |
| `413`         | File too large                                                                                                                        |
| `422`         | Invalid file format or corrupted file. For Split and Classify, also an invalid page range or an option this deployment does not offer |
| `429`         | Rate or admission limit                                                                                                               |
| `503`         | Billing unavailable                                                                                                                   |