DocAI API Documentation
DocAI provides a REST API for extracting structured data from uploaded documents or normalized inbound-email attachments. Persistent jobs, human approval, signed webhooks, and accounting exports support automation workflows in Make, n8n, Zapier, or custom integrations.
Authentication
Create and manage API keys in the Developer Settings page. Send the key as a bearer token; scopes and the key's monthly page quota are enforced on every request.
Authorization: Bearer sk_docai_<your_key>
API keys start with sk_docai_. Keep them secret. They are shown only once at creation.
Use the extract scope to submit and monitor jobs. Add the history scope to fetch saved results and accounting exports. These are the only supported API-key scopes.
Rate Limits
Analysis usage is governed by your plan's page allowance and storage quota. There is no separate per-request or per-day cap.
API keys additionally meter OCR pages against the key's monthly page quota.
Requests that run out of pages or storage return HTTP 402; an API key over its monthly page quota returns HTTP 429 with a Retry-After hint.
Error Format
{
"detail": "File too large. Maximum upload size is 15 MB.",
"request_id": "abc123"
}
Sync Document Extraction
POST/api/v1/analyze
Upload a document and get extraction results synchronously. Best for small documents (< 2 pages).
Request
Multipart form data:
| Field | Type | Description | |
|---|---|---|---|
file | file | required | PDF, PNG, JPG, HEIC, AVIF, TIFF, BMP, or WEBP (max 15MB) |
filename | string | optional | Override the displayed filename |
Example
curl -X POST https://docai.synairo.com/api/v1/analyze \ -H "Authorization: Bearer sk_docai_..." \ -F "file=@purchase_order.pdf"
Response
{
"request_id": "3fa8...",
"filename": "purchase_order.pdf",
"document_type": "purchase_order",
"document_type_confidence": 0.94,
"summary": "Purchase order from Acme Corp to Widget Co.",
"language": "en",
"extracted_fields": [
{
"field": "po_number",
"value": "PO-2026-0042",
"confidence": 0.97,
"page": 1,
"evidence": "PO-2026-0042"
}
],
"warnings": [],
"ocr": { "pages": 1, "tokens": 312, "language": "eng+pol" },
"llm": { "status": "success", "provider": "openai", "model": "gpt-4o-mini" }
}
Streaming Extraction (SSE)
POST/api/v1/analyze/stream
Same as sync, but streams Server-Sent Events showing processing progress. Best for real-time UIs.
Create Async Job
POST/api/v1/jobs
Upload a document and get a job ID. Process happens in the background.
curl -X POST https://docai.synairo.com/api/v1/jobs \ -H "Authorization: Bearer sk_docai_..." \ -F "file=@invoice.pdf"
{ "job_id": "abc123", "status": "queued", "request_id": "xyz..." }
Ingest Email Attachments
POST/api/v1/ingest/email
Provider-neutral inbound-email bridge. Postmark, Mailgun, SendGrid, Amazon SES, Make, n8n, or another adapter must parse the provider payload and send accepted attachments as multipart form data. DocAI does not host a mailbox or perform provider-specific MIME parsing.
| Field | Type | Description | |
|---|---|---|---|
message_id | string | required | Stable message identifier from the provider |
source_namespace | string | required | Stable provider/account scope, such as postmark:server-123 |
files | file[] | required | Repeat for every supported attachment |
organization_id | string | optional | Target workspace; the caller must have upload permission |
curl -X POST https://docai.synairo.com/api/v1/ingest/email \ -H "Authorization: Bearer sk_docai_..." \ -F "message_id=provider-message-42" \ -F "source_namespace=postmark:server-123" \ -F "organization_id=org_..." \ -F "files=@invoice.pdf;type=application/pdf" \ -F "files=@receipt.jpg;type=image/jpeg"
{
"message_id": "provider-message-42",
"source_namespace": "postmark:server-123",
"accepted_count": 1,
"duplicate_count": 1,
"jobs": [
{"job_id": "job-new", "status": "queued", "filename": "invoice.pdf", "duplicate": false},
{"job_id": "job-old", "status": "completed", "filename": "receipt.jpg", "duplicate": true}
]
}
Idempotency includes the authenticated owner, provider/account namespace, destination, message ID, normalized filename, file content, and occurrence among identical attachments. Reordered provider retries return the original job IDs. A failed ingestion can requeue the same job with fresh bytes up to three total attempts; active and completed jobs are never processed twice.
Get Job Status
GET/api/v1/jobs/{job_id}
curl https://docai.synairo.com/api/v1/jobs/abc123 \ -H "Authorization: Bearer sk_docai_..."
{
"id": "abc123",
"status": "completed",
"progress_pct": 100,
"document_type": "invoice",
"pages_processed": 2
}
Possible statuses: queued, processing, review_required, completed, failed, cancelled.
Get Job Result
GET/api/v1/jobs/{job_id}/result
Returns the full extraction result once job status is completed or review_required. Requires the history scope for API keys.
curl https://docai.synairo.com/api/v1/jobs/abc123/result \ -H "Authorization: Bearer sk_docai_..."
Export JSON
POST/api/v1/export/json
Send extraction result as JSON body, get clean export file.
curl -X POST https://docai.synairo.com/api/v1/export/json \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk_docai_..." \
-d '{"request_id":"...","extracted_fields":[...]}' \
-o export.json
Export CSV
POST/api/v1/export/csv
curl -X POST https://docai.synairo.com/api/v1/export/csv \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk_docai_..." \
-d '{"request_id":"...","extracted_fields":[...]}' \
-o fields.csv
Export XLSX
POST/api/v1/export/xlsx
Returns an Excel workbook with Summary, Fields, Line Items, Warnings, and Metadata sheets.
List History
GET/api/v1/history
curl https://docai.synairo.com/api/v1/history \ -H "Authorization: Bearer sk_docai_..."
Review and Approval Workflow
POST/api/v1/history/{record_id}/workflow
Apply a controlled workflow transition to a saved record. This route requires an interactive Clerk session: API keys cannot approve documents. Workspace members can review; workspace admins can approve, request changes, or reject. A personal-record owner performs both roles.
{
"action": "approve",
"comment": "Ready to post"
}
Actions: start_review, complete_review, reopen_review, submit_for_approval, approve, request_changes, reject, and accept_partial_analysis. Approval commits the workflow audit event and document.approved outbox event together.
Delete All History
DELETE/api/v1/history
Permanently deletes all saved analyses for your account.
List API Keys
GET/api/v1/keys
Create API Key
POST/api/v1/keys
curl -X POST https://docai.synairo.com/api/v1/keys \
-H "Authorization: Bearer <clerk_session_token>" \
-H "Content-Type: application/json" \
-d '{"name": "My automation key", "scopes": "extract,history"}'
{
"id": "...",
"name": "My automation key",
"key": "sk_docai_...", // shown ONCE - save it now
"prefix": "sk_docai_abc",
"scopes": "extract,history",
"created_at": "2026-06-10T12:00:00Z"
}
Revoke API Key
DELETE/api/v1/keys/{key_id}
Create Webhook
POST/api/v1/webhooks
curl -X POST https://docai.synairo.com/api/v1/webhooks \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"name": "My webhook", "endpoint_url": "https://my.app/hook", "event_types": ["document.completed", "document.review_required", "document.approved", "document.failed"]}'
The response includes a secret for signature verification. Save it now, it won't be shown again.
Webhook Event Types
| Event | When it fires |
|---|---|
document.completed | Extraction completed and the result was saved |
document.review_required | Validation or confidence routing requires human review; also fires with document.completed |
document.approved | An authorized approver committed the approval decision; use this for accounting writes |
document.failed | Processing failed; email-ingested jobs include retryability and attempt metadata |
document.approved, not document.completed, as the control point for posting data to an accounting system. Extraction can complete while fields still require correction.
Test Webhook
POST/api/v1/webhooks/{webhook_id}/test
Verify Webhook Signature
Every delivery includes these headers:
X-DocAI-Event: event type (e.g.,document.completed)X-DocAI-Timestamp: ISO 8601 UTC timestampX-DocAI-Signature:sha256=<hmac>
import hashlib, hmac
def verify(secret, body_str, timestamp, signature_header):
msg = f"{timestamp}.{body_str}"
digest = hmac.new(secret.encode(), msg.encode(), hashlib.sha256).hexdigest()
return hmac.compare_digest(f"sha256={digest}", signature_header)
Failed Durable Events
DocAI retries outbound deliveries automatically. If a durable outbox event cannot be expanded after five attempts, it becomes a dead letter. The owner can inspect metadata without exposing the stored payload and replay the event after correcting the cause.
GET/api/v1/webhook-outbox/failed
curl https://docai.synairo.com/api/v1/webhook-outbox/failed \ -H "Authorization: Bearer sk_docai_..."
POST/api/v1/webhook-outbox/{event_id}/replay
curl -X POST https://docai.synairo.com/api/v1/webhook-outbox/EVENT_ID/replay \ -H "Authorization: Bearer sk_docai_..."
The same controls are available under Developer Settings β Events needing attention. Delivery and terminal outbox records are retained for 30 days.
Use with Make / n8n / Zapier
For direct uploads, call /api/v1/jobs. For inbound email, let the provider parse attachments and call /api/v1/ingest/email with a stable message ID and source namespace. Both routes create the same persistent jobs and use the same review workflow.
Subscribe to completion and review events for status, then use document.approved to trigger controlled downstream accounting actions. Signed webhooks remove the need to poll.