POST /document/zero-shot
Runs zero-shot field discovery against a single document — the model inspects the file and proposes the fields it finds, with no prior template required. Use it when you are bootstrapping a new template, exploring an unknown document family, or validating what the AI is able to pick up before formalizing a schema.
📷 Paste here: screenshot of the Playground → Zero-shot screen on the platform, so the reader can compare the API output with the UI output side by side.
Endpoint
POST https://api-dev.xtrakt.ai/document/zero-shot
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 analyze. |
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 — data contains the discovery id plus a metadata payload listing the fields the model detected:
{
"data": {
"id": "f2c1a3e4-7b8d-4c9e-9012-34567890abcd",
"metadata": {
"discoveredFields": [
{ "name": "supplier", "value": "Acme Industries", "confidence": 0.96 },
{ "name": "invoiceNumber", "value": "INV-2026-00123", "confidence": 0.94 },
{ "name": "issueDate", "value": "2026-05-12", "confidence": 0.92 },
{ "name": "total", "value": "1542.30", "confidence": 0.89 }
]
},
"createdDate": "2026-05-19T13:48:02Z"
},
"meta": { "httpStatusCode": 200, "messages": [] },
"hasErrors": false
}
The exact list of discovered fields depends entirely on the document's content. There is no guarantee of which fields will appear from one call to the next.
Example — curl
curl -X POST "https://api-dev.xtrakt.ai/document/zero-shot" \
-H "Authorization: Bearer xtkt_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-F "file=@./unknown-document.pdf"
Example — Python
import requests
API_KEY = "xtkt_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
BASE_URL = "https://api-dev.xtrakt.ai"
with open("unknown-document.pdf", "rb") as fp:
response = requests.post(
f"{BASE_URL}/document/zero-shot",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"file": ("unknown-document.pdf", fp, "application/pdf")},
)
response.raise_for_status()
print(response.json()["data"]["metadata"]["discoveredFields"])
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("./unknown-document.pdf")]), "unknown-document.pdf");
const response = await fetch(`${BASE_URL}/document/zero-shot`, {
method: "POST",
headers: { Authorization: `Bearer ${API_KEY}` },
body: form,
});
const { data } = await response.json();
console.log(data.metadata.discoveredFields);
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 the zero-shot capability. |
429 Too Many Requests | API key exceeded the 50 req/min limit. |