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

# Balanced and Accurate Extraction Modes

> Extraction with per-field verification, reasoning, and citations.

Balanced and accurate modes run an extraction pipeline with independent verification. Scalar fields include metadata describing the supporting evidence and extraction reasoning. When available, verification metadata records the independent check; nested objects and arrays retain their structure.

**Before you begin**, make sure you have:

1. A [Datalab account](https://www.datalab.to/auth/sign_up) with an [API key](https://www.datalab.to/app/keys) (new accounts include \$5 in free credits)
2. Python 3.10+ installed
3. The Datalab SDK: `pip install datalab-python-sdk`
4. Your `DATALAB_API_KEY` environment variable set

<Info>
  EU requests return a signed `result_url`; the REST examples below download it before reading the output. See [Regional Result Downloads](/docs/recipes/conversion/conversion-api-overview#regional-result-downloads), including the Python SDK 0.5.0 limitation.
</Info>

## Choosing an Extraction Mode

| | Fast | Balanced (default) | Accurate |
| - | - | - | - |
| **Base extraction rate** | \$6 / 1K pages | \$15 / 1K pages | \$20 / 1K pages |
| **Per-field citations** | Yes | Yes | Yes |
| **Extraction status and reasoning** | No | Yes | Yes |
| **Independent verification** | No | Yes | Yes |
| **Use when** | Speed and cost are the priority | You need verification metadata | Complex documents need additional auditing and a stronger extraction model |

Accurate uses the same verification format as balanced. It can take longer and cost more; evaluate both on your documents. [Turbo mode](/docs/recipes/structured-extraction/api-overview#extraction-modes) skips parsing and returns extracted JSON without citations or verification.

The rates above cover extraction. Parsing is billed separately when it runs, and complex requests can incur usage-based charges. See [Billing](/platform/billing) and [pricing](https://www.datalab.to/pricing).

## Schema Size

Balanced and accurate extraction accept up to **750 schema fields**. Count scalar fields inside objects and arrays; repeated array items do not multiply the schema field count. Schemas above this limit fail with an error asking you to split or simplify them.

Large schemas on short documents are partitioned during extraction. The 750-field limit applies across document lengths. Free accounts without a payment method also have a processing-cost limit; a request that exceeds it returns an error asking you to reduce the workload or upgrade.

## Quick Start

<CodeGroup>
  ```python Python SDK theme={null}
  import json
  from datalab_sdk import DatalabClient, ExtractOptions

  client = DatalabClient()

  schema = {
      "type": "object",
      "properties": {
          "company_name": {"type": "string", "description": "Full legal name of the company"},
          "fiscal_year_end": {"type": "string", "description": "End date of the fiscal year (YYYY-MM-DD)"},
          "total_revenue": {"type": "number", "description": "Total revenue in the reporting currency"},
          "auditor_name": {"type": "string", "description": "Name of the external audit firm"}
      },
      "required": ["company_name", "fiscal_year_end"]
  }

  options = ExtractOptions(
      page_schema=json.dumps(schema),
      extraction_mode="balanced",
      mode="accurate",
  )

  result = client.extract("annual_report.pdf", options=options)
  extracted = json.loads(result.extraction_schema_json)

  # Each field comes with citations and metadata
  print(f"Company: {extracted['company_name']}")
  print(f"Citations: {extracted['company_name_citations']}")
  print(f"Status: {extracted['company_name_meta']['extraction_status']}")
  verification = extracted["company_name_meta"].get("verification") or {}
  print(f"Verified: {verification.get('status', 'UNAVAILABLE')}")
  ```

  ```bash cURL theme={null}
  curl -X POST https://www.datalab.to/api/v1/extract \
    -H "X-API-Key: $DATALAB_API_KEY" \
    -F "file=@annual_report.pdf" \
    -F "extraction_mode=balanced" \
    -F 'page_schema={"type":"object","properties":{"company_name":{"type":"string","description":"Full legal name"},"total_revenue":{"type":"number","description":"Total revenue"}}}'

  # Poll request_check_url from response until status is "complete"
  ```

  ```python Python (requests) theme={null}
  import requests, json, time, os

  headers = {"X-API-Key": os.getenv("DATALAB_API_KEY")}

  schema = {
      "type": "object",
      "properties": {
          "company_name": {"type": "string", "description": "Full legal name"},
          "total_revenue": {"type": "number", "description": "Total revenue"}
      }
  }

  with open("annual_report.pdf", "rb") as f:
      response = requests.post(
          "https://www.datalab.to/api/v1/extract",
          files={"file": ("annual_report.pdf", f, "application/pdf")},
          data={
              "page_schema": json.dumps(schema),
              "extraction_mode": "balanced"
          },
          headers=headers
      )

  check_url = response.json()["request_check_url"]

  while True:
      result = requests.get(check_url, headers=headers).json()
      if result.get("success") is False or result.get("status") == "failed":
          raise RuntimeError(result.get("error") or "Document processing failed")
      if result["status"] == "complete":
          if result.get("result_url"):
              download = requests.get(result["result_url"], timeout=60)
              download.raise_for_status()
              result = {**download.json(), **{k: v for k, v in result.items() if v is not None}}
          if result.get("success") is False:
              raise RuntimeError(result.get("error") or "Document processing failed")
          extracted = result["extraction_schema_json"]
          if isinstance(extracted, str):
              extracted = json.loads(extracted)
          print(json.dumps(extracted, indent=2))
          break
      time.sleep(2)
  ```
</CodeGroup>

<Note>
  `extraction_mode` controls the extraction pipeline (`turbo`, `fast`, `balanced`, or `accurate`). This is separate from `mode`, which controls the document parsing stage (`fast`, `balanced`, or `accurate`). You can combine them independently — for example, `mode="fast"` with `extraction_mode="balanced"`.

  Set `ExtractOptions(extraction_mode="balanced")` or `extraction_mode="accurate"` in the SDK. Its parse `mode` defaults to `"fast"`, so set `mode="accurate"` explicitly to match the REST default for these extraction modes. When extraction mode is omitted, the team's configured default applies.
</Note>

## Response Format

For a scalar property in an object, balanced and accurate modes return three sibling keys. The `_citations` sibling is the same format as fast mode for compatibility — balanced mode adds `_meta` with richer metadata on top:

```json theme={null}
{
  "company_name": "Whitbread PLC",
  "company_name_citations": ["/page/0/Text/3", "/page/2/Table/1"],
  "company_name_meta": {
    "extraction_status": "EXTRACTED",
    "reasoning": "The company name 'Whitbread PLC' appears in the document header on the cover page (/page/0/Text/3) and is confirmed in the directors' report (/page/2/Table/1).",
    "citations": ["/page/0/Text/3", "/page/2/Table/1"],
    "verification": {
      "status": "PASS",
      "feedback": "The company name 'Whitbread PLC' is printed on the cover page (/page/0/Text/3) and confirmed in the directors' report. No conflicting name appears in the document."
    }
  }
}
```

The `_citations` key is shared with fast mode — if you switch between modes, citation-consuming code continues to work. The `_meta` key is available in balanced and accurate modes and contains the full audit trail.

### Field Metadata

Scalar-field `_meta` objects contain:

| Field | Description |
| - | - |
| `extraction_status` | How the value was produced: `EXTRACTED` (value found in the document) or `NOT_RESOLVABLE` (document doesn't contain this information) |
| `reasoning` | Audit-ready prose explaining how the value was produced, with block ID citations |
| `citations` | Block IDs from the source document that support the value |
| `verification` | Independent verification result with `status` and `feedback`, when available. Missing verification does not mean the value passed. |

### Nested Objects and Arrays

* Nested objects keep metadata beside their scalar properties; the parent object does not automatically have its own `_meta`.
* Arrays of objects keep each item's field metadata inside that item. A separate array `_meta.verification` can describe list completeness.
* Arrays of scalar values can have aggregate `_citations`, per-item metadata in `_meta.items`, and list-level `_meta.verification`.

Check both item-level results and list completeness. A list-level `PASS` alone does not establish that every field in every item passed.

### Extraction Status

| Status | Meaning | Value |
| - | - | - |
| `EXTRACTED` | The value was found in or derived from the document | The extracted value |
| `NOT_RESOLVABLE` | The document does not contain or imply this value | `null` |

### Verification Status

| Status | Meaning |
| - | - |
| `PASS` | The value and citations were independently confirmed against the source document |
| `PENDING` | Verification has not reached a conclusion; treat as needing review |
| `FAIL_UNRESOLVABLE` | The document does not support a value for this field |
| `FAIL_FIX` | The value was flagged as incorrect during verification — the document supports a different value |
| `FAIL_CITATIONS` | The value is correct but the citations are wrong or insufficient |
| `ITEMS_MISSING` | (List fields only) The document contains entries that are not present in the extraction |

A status other than `PASS`, or missing verification metadata, needs review before using the value in a workflow that requires verification.

## Building Workflows with Verification Metadata

The example below checks the flat scalar schema from Quick Start. For nested objects and arrays, also traverse their field metadata and check list completeness before approving the document.

```python theme={null}
import json

extracted = json.loads(result.extraction_schema_json)

# Separate fields by verification status
auto_approved = []
needs_review = []

# Check every requested field, including fields with missing metadata.
for field_name in schema["properties"]:
    meta = extracted.get(f"{field_name}_meta") or {}
    verification = meta.get("verification") or {}

    if (
        field_name in extracted
        and meta.get("extraction_status") == "EXTRACTED"
        and verification.get("status") == "PASS"
    ):
        auto_approved.append(field_name)
    else:
        needs_review.append({
            "field": field_name,
            "extraction_status": meta.get("extraction_status"),
            "reasoning": meta.get("reasoning") or "No reasoning returned",
            "verification_feedback": verification.get("feedback"),
        })

print(f"Auto-approved: {len(auto_approved)} fields")
print(f"Needs review: {len(needs_review)} fields")

# Route to human review queue
for item in needs_review:
    print(f"  {item['field']}: {item['extraction_status']}")
    print(f"    Reason: {item['reasoning'][:100]}...")
```

### Common Workflow Patterns

* **Apply your approval policy** only after checking every requested field and any list-level verification; a model verification result is not a guarantee of correctness
* **Flag for review** when any requested field or verification result is missing, or a status is `NOT_RESOLVABLE`, `PENDING`, `ITEMS_MISSING`, or `FAIL_*`
* **Show citations** to reviewers so they can verify in seconds — each field links back to specific blocks in the document
* **Use reasoning as an audit trail** — for compliance workflows, the per-field reasoning documents exactly how each value was produced, with block-level citations back to the source document

## Next Steps

<CardGroup cols={2}>
  <Card title="Structured Extraction Overview" icon="table" href="/docs/recipes/structured-extraction/api-overview">
    Schema format, response structure, and extraction tips
  </Card>

  <Card title="Confidence Scoring" icon="chart-bar" href="/docs/recipes/structured-extraction/confidence-scoring">
    Numeric per-field confidence scores for fast extraction only
  </Card>

  <Card title="Saved Schemas" icon="bookmark" href="/docs/recipes/structured-extraction/saved-schemas">
    Save and version schemas for reuse across requests
  </Card>

  <Card title="Handling Long Documents" icon="file-lines" href="/docs/recipes/structured-extraction/handling-long-documents">
    Tips for extracting from 100+ page documents
  </Card>
</CardGroup>


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