POST /document/split
Splits a long PDF that contains multiple logical documents into its constituent parts — for example, a 60-page scan that bundles an invoice, a delivery note and an ID card. The endpoint returns one entry per detected sub-document, along with the page ranges that make it up.
Unlike the other endpoints, /document/split accepts very large PDFs — there is no 10 MB cap, so you can send the raw scanner output without pre-processing.
📷 Paste here: screenshot of the Playground → Split 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/split
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 PDF to split. PDFs work best; other supported formats are accepted but will typically produce a single segment. |
Constraints
- Allowed extensions:
.pdf,.png,.jpg,.jpeg,.tiff,.tif,.bmp,.doc,.docx. - No file-size cap — large multipage PDFs are expected.
- Rate limit: 50 requests/minute per API key.
Response
200 OK — the envelope's data carries the split id and the list of detected sub-documents. Each entry includes the page range and a stored copy of the segment:
{
"data": {
"id": "abc12345-6789-0def-1234-56789abcdef0",
"metadata": {
"segments": [
{
"index": 0,
"documentType": "Invoice",
"pageFrom": 1,
"pageTo": 3,
"fileUrl": "https://storage.googleapis.com/.../segment-0.pdf"
},
{
"index": 1,
"documentType": "Delivery Note",
"pageFrom": 4,
"pageTo": 6,
"fileUrl": "https://storage.googleapis.com/.../segment-1.pdf"
},
{
"index": 2,
"documentType": "Identity Document",
"pageFrom": 7,
"pageTo": 7,
"fileUrl": "https://storage.googleapis.com/.../segment-2.pdf"
}
]
},
"createdDate": "2026-05-19T14:02:55Z"
},
"meta": { "httpStatusCode": 200, "messages": [] },
"hasErrors": false
}
If you receive
200 OKbutmetadatadoes not contain any images/segments, the underlying model probably returned the wrong response shape — try again or switch the configured AI model in the platform. This is a known sensitivity of the split feature.
Example — curl
curl -X POST "https://api-dev.xtrakt.ai/document/split" \
-H "Authorization: Bearer xtkt_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-F "file=@./batch-scan.pdf"
Example — Python
import requests
API_KEY = "xtkt_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
BASE_URL = "https://api-dev.xtrakt.ai"
with open("batch-scan.pdf", "rb") as fp:
response = requests.post(
f"{BASE_URL}/document/split",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"file": ("batch-scan.pdf", fp, "application/pdf")},
timeout=300,
)
response.raise_for_status()
for seg in response.json()["data"]["metadata"]["segments"]:
print(seg["index"], seg["documentType"], seg["pageFrom"], "-", seg["pageTo"])
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("./batch-scan.pdf")]), "batch-scan.pdf");
const response = await fetch(`${BASE_URL}/document/split`, {
method: "POST",
headers: { Authorization: `Bearer ${API_KEY}` },
body: form,
});
const { data } = await response.json();
console.table(data.metadata.segments);
Errors
| HTTP status | Reason |
|---|---|
400 Bad Request | Missing file, empty file, or disallowed extension. |
401 Unauthorized | Missing/invalid/revoked API key. |
403 Forbidden | Tenant has no active subscription for the split capability. |
429 Too Many Requests | API key exceeded the 50 req/min limit. |