Prompt for your coding agent
| Synchronous | Asynchronous | |
|---|---|---|
| Endpoint | POST /v1/reflex/synchronous_predict_batch | POST /v1/reflex/asynchronous_batches/upload |
| Rows per call | up to 300 | up to 10,000 |
| Results | inline, one response | upload now, poll, then fetch |
model per row | one or many | one or many (always an array) |
| Price tier | realtime rate | discounted batch rate |
| Reach for it when | a few hundred rows you need now | a large offline backlog, cost-sensitive |
id (echoed back so you can map results to your records), a model, and the text to classify. A row can name several models to run all of them over the same text at once.
Synchronous batch
| Field | Type | Required | Description |
|---|---|---|---|
requests | array | Yes | Up to 300 rows. |
requests[].id | string | Yes | Your correlation key, echoed back on each result. |
requests[].model | string / array | Yes | One model name, or an array to run several over the same text. A default Reflex (jailbreak, guardrail, …) or one you trained. |
requests[].text | string | Yes | The text to classify. |
id and carries one prediction per model on that row. A prediction mirrors the /predict response — a mode and one classes entry per label, with the winner marked "selected": true.
A row that fails validation (e.g. empty
text) comes back as { "id": ..., "error": { "type", "message" } } instead of predictions — other rows still return normally, so check for error per row. One exception: naming a model that doesn’t exist is rejected up front and fails the whole request with 404 model_not_found (no partial results), so validate model names before you batch.Asynchronous batch
For larger or cost-sensitive jobs, upload the rows and pick up results later. This is the discounted batch tier: rows queue durably, a background worker drains them, and you poll for progress. Three calls — upload, poll, fetch.model must be an array here, even for a single model (["jailbreak"]) — a bare string is rejected. It’s the one shape difference from the synchronous endpoint.Upload the batch
POST /v1/reflex/asynchronous_batches/upload. Up to 10,000 rows, each id unique, each text ≤ 350,000 characters. Returns immediately with a batch_id once the rows are queued — it does not wait for classification.| Field | Type | Required | Description |
|---|---|---|---|
requests | array | Yes | Up to 10,000 rows. |
requests[].id | string | Yes | Unique within the batch. Echoed back on each result. |
requests[].model | array | Yes | One or more model names. Always an array. |
requests[].text | string | Yes | The text to classify. ≤ 350,000 characters. |
Idempotency-Key header to make retries safe — replaying the same key returns the existing batch (with 200 instead of 201), never a duplicate.Poll for progress
GET /v1/reflex/asynchronous_batches/{batch_id}. Same shape as upload, with request_counts advancing as the worker drains the queue. status moves queued → in_progress → completed.cURL
The queue drains at a steady, throttled rate (~2 rows/sec) so batch work never competes with realtime predictions. Small batches finish in seconds; a full 10,000-row batch takes roughly 80 minutes. Poll on an interval — don’t hold a request open waiting.
Fetch results
GET /v1/reflex/asynchronous_batches/{batch_id}/results. Returns the status block plus a results array — one entry per row, keyed by your id, as inline JSON (not a file to download).cURL
completed (carries predictions, one per model), failed (carries an error), or still pending if you fetch before the batch finishes.Upload, poll, and collect
The whole loop end to end — upload, poll until done, fetch, then map results back to your records byid.
Python
Classifying traces
The most common batch job is labeling a backlog of agent traces — scanning past conversations for jailbreaks, guardrail violations, loops, or leaked thinking. Run it without code from the Traces dashboard: select conversations, pick the Reflexes to run, and the labels land back on each trace. Under the hood that’s an asynchronous batch over the text of each turn.Errors
OpenAI-shaped:{ "error": { "message", "type", "param", "code" } } — param appears only on invalid_request_error, and code is null for the validation cases below. These are request-level failures; an individual row that fails to classify is reported per row in results (see above), not as a request error.
| Status | type | When |
|---|---|---|
401 | authentication_error | Missing (missing_api_key) or invalid (invalid_api_key) key. |
400 | invalid_request_error | Validation failed — a duplicate id, text over 350k chars, model not an array (async), or more than 10,000 rows (async). param names the offending field. |
413 | invalid_request_error | (sync) more than 300 rows in one call. |
404 | invalid_request_error | model_not_found (a named model doesn’t exist) or batch_not_found (unknown batch_id, async). |
409 | invalid_request_error | model_not_ready — a named model hasn’t finished training. |
Reflexes overview
What a Reflex is, the default classifiers, and realtime
/predict.Train a Custom Reflex
Bring labeled examples or synthesize a dataset; get a classifier in ~30s.