Batch API¶
The batch API accepts an array of messages and returns a job ID immediately. Processing happens asynchronously in the background. Poll the job endpoint for status, or receive a webhook when the job completes.
Designed for offline document processing pipelines: bulk contract review, nightly data exports, training data generation, report anonymization.
Submit a Batch¶
{
"messages": [
{ "role": "user", "content": "Review the NDA signed by Michael Chen..." },
{ "role": "user", "content": "Summarize the patient record for Sarah Williams..." }
],
"model": "claude-sonnet-4-6",
"webhook_url": "https://your-server.com/batch-done"
}
| Field | Type | Required | Description |
|---|---|---|---|
messages |
array | Yes | Up to 500 {role, content} objects. Each is processed independently. |
model |
string | No | Model to use. Default: claude-sonnet-4-6. |
webhook_url |
string | No | Called with a batch.completed event when all messages finish. |
Response (202 Accepted):
{
"ok": true,
"job_id": "a1b2c3d4e5f6...",
"status": "pending",
"total_messages": 2,
"poll_url": "/redact/v1/batch/a1b2c3d4e5f6..."
}
The request returns immediately. The job starts processing in the background.
Poll Job Status¶
Response while processing:
{
"ok": true,
"job": {
"id": "a1b2c3d4e5f6...",
"status": "processing",
"total_messages": 2,
"processed_count": 1,
"results": null,
"created_at": "2026-05-22T10:00:00",
"completed_at": null
}
}
Response when complete:
{
"ok": true,
"job": {
"id": "a1b2c3d4e5f6...",
"status": "completed",
"total_messages": 2,
"processed_count": 2,
"results": [
{
"index": 0,
"content": "Review the NDA signed by Finley Warren...",
"entities_stripped": 3,
"doc_class": "legal"
},
{
"index": 1,
"content": "Summarize the patient record for Riley Carter...",
"entities_stripped": 2,
"doc_class": "healthcare"
}
],
"created_at": "2026-05-22T10:00:00",
"completed_at": "2026-05-22T10:00:45"
}
}
| Status | Meaning |
|---|---|
pending |
Queued, not yet started |
processing |
Running, check processed_count for progress |
completed |
All messages done, results populated |
failed |
Fatal error, check error field |
Webhook Notification¶
If webhook_url is set, Redact fires a batch.completed POST when the job finishes:
{
"event": "batch.completed",
"job_id": "a1b2c3d4e5f6...",
"workspace_id": "wks_...",
"total_messages": 2,
"timestamp": "2026-05-22T10:00:45"
}
Fetch the job results from the poll endpoint after receiving this notification.
Python Example¶
import time
import openai
# Submit batch
import requests
resp = requests.post(
"https://www.xybern.com/redact/v1/batch",
headers={"Authorization": "Bearer xr_live_YOUR_KEY"},
json={
"messages": [
{"role": "user", "content": doc}
for doc in documents # list of strings
],
"model": "claude-sonnet-4-6",
},
)
job = resp.json()
job_id = job["job_id"]
# Poll until done
while True:
status = requests.get(
f"https://www.xybern.com/redact/v1/batch/{job_id}",
headers={"Authorization": "Bearer xr_live_YOUR_KEY"},
).json()["job"]
if status["status"] == "completed":
for result in status["results"]:
print(f"Message {result['index']}: {result['content'][:80]}...")
break
elif status["status"] == "failed":
print("Batch failed:", status.get("error"))
break
time.sleep(5)
Limits¶
| Limit | Value |
|---|---|
| Messages per batch | 500 |
Message content length |
No hard limit (upstream model limits apply) |
| Concurrent jobs | Unlimited (background threads) |
| Job retention | Stored indefinitely in the dashboard |
Auto document class detection
Each message in a batch is independently scanned for document class keywords. The doc_class field in each result tells you what was inferred. No need to tag individual messages.