Batch API
Upload a JSONL file of chat completions, create a batch and collect the results when it finishes.
Batch
The Batch API runs many chat completions without keeping a connection open, the same way OpenAI's Batch API does: upload a JSONL file, create a batch from it, and download the results when it finishes, within 24h.
Each line of the file is one request:
{"custom_id": "req-1", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "deepseek/deepseek-v4.1-flash", "messages": [{"role": "user", "content": "Hello from OpenScale"}]}}The body is a normal chat completion request without stream, and every line uses the same model. Every line is checked when the batch is created, with the same checks as POST /v1/chat/completions: a file with any invalid line gives a failed batch whose errors list the lines, and nothing runs.
curl https://api.openscale.so/v1/files -H "Authorization: Bearer $OPENSCALE_API_KEY" -F purpose=batch -F file=@requests.jsonl
curl https://api.openscale.so/v1/batches -H "Authorization: Bearer $OPENSCALE_API_KEY" -H "Content-Type: application/json" -d '{"input_file_id": "file-...", "endpoint": "/v1/chat/completions", "completion_window": "24h"}'When the batch is completed, output_file_id holds the successful responses and error_file_id the failed, expired and cancelled requests, one JSON line each with its custom_id. Download them with GET /files/{file_id}/content.
| Limit | Value |
|---|---|
| File size | 20 MB |
| Requests per file | 10,000 |
| Requests waiting across an account's batches | 50,000 |
custom_id length | 512 characters |
| Completion window | 24h |
| Files, batches and results kept | 30 days |
Batches bill your balance, so they need a pay-as-you-go key: a plan key gets 400 with code: batch_not_in_plan. Files and batches belong to your account, so every key on it can read them. With zero data retention on, new files and batches answer 400 with code: zero_data_retention.
Endpoints
- List files:
GET https://api.openscale.so/v1/files - Upload a file:
POST https://api.openscale.so/v1/files - Retrieve a file:
GET https://api.openscale.so/v1/files/{file_id} - Delete a file:
DELETE https://api.openscale.so/v1/files/{file_id} - Download file content:
GET https://api.openscale.so/v1/files/{file_id}/content - List batches:
GET https://api.openscale.so/v1/batches - Create a batch:
POST https://api.openscale.so/v1/batches - Retrieve a batch:
GET https://api.openscale.so/v1/batches/{batch_id} - Cancel a batch:
POST https://api.openscale.so/v1/batches/{batch_id}/cancel
List files
GET https://api.openscale.so/v1/files
Your account's files, newest first. Filter with purpose (batch or batch_output).
Query parameters
| Field | Type | Required | Description |
|---|---|---|---|
purpose | string | No | One of batch, batch_output. |
limit | integer | No | From 1 to 100. Default 20. |
after | string | No | The id of the last object on the previous page. |
Example request
curl https://api.openscale.so/v1/files \
-H "Authorization: Bearer $OPENSCALE_API_KEY"Response
200: A list of files.
| Field | Type | Description |
|---|---|---|
object | string | Always list. |
data | array of object | |
data[].id | string | Example: file-example. |
data[].object | string | Always file. |
data[].bytes | integer | |
data[].created_at | integer | |
data[].expires_at | integer | Unix seconds when the file is deleted, 30 days after upload. |
data[].filename | string | |
data[].purpose | string | batch for uploads, batch_output for results. One of batch, batch_output. |
data[].status | string | Always processed. |
first_id | string or null | |
last_id | string or null | |
has_more | boolean |
Upload a file
POST https://api.openscale.so/v1/files
Upload a JSONL batch input file as multipart/form-data with the fields file and purpose (batch). Up to 20 MB and 10,000 requests.
Request body
Sent as multipart/form-data.
| Field | Type | Required | Description |
|---|---|---|---|
file | string | Yes | The JSONL file, one request per line. |
purpose | string | Yes | Always batch. |
Example request
curl https://api.openscale.so/v1/files \
-H "Authorization: Bearer $OPENSCALE_API_KEY" \
-F purpose=batch \
-F file=@requests.jsonlResponse
200: The file.
| Field | Type | Description |
|---|---|---|
id | string | Example: file-example. |
object | string | Always file. |
bytes | integer | |
created_at | integer | |
expires_at | integer | Unix seconds when the file is deleted, 30 days after upload. |
filename | string | |
purpose | string | batch for uploads, batch_output for results. One of batch, batch_output. |
status | string | Always processed. |
{
"id": "file-example",
"object": "file",
"bytes": 1204,
"created_at": 1790078324,
"expires_at": 1792670324,
"filename": "requests.jsonl",
"purpose": "batch",
"status": "processed"
}Errors
| Status | Meaning |
|---|---|
| 400 | Invalid upload; param names the field. zero_data_retention when the account has zero data retention on. |
| 413 | The file is larger than the limit. |
Retrieve a file
GET https://api.openscale.so/v1/files/{file_id}
A file's metadata.
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
file_id | string | Yes |
Example request
curl https://api.openscale.so/v1/files/$FILE_ID \
-H "Authorization: Bearer $OPENSCALE_API_KEY"Response
200: The file.
| Field | Type | Description |
|---|---|---|
id | string | Example: file-example. |
object | string | Always file. |
bytes | integer | |
created_at | integer | |
expires_at | integer | Unix seconds when the file is deleted, 30 days after upload. |
filename | string | |
purpose | string | batch for uploads, batch_output for results. One of batch, batch_output. |
status | string | Always processed. |
Errors
| Status | Meaning |
|---|---|
| 404 | No file with this id in your account. |
Delete a file
DELETE https://api.openscale.so/v1/files/{file_id}
Delete a file at once.
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
file_id | string | Yes |
Example request
curl -X DELETE https://api.openscale.so/v1/files/$FILE_ID \
-H "Authorization: Bearer $OPENSCALE_API_KEY"Response
200: Deleted.
{
"id": "file-example",
"object": "file",
"deleted": true
}Errors
| Status | Meaning |
|---|---|
| 404 | No file with this id in your account. |
Download file content
GET https://api.openscale.so/v1/files/{file_id}/content
The file as uploaded, or a batch's results: one JSON line per request with its custom_id and either a response (status_code and body) or an error.
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
file_id | string | Yes |
Example request
curl https://api.openscale.so/v1/files/$FILE_ID/content \
-H "Authorization: Bearer $OPENSCALE_API_KEY"Response
200: The file content.
Errors
| Status | Meaning |
|---|---|
| 404 | No file with this id in your account. |
List batches
GET https://api.openscale.so/v1/batches
Your account's batches, newest first.
Query parameters
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | No | From 1 to 100. Default 20. |
after | string | No | The id of the last object on the previous page. |
Example request
curl https://api.openscale.so/v1/batches \
-H "Authorization: Bearer $OPENSCALE_API_KEY"Response
200: A list of batches.
| Field | Type | Description |
|---|---|---|
object | string | Always list. |
data | array of object | |
data[].id | string | Example: batch_example. |
data[].object | string | Always batch. |
data[].endpoint | string | Always /v1/chat/completions. |
data[].model | string or null | |
data[].errors | object or null | For a failed batch: the invalid lines of the input file, each with its line number, code and message. |
data[].input_file_id | string | |
data[].completion_window | string | Always 24h. |
data[].status | string | One of failed, in_progress, completed, expired, cancelling, cancelled. |
data[].output_file_id | string or null | Results of the requests that succeeded. |
data[].error_file_id | string or null | Failed, expired and cancelled requests. |
data[].created_at | integer | |
data[].expires_at | integer or null | |
data[].completed_at | integer or null | |
data[].request_counts | object | |
data[].metadata | object or null | |
first_id | string or null | |
last_id | string or null | |
has_more | boolean |
Create a batch
POST https://api.openscale.so/v1/batches
Start a batch from an uploaded file. Every line is checked first: a file with an invalid line gives a failed batch that lists the errors, and nothing runs. Needs a pay-as-you-go key.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
input_file_id | string | Yes | A file uploaded with purpose: batch. |
endpoint | string | Yes | Always /v1/chat/completions. |
completion_window | string | Yes | Always 24h. |
metadata | object | No | Up to 16 string pairs (keys up to 64 characters, values up to 512). |
Example request
curl https://api.openscale.so/v1/batches \
-H "Authorization: Bearer $OPENSCALE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input_file_id": "file-example",
"endpoint": "/v1/chat/completions",
"completion_window": "24h"
}'Response
200: The batch.
| Field | Type | Description |
|---|---|---|
id | string | Example: batch_example. |
object | string | Always batch. |
endpoint | string | Always /v1/chat/completions. |
model | string or null | |
errors | object or null | For a failed batch: the invalid lines of the input file, each with its line number, code and message. |
input_file_id | string | |
completion_window | string | Always 24h. |
status | string | One of failed, in_progress, completed, expired, cancelling, cancelled. |
output_file_id | string or null | Results of the requests that succeeded. |
error_file_id | string or null | Failed, expired and cancelled requests. |
created_at | integer | |
expires_at | integer or null | |
completed_at | integer or null | |
request_counts | object | |
request_counts.total | integer | |
request_counts.completed | integer | |
request_counts.failed | integer | |
metadata | object or null |
{
"id": "batch_example",
"object": "batch",
"endpoint": "/v1/chat/completions",
"model": "deepseek/deepseek-v4.1-flash",
"errors": null,
"input_file_id": "file-example",
"completion_window": "24h",
"status": "in_progress",
"output_file_id": null,
"error_file_id": null,
"created_at": 1790078324,
"expires_at": 1790164724,
"completed_at": null,
"request_counts": {
"total": 2,
"completed": 0,
"failed": 0
},
"metadata": null
}Errors
| Status | Meaning |
|---|---|
| 400 | Invalid request; param names the field. batch_not_in_plan for a plan key, zero_data_retention when the account has zero data retention on. |
| 401 | Missing or invalid API key. |
Retrieve a batch
GET https://api.openscale.so/v1/batches/{batch_id}
A batch, with live request counts while it runs.
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
batch_id | string | Yes |
Example request
curl https://api.openscale.so/v1/batches/$BATCH_ID \
-H "Authorization: Bearer $OPENSCALE_API_KEY"Response
200: The batch.
| Field | Type | Description |
|---|---|---|
id | string | Example: batch_example. |
object | string | Always batch. |
endpoint | string | Always /v1/chat/completions. |
model | string or null | |
errors | object or null | For a failed batch: the invalid lines of the input file, each with its line number, code and message. |
input_file_id | string | |
completion_window | string | Always 24h. |
status | string | One of failed, in_progress, completed, expired, cancelling, cancelled. |
output_file_id | string or null | Results of the requests that succeeded. |
error_file_id | string or null | Failed, expired and cancelled requests. |
created_at | integer | |
expires_at | integer or null | |
completed_at | integer or null | |
request_counts | object | |
request_counts.total | integer | |
request_counts.completed | integer | |
request_counts.failed | integer | |
metadata | object or null |
Errors
| Status | Meaning |
|---|---|
| 404 | No batch with this id in your account. |
Cancel a batch
POST https://api.openscale.so/v1/batches/{batch_id}/cancel
Cancel the requests that have not started. The batch moves to cancelling, then cancelled; finished requests keep their results.
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
batch_id | string | Yes |
Example request
curl -X POST https://api.openscale.so/v1/batches/$BATCH_ID/cancel \
-H "Authorization: Bearer $OPENSCALE_API_KEY"Response
200: The batch.
| Field | Type | Description |
|---|---|---|
id | string | Example: batch_example. |
object | string | Always batch. |
endpoint | string | Always /v1/chat/completions. |
model | string or null | |
errors | object or null | For a failed batch: the invalid lines of the input file, each with its line number, code and message. |
input_file_id | string | |
completion_window | string | Always 24h. |
status | string | One of failed, in_progress, completed, expired, cancelling, cancelled. |
output_file_id | string or null | Results of the requests that succeeded. |
error_file_id | string or null | Failed, expired and cancelled requests. |
created_at | integer | |
expires_at | integer or null | |
completed_at | integer or null | |
request_counts | object | |
request_counts.total | integer | |
request_counts.completed | integer | |
request_counts.failed | integer | |
metadata | object or null |
Errors
| Status | Meaning |
|---|---|
| 404 | No batch with this id in your account. |
| 409 | The batch has already finished (batch_not_cancellable). |
More of the API reference
- API reference: base URLs, authentication and a first request.
- Chat Completions: POST /v1/chat/completions: the OpenAI Chat Completions format, streamed or not, with reasoning and tools.
- Responses: POST /v1/responses: the OpenAI Responses format with stored state, background runs and enforced tool rules.
- Conversations: Keep the turns of a Responses conversation on our side and continue it by id.
- Prompts: Save instructions, messages and settings once, then use them by id in the Responses API.
- Anthropic Messages: POST /anthropic/v1/messages: the Anthropic Messages format, for Claude Code and Anthropic SDKs.
- Models and pricing: Model ids, prices per 1M tokens, context windows, output limits, versions and the live catalog endpoint.
- Errors: The error shape, every status code and code, and which ones to retry.
- Rate limits: Requests and tokens per minute, how a 429 tells you when to retry, and how to get more.
- Data retention: What is stored, for how long, how to delete it, and zero data retention.
- Interactive reference: try every endpoint in the browser.
- OpenAPI document: the whole API as OpenAPI 3.1.
This page as Markdown: /docs/batch.md