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
/api/documents/uploadcurl -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.0 – 1.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
- Upload & process → — every form-field documented
- Document types → — the canonical type registry
- Templates → — define your own schemas
- Webhooks →