Document extraction API quickstart
The docRefinery document extraction API takes a PDF or image and returns structured fields with confidence scores. It works in two calls: submit the file, which gives you a trace_id, then poll that trace_id until the run finishes. You need an API key and at least one document type chosen; requests go to https://api.docrefinery.com.
Updated
Before you start
Three things have to be in place before the first request. The second is not self-serve yet, so ask for it first.
- A docRefinery account. Sign up if you don't have one.
- API keys switched on for your account. docRefinery turns them on per account, separately from your plan, so contact us to ask. Until then, Settings has no API keys tab.
- Your document types chosen in the dashboard under Schemas & thresholds. You don't send a field list with each request: the API reads the fields your account has set for that type of document.
Create an API key
Open Settings, then API keys, and choose Create key. Give it a name and an expiry. The secret starts with dbk_live_ and is shown once, so copy it before you close the dialog. Organisation owners and admins can create keys; authentication has the details.
export DOCREFINERY_API="https://api.docrefinery.com"
export DOCREFINERY_API_KEY="dbk_live_your_secret"Submit a document
Send the file as multipart form data in a part called file, with your key as a bearer token. The response comes back as soon as the document is queued, and the value you need from it is trace_id.
curl -X POST "$DOCREFINERY_API/v1/runway/async" \
-H "Authorization: Bearer $DOCREFINERY_API_KEY" \
-F "[email protected]"{
"trace_id": "9f1c0a7e",
"status": "queued",
"wait_time_ms": 1800,
"estimated_execution_time_utc": "2026-11-04T10:31:04Z"
}Poll for the result
There are no webhooks, so you ask until the run settles. Call the poll endpoint every 2 seconds, which is the interval our own dashboard uses, and stop when status is fulfilled or completed (the result is ready), failed or error (it stopped), or awaiting_review (a person has to look at it first). Anything else means keep polling.
curl "$DOCREFINERY_API/v1/runway/9f1c0a7e" \
-H "Authorization: Bearer $DOCREFINERY_API_KEY"{
"status": "fulfilled",
"files": ["invoice.pdf"],
"document_type": "invoice",
"document_confidence": 0.97,
"result": {
"fields": [
{ "text": "INV-2291", "alias": "invoice_number", "field_confidence": 0.97 }
],
"extraction_approval": "auto",
"low_confidence_fields": []
}
}This is an excerpt: real responses carry other keys. Build only on the keys described in these docs. Extract a document explains each one, including tables and flagged fields.
Field names and result shape
alias is a name you control. Each field has a Return as alias, set in the dashboard under Schemas & thresholds, and it comes back as the alias on that value. In the excerpt above, invoice_number is that name. Changing it relabels the value and leaves what is extracted alone.
The result shape is identical across document types: fields carry text, alias and field_confidence, and tables carry rows of the same cells. Code that reads an invoice also reads a bank statement or a passport. Return as has the rules and an excerpt.
The whole flow in Python
This script submits a file, polls until the run settles and prints what came back. It uses the requests library: docRefinery has no official SDK. The values are illustrative, and you should add your own error handling and an overall timeout.
import os
import time
import requests
API = os.environ["DOCREFINERY_API"]
HEADERS = {"Authorization": f"Bearer {os.environ['DOCREFINERY_API_KEY']}"}
SETTLED = {"fulfilled", "completed", "failed", "error", "awaiting_review"}
with open("invoice.pdf", "rb") as document:
submitted = requests.post(
f"{API}/v1/runway/async",
headers=HEADERS,
files={"file": document},
timeout=120,
)
submitted.raise_for_status()
trace_id = submitted.json()["trace_id"]
while True:
poll = requests.get(f"{API}/v1/runway/{trace_id}", headers=HEADERS, timeout=30)
poll.raise_for_status()
run = poll.json()
if run["status"] in SETTLED:
break
time.sleep(2)
print(run["status"])
print((run.get("result") or {}).get("fields"))The whole flow in JavaScript
The same flow for Node.js 20 or later, using the built-in fetch. Run it from your server, never from a web page: a browser would expose your key, and the API doesn't accept browser requests from other sites.
import { openAsBlob } from "node:fs";
const API = process.env.DOCREFINERY_API;
const headers = { Authorization: "Bearer " + process.env.DOCREFINERY_API_KEY };
const SETTLED = ["fulfilled", "completed", "failed", "error", "awaiting_review"];
const form = new FormData();
form.append("file", await openAsBlob("invoice.pdf"), "invoice.pdf");
const submitted = await fetch(API + "/v1/runway/async", {
method: "POST",
headers,
body: form,
});
if (!submitted.ok) throw new Error("Submit failed: " + submitted.status);
const { trace_id } = await submitted.json();
let run;
do {
await new Promise((resolve) => setTimeout(resolve, 2000));
const poll = await fetch(API + "/v1/runway/" + trace_id, { headers });
if (!poll.ok) throw new Error("Poll failed: " + poll.status);
run = await poll.json();
} while (!SETTLED.includes(run.status));
console.log(run.status);
console.log(run.result?.fields);What to read next
- Authentication: who can create keys, expiry, revoking and activity.
- Extract a document: every submit option and how to read fields, tables and flags.
- Errors and limits: error shapes, the page quota, rate limits and the 100 MB upload limit.
Common questions
Is the docRefinery extraction API synchronous?
No. Submitting a document returns a trace_id straight away, and you poll for the result. There are no webhooks or websockets, so your code asks until the run settles. Polling every 2 seconds matches what the docRefinery dashboard does.
Do I send the list of fields with each request?
No. docRefinery has no per-request field list. Fields are set once per document type in the dashboard under Schemas & thresholds, including each field's Return as alias, so every system that uses your account gets the same fields back under the same names.
Is there an official docRefinery SDK?
No. The API is plain HTTPS with multipart uploads and JSON responses, so curl, the Python requests library or the fetch built into Node.js are all you need.
Related
- IntegrationsConnect docRefinery to your systems: REST API keys, workflows from one sample document, a Chrome extension, JSON, CSV and XLSX export, and on-premises options.
- AuthenticationAuthenticate with the docRefinery document extraction API: bearer API keys, who can create them, expiry, revoking, activity logs and what a key can reach.
- Extract a documentExtract data from an invoice with the docRefinery API: submit with curl, Python or JavaScript, poll the run, then read fields, tables and low-confidence flags.
- Errors and limitsdocRefinery API errors and limits: error shapes, status codes, the monthly page quota, submissions per minute, the 100 MB upload limit and when to retry.
- InvoiceExtract data from invoice PDFs and scans: 62 fields including line items and VAT, as JSON with confidence scores and page and box citations on values.
- PricingStarter is free for 100 pages a month, no card needed. Paid plans are custom: subscription or per page. Enterprise adds VPC or on-premises.
Send your first document.
Make a free account and try the API on a file of your own.
100 pages a month free. No credit card, no sales call.