> For the complete documentation index, see [llms.txt](https://docs.uptiq.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.uptiq.ai/document-ai/developer-documentation/getting-started/quickstart-extract-a-document.md).

# Quickstart: extract a document

**Goal.** Send a PDF to Document AI and get back structured fields — company name, dates, financial line items — without writing any polling logic.

This is the shortest path from a file to data. It uses the synchronous endpoint, which holds the connection open until extraction finishes. That makes it ideal for trying the API out and poor for production, for reasons the last section covers.

### Before you start

* An API key. **Settings → API Keys** in the portal, as Owner or Admin — see [Authentication](/document-ai/developer-documentation/getting-started/authentication.md).
* A document. This recipe uses a one-page balance sheet PDF.
* A client that will wait **at least two minutes** for a response.

```bash
export DOCAI_API_KEY='ak_…'
```

### Step 1 — Choose a document type

Extraction is schema-driven: telling the platform what the document *is* determines which fields it looks for. Values come from the registry.

```bash
curl -s "https://api-docai-uat.uptiq.ai/listSupportedDocuments" \
  | jq -r '.documents[] | "\(.type)\t\(.category)"' | head
```

```
ACATAccountTransferForm         Account Transfer Document
AadhaarCard                     Identity Document
AccountReceivablesAgingReport   Financial Report
AccountsPayableAgingReport      Financial Report
ArticlesOfIncorporation         Corporate Document
```

We want `BalanceSheet`. If you do not know the type ahead of time, [classify first](/document-ai/cookbooks/classify-then-extract.md).

### Step 2 — Build the request

The document travels inside the JSON body, base64-encoded, so no multipart upload is involved.

```bash
python -c "
import base64, json
content = base64.b64encode(open('balance-sheet.pdf','rb').read()).decode()
json.dump({
    'documentType': 'BalanceSheet',
    'content': content,
    'model': 'gemini-3'
}, open('request.json','w'))
"
```

{% hint style="info" %}
If your file already has a URL the platform can reach, send `file_url` instead of `content` and skip the base64 step. Send one or the other — never both.
{% endhint %}

### Step 3 — Call the endpoint

Use [Synchronous document extraction](/document-ai/developer-documentation/extraction-1/synchronous-document-extraction.md) for the complete request and response schema.

```bash
curl -X POST "https://api-docai-uat.uptiq.ai/extract/sync" \
  -H "X-Api-Key: $DOCAI_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @request.json \
  -o response.json
```

This took **93 seconds** for a single page. That is normal — the work is OCR plus model inference. Do not lower your timeout to "fix" it.

### Step 4 — Read the result

```json
{
  "_id": "8c1d47e9-2f36-4a85-b7c0-6e93a5d21fb8",
  "documentStatus": "Processed",
  "documentType": "BalanceSheet",
  "requestId": "b93c5f28-41a7-4e60-9d18-72c6ea035b1f",
  "status": "success",
  "result": {
    "extractedData": { },
    "extractionMetrics": { },
    "documentQuality": { },
    "layoutData": { },
    "tokenUsage": { },
    "ocrUsage": { }
  }
}
```

Check `documentStatus` — `Processed` means it worked. `status: "success"` refers to the API call, not the document, and will read `success` even for a document that failed to process.

The fields are under `result.extractedData`, each with its value and where it was found on the page:

```bash
jq '.result.extractedData.CompanyName' response.json
```

```json
{
  "value": "Northwind Trading Co.",
  "bbox": [
    { "pageNumber": 1, "pageWidth": 8.5, "pageHeight": 11.0,
      "x1": 0.8256, "y1": 0.2805, "x2": 3.7036, "y2": 0.7508 }
  ]
}
```

The `bbox` coordinates are in inches, page-relative — enough to draw a highlight over the source document if you are building a review UI.

### Step 5 — Judge whether to trust it

Do not treat every extraction as equally good. `result.extractionMetrics` grades the run:

```json
{
  "accuracyScore": 85.67,
  "completenessScore": 66.67,
  "consistencyScore": 88.0,
  "formatScore": 100.0,
  "rulesChecked": 25,
  "rulesPassed": 22,
  "rulesFailed": 3,
  "totalExpectedFields": 6,
  "totalPopulatedFields": 4,
  "missingFields": [ ],
  "failedRules": [ ]
}
```

On our run, four of six expected fields were populated — hence `completenessScore` of 66.67 — because the test document was deliberately sparse. `missingFields` names exactly what was not found.

A sensible gate: auto-accept above a threshold on `accuracyScore`, route anything below it to human review. `result.documentQuality.level` (`high`, and a `sharpness` figure) tells you whether a poor result is the document's fault or the model's.

### What it cost

```json
{
  "creditReservation": { "cost": 0.03, "pages": 1, "operation": "extraction" },
  "tokenUsage":  { "total_tokens": 29375, "model": "gemini-3", "provider": "gemini" },
  "ocrUsage":    { "estimated_cost": 0.01, "page_count": 1, "provider": "azure" }
}
```

Useful for chargeback, and for noticing when a job runs away.

### When it goes wrong

| Symptom                  | Cause                                                               | Fix                                                                                                    |
| ------------------------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `401`                    | Missing, expired or revoked key                                     | Check **Settings → API Keys**                                                                          |
| `500` immediately        | Missing or malformed body — **not** a server fault on this endpoint | Validate your JSON; see [Errors](/document-ai/developer-documentation/getting-started/errors.md)       |
| Client timeout           | Waiting less than \~2 minutes                                       | Raise the timeout, or use the [async endpoint](/document-ai/cookbooks/async-extraction-and-polling.md) |
| `documentStatus: Failed` | The document could not be read                                      | Check `result.documentQuality`; resubmitting an unreadable file will fail again                        |
| Empty `extractedData`    | Wrong `documentType` for the document                               | [Classify it first](/document-ai/cookbooks/classify-then-extract.md)                                   |

### Next steps

**Do not build production on this endpoint.** Ninety seconds of held connection does not survive a load balancer, a serverless timeout, or a user watching a spinner. Move to [Extract asynchronously and poll](/document-ai/cookbooks/async-extraction-and-polling.md), or better, [Build an event-driven pipeline](/document-ai/cookbooks/event-driven-pipeline.md). The request body is identical — only the URL changes.

### Related pages

* [Extraction API](/document-ai/developer-documentation/integration-guides/extraction.md) — every parameter this request accepts.
* [Document Extraction](/document-ai/guides-1/document-extraction.md) — the same capability in the UI, including result review.
* [Conventions](/document-ai/developer-documentation/getting-started/conventions.md) — envelopes, the lifecycle, and timing.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.uptiq.ai/document-ai/developer-documentation/getting-started/quickstart-extract-a-document.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
