📘 Public beta · Endpoints are stable; OpenAPI specs and SDKs ship monthly. See changelog →
Products
Document Intelligence
Quickstart

Document Intelligence · Quickstart

Upload an NPWP, get back structured fields.

Time: ~5 minutes.

Prerequisites

Sandbox API key with scopes: documents:write, documents:read, webhooks:manage.

1. Upload

POST/api/documents/upload
Auth · API keyScope · documents:write
curl -X POST https://sandbox.quantumelixir.tech/document-intelligence/api/documents/upload \
  -H "Authorization: Bearer $QE_API_KEY" \
  -F "file=@./npwp-sample.pdf" \
  -F "type=npwp" \
  -F "externalRef=loan-app-2026-05-24-001"

Response (201):

{
  "data": {
    "document": {
      "id": "doc_01HXY...",
      "type": "npwp",
      "status": "queued",
      "filename": "npwp-sample.pdf",
      "sizeBytes": 184392,
      "sha256": "...",
      "externalRef": "loan-app-2026-05-24-001",
      "createdAt": "..."
    },
    "deduped": false
  }
}

The processing pipeline (classify if no type hint → extract → validate) runs async. Don't wait inline — subscribe to webhooks or poll.

2. Wait for completion (poll)

curl https://sandbox.quantumelixir.tech/document-intelligence/api/documents/doc_01HXY... \
  -H "Authorization: Bearer $QE_API_KEY"

status progresses: queued → parsing → extracted (or requires_review if low-confidence, failed if hard error).

3. Read extractions

curl .../api/documents/doc_01HXY.../extractions \
  -H "Authorization: Bearer $QE_API_KEY"
{
  "data": [
    {
      "id": "ext_01HXY...",
      "documentId": "doc_01HXY...",
      "method": "quantum_ai_vision",
      "modelUsed": "quantum-ai:v1",
      "confidenceScore": 94,
      "fields": {
        "npwp_number": "12.345.678.9-012.000",
        "name": "BUDI SANTOSO",
        "address": "JL. SUDIRMAN KAV. 1, JAKARTA SELATAN",
        "registered_at": "2018-04-15"
      },
      "fieldBoundingBoxes": {
        "npwp_number": { "page": 0, "x": 0.34, "y": 0.21, "w": 0.32, "h": 0.04 }
      },
      "flags": [],
      "createdAt": "..."
    }
  ]
}

Bounding boxes are normalized (0.01.0) relative to the document page. Multiply by page width/height to get pixel coords.

4. (Recommended) Subscribe to webhooks

Polling is fine for the quickstart. In production, register a webhook:

curl -X POST .../api/webhooks \
  -H "Authorization: Bearer $QE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.example.com/webhooks/quantum-di",
    "events": ["document.extracted", "document.requires_review", "document.failed"]
  }'

Now whenever processing finishes, you get a POST with the full extraction in the body.

Pass the type hint when you know it

Passing type=npwp lets us skip the classify step and go straight to extract. Lower latency and slightly higher confidence than letting the model auto-classify. Only omit type when you genuinely don't know what the file contains.

Next steps