Skip to main content
The Batch API lets you send groups of requests as a single job that processes asynchronously. This is useful when you need to run many requests and do not need immediate results — for example, running evaluations, generating embeddings for a large dataset, or classifying content in bulk.

How batches run

A batch processes its lines one at a time, so per-request latency sets its throughput: 1,000 lines that take 3 seconds each finish in about 50 minutes. Separate batches run in parallel, so split a large job across several batches to finish it sooner. Batch lines do not count against your API key’s rate limits. If your organization uses judge-based auto-routing, a line with model: "auto" still counts against the selected model’s own rate limits, and a line that exceeds them fails with rate_limit_exceeded. Batch requests are billed at the same rates as synchronous requests. Plan for each batch to finish within its 24-hour completion window. A batch that overruns is stopped and returns no results, even for lines that completed. Its status stays in_progress, so give your poller its own deadline.

Supported endpoints

All requests in a single batch must target the same endpoint.

Lifecycle

A batch moves through these statuses:

Step 1 — Prepare the input file

Create a JSONL file where each line is one request. Every line has four fields:
Each body takes the same parameters as a synchronous Responses request, with these rules:
  • Leave out stream and background, or set them to false. A line that sets either one to true fails.
  • To set reasoning effort, send both keys of the reasoning object, for example "reasoning": {"effort": "low", "summary": null}. See Control reasoning.
These lines set store: false because the output file already holds each result. Leave it out if you also want to retrieve each response by ID later. A single batch can contain up to 10,000 requests. The input file can be up to 25 MB; a larger upload is rejected with HTTP 413.

Step 2 — Upload the input file

Upload the JSONL file using the Files API with purpose: "batch".

Step 3 — Create the batch

Pass the uploaded file ID, the target endpoint, and the completion window.
You can also attach metadata for your own tracking:

Step 4 — Check batch status

Poll the batch until it reaches a terminal status.
Here is a polling helper that waits for the batch to finish, up to a deadline:

Step 5 — Download the results

Once the batch is completed, download the output file. It is a JSONL file where each line contains the custom_id you provided, the response, and any error.
Each line in the output file has this structure:
If a request failed, response is null and error contains the details:
If any requests failed, the batch also provides an error_file_id containing only the failed entries.

Cancel a batch

Cancel a batch that is still in progress. Requests that have already completed remain in the output.
The batch transitions to cancelling while in-flight requests finish, then to cancelled.

List batches

Retrieve all batches for the current account, newest first. Supports pagination.
Use the after parameter with a batch ID to page through results.

Example: batch chat completions

The same flow works for chat completions. Change the url in each JSONL line and the endpoint when creating the batch.

Example: batch embeddings

The same flow works for embeddings. Change the url in each JSONL line and the endpoint when creating the batch.

Validation errors

If the input file has formatting issues, the batch moves to failed immediately. Common causes:
  • Invalid JSON — a line is not valid JSON.
  • Missing fields — a line is missing custom_id, method, url, or body.
  • Wrong method — method must be "POST".
  • URL mismatch — the url in a line does not match the endpoint declared when creating the batch.
  • Duplicate custom_id — each custom_id must be unique within the file.
Check batch.errors.data for the specific error messages and line numbers.

See also