Extract structured data from documents using AI.
Zendix helps developers extract structured JSON data from invoices, receipts, purchase orders, PDFs, images, forms, and other business documents using AI extraction jobs.
Create a schema
Define your JSON schema that matches Zendix schema structure, or create a schema in the Zendix dashboard and then copy the generated JSON into your API request.
Send files or text
Upload files, send text content, or combine both in a single extraction request.
Receive structured JSON
Zendix processes the job synchronously and returns the structured extraction results immediately.
How Zendix works
Zendix uses synchronous extraction jobs. When you create a job, Zendix immediately starts to process it and sends the results back to the client in a JSON response.
| Job Status | Description |
|---|---|
successful |
The extraction completed successfully and results are available. |
failed |
The extraction failed and an error message is available. |
Your first request
The example below uploads an invoice PDF and creates a new extraction job using a JSON schema.
import requests
import json
url = "https://api.zendix.app/v1/jobs/s/create/"
headers = {
"Authorization": "Bearer YOUR_API_KEY"
}
files = [
("files", open("invoice.pdf", "rb"))
]
payload = {
"body": "",
"schema": json.dumps({
"invoice_number": "string",
"invoice_date": "string",
"total": "float"
}),
"document_type": "invoice"
}
response = requests.post(url, headers=headers, files=files, data=payload)
print(response.json())
const formData = new FormData();
formData.append("body", "");
formData.append("schema", JSON.stringify({
"invoice_number": "string",
"invoice_date": "string",
"total": "float"
})
);
formData.append("document_type", "invoice");
formData.append("files", fileInput.files[0]);
const response = await fetch("https://api.zendix.app/v1/jobs/s/create/", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY"
},
body: formData
});
const data = await response.json();
console.log(data);
curl -X POST https://api.zendix.app/v1/jobs/s/create/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "body=" \
-F 'schema={"invoice_number": "string", "invoice_date": "string", "total": "float"}' \
-F "document_type=invoice" \
-F "files=@invoice.pdf"
{
"success": true,
"data": {
"status": "successful",
"result": {
"invoice_number": "INV-2026-001",
"invoice_date": "May 12, 2026",
"total": 1381.38,
"fail reason": ""
},
"error": null,
"details": {
"body": "",
"document_type": "invoice",
"schema": {
"invoice_number": "string",
"invoice_date": "string",
"total": "float"
},
"file_count": 1,
"created_at": "2026-08-15T14:59:53.663789Z"
}
},
"meta": {
"job_id": 90
}
}
Authentication
All Zendix API requests must include your API key in the Authorization header.
Your API keys should be kept secret and secure. Never expose them in frontend applications, public repositories, or client-side code.
Include it in requests
Send the API key in the Authorization header using the Bearer format.
response = requests.get(url, headers = {
"Authorization": "Bearer YOUR_API_KEY"
})
const response = await fetch(url, {
headers: {
Authorization: "Bearer YOUR_API_KEY"
}
});
curl url \
-H "Authorization: Bearer YOUR_API_KEY"
Authentication errors
Zendix returns standardized error responses when authentication fails.
{
"success": false,
"error": {
"code": "authentication_failed",
"message": "Invalid API key."
},
"meta": null
}
Create job
Create an extraction job by sending files, text content, or both. Zendix processes the job synchronously and returns a JSON response immediately.
Custom Extraction Jobs
Create an extraction job that extracts specific fields from your documents as defined by your schema.
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
schema |
JSON | yes | JSON schema used for extraction. Must match Zendix schema structure. |
document_type |
string | yes | The type of document being processed (e.g invoice, receipt, form). |
files |
File[] | optional | Uploaded documents. Max 10 files. Supported formats: pdf, png, jpg, jpeg, webp, txt. |
body |
string | optional | Raw text content to extract data from. |
You must provide either files, body, or both.
Supported combinations
| Files | Body | Valid |
|---|---|---|
| ✔ | ✖ | Yes |
| ✖ | ✔ | Yes |
| ✔ | ✔ | Yes |
| ✖ | ✖ | No |
Limits
- Maximum files: 10
- Maximum total upload size: 5MB
- Supported file formats: pdf, png, jpg, jpeg, webp, txt
import requests
import json
url = "https://api.zendix.app/v1/jobs/s/create/"
headers = {
"Authorization": "Bearer YOUR_API_KEY"
}
files = [
("files", open("invoice.pdf", "rb"))
]
payload = {
"body": "",
"schema": json.dumps({
"invoice_number": "string",
"invoice_date": "string",
"total": "float"
}),
"document_type": "invoice"
}
response = requests.post(url, headers=headers, files=files, data=payload)
print(response.json())
const formData = new FormData();
formData.append("body", "");
formData.append("schema", JSON.stringify({
"invoice_number": "string",
"invoice_date": "string",
"total": "float"
})
);
formData.append("document_type", "invoice");
formData.append("files", fileInput.files[0]);
const response = await fetch("https://api.zendix.app/v1/jobs/s/create/", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY"
},
body: formData
});
const data = await response.json();
console.log(data);
curl -X POST https://api.zendix.app/v1/jobs/s/create/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "body=" \
-F 'schema={"invoice_number": "string", "invoice_date": "string", "total": "float"}' \
-F "document_type=invoice" \
-F "files=@invoice.pdf"
{
"success": true,
"data": {
"status": "successful",
"result": {
"invoice_number": "INV-2026-001",
"invoice_date": "May 12, 2026",
"total": 1381.38,
"fail reason": ""
},
"error": null,
"details": {
"body": "",
"document_type": "invoice",
"schema": {
"invoice_number": "string",
"invoice_date": "string",
"total": "float"
},
"file_count": 1,
"created_at": "2026-08-15T14:59:53.663789Z"
}
},
"meta": {
"job_id": 90
}
}
Automatic Extraction Jobs
Create an extraction job that automatically identifies and extracts the data from your documents without needing a schema.
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
files |
File[] | optional | Uploaded documents. Max 10 files. Supported formats: pdf, png, jpg, jpeg, webp, txt. |
body |
string | optional | Raw text content to extract data from. |
You must provide either files, body, or both.
Supported combinations
| Files | Body | Valid |
|---|---|---|
| ✔ | ✖ | Yes |
| ✖ | ✔ | Yes |
| ✔ | ✔ | Yes |
| ✖ | ✖ | No |
Limits
- Maximum files: 10
- Maximum total upload size: 5MB
- Supported file formats: pdf, png, jpg, jpeg, webp, txt
import requests
import json
url = "https://api.zendix.app/v1/jobs/s/a/create/"
headers = {
"Authorization": "Bearer YOUR_API_KEY"
}
files = [
("files", open("invoice.pdf", "rb"))
]
payload = {
"body": ""
}
response = requests.post(url, headers=headers, files=files, data=payload)
print(response.json())
const formData = new FormData();
formData.append("body", "");
formData.append("files", fileInput.files[0]);
const response = await fetch("https://api.zendix.app/v1/jobs/s/a/create/", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY"
},
body: formData
});
const data = await response.json();
console.log(data);
curl -X POST https://api.zendix.app/v1/jobs/s/a/create/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "body=" \
-F "files=@invoice.pdf"
{
"success": true,
"data": {
"status": "successful",
"result": {
"invoice_number": "INV-2026-001",
"invoice_date": "May 12, 2026",
"total": 1381.38,
"fail reason": ""
},
"error": null,
"details": {
"body": "",
"document_type": null,
"schema": null,
"file_count": 1,
"created_at": "2026-08-15T14:59:53.663789Z"
}
},
"meta": {
"job_id": 90
}
}
Rate limiting
Zendix enforces rate limits to ensure fair usage and system stability.
Rate limits are applied per API key.
| Type | Rate Limit | Window |
|---|---|---|
| API key | 100 requests | per minute |
All API keys can each make a maximum of 100 requests per minute.
File limits
Zendix enforces strict file upload limits to ensure performance and reliability.
| Limit | Value |
|---|---|
| Maximum files | 10 files |
| Total upload size | 5MB |
| Supported formats | pdf, png, jpg, jpeg, webp, txt |
Error codes
All errors follow a standardized structure to make debugging simple and predictable.
{
"success": false,
"error": {
"code": "error_code",
"message": "Human readable message"
},
"meta": null
}
Common error codes
| Code | Meaning |
|---|---|
validation_error |
Invalid request data |
method_not_allowed |
Request method not allowed |
rate_limit_exceeded |
Too many requests |
authentication_failed |
Invalid API key |
parse_error |
Invalid form data |
file_storage_limit_exceeded |
Insufficient file storage |
file_not_stored |
A file in request files failed to upload |