POST /document/extraction
Extracts structured fields from a single document, using the templates configured for your tenant. The platform automatically picks the best template for the uploaded document; you can also bias the prompt by sending a ComplementaryPrompt to nudge the model toward extra fields or specific phrasing.
📷 Paste here: screenshot of the Template editor on the platform, so the reader understands where the schemas being extracted come from.
Endpoint
POST https://api-dev.xtrakt.ai/document/extraction
Authentication
Send your API key as a Bearer token. See Getting Started for how to generate one.
Authorization: Bearer xtkt_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Request
Content-Type: multipart/form-data
| Field | Type | Required | Description |
|---|---|---|---|
file | file | ✅ | The document to extract from. |
ComplementaryPrompt | string | ❌ | Free-text instruction appended to the model prompt. Use it to ask for extra fields, enforce formatting, or narrow the scope. |
Constraints
- Allowed extensions:
.pdf,.png,.jpg,.jpeg,.tiff,.tif,.bmp,.doc,.docx. - Max size: 10 MB.
- Rate limit: 50 requests/minute per API key.
Response
200 OK — the envelope's data carries a unique extraction id and a free-form metadata payload whose shape is defined by the template that ran:
{
"data": {
"id": "9d8a7c6e-1b2f-4a3d-9e8f-7c6d5b4a3210",
"metadata": {
"documentType": "Invoice",
"fields": {
"supplier": "Acme Industries",
"invoiceNumber": "INV-2026-00123",
"issueDate": "2026-05-12",
"total": 1542.30,
"currency": "USD",
"lineItems": [
{ "description": "Widget A", "qty": 4, "unitPrice": 250.00 },
{ "description": "Service fee", "qty": 1, "unitPrice": 542.30 }
]
}
},
"createdDate": "2026-05-19T13:42:11Z"
},
"meta": { "httpStatusCode": 200, "messages": [] },
"hasErrors": false
}
The exact
metadata.fieldsshape depends entirely on the template that matched. Templates are managed in the platform — change the schema there and this endpoint returns the new shape on the next call.
Example — curl
curl -X POST "https://api-dev.xtrakt.ai/document/extraction" \
-H "Authorization: Bearer xtkt_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-F "file=@./invoice.pdf" \
-F "ComplementaryPrompt=Also extract the buyer's tax id if present."
Example — Python
import requests
API_KEY = "xtkt_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
BASE_URL = "https://api-dev.xtrakt.ai"
with open("invoice.pdf", "rb") as fp:
response = requests.post(
f"{BASE_URL}/document/extraction",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"file": ("invoice.pdf", fp, "application/pdf")},
data={"ComplementaryPrompt": "Also extract the buyer's tax id if present."},
)
response.raise_for_status()
print(response.json()["data"]["metadata"])
Example — Node.js
import fs from "node:fs";
const API_KEY = "xtkt_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const BASE_URL = "https://api-dev.xtrakt.ai";
const form = new FormData();
form.append("file", new Blob([fs.readFileSync("./invoice.pdf")]), "invoice.pdf");
form.append("ComplementaryPrompt", "Also extract the buyer's tax id if present.");
const response = await fetch(`${BASE_URL}/document/extraction`, {
method: "POST",
headers: { Authorization: `Bearer ${API_KEY}` },
body: form,
});
const { data } = await response.json();
console.log(data.metadata);
Errors
| HTTP status | Reason |
|---|---|
400 Bad Request | Missing file, empty file, disallowed extension, or file over 10 MB. |
401 Unauthorized | Missing/invalid/revoked API key. |
403 Forbidden | Tenant has no active subscription for extraction. |
422 Unprocessable Entity | No template matched the document — set up a matching template in the platform before retrying. |
429 Too Many Requests | API key exceeded the 50 req/min limit. |