OpenAI Batch API JSONL Format Guide

Learn how to structure JSONL files for OpenAI's Batch API to save 50% on costs

Last updated: February 2026

What is the OpenAI Batch API?

The OpenAI Batch API allows you to send large volumes of API requests as a single batch job. Instead of making thousands of individual API calls, you upload a JSONL file containing all your requests and OpenAI processes them asynchronously within 24 hours.

The key benefit is cost: batch requests are 50% cheaper than real-time API calls. This makes the Batch API ideal for tasks that don't need immediate responses, such as content generation, data classification, embeddings computation, and evaluation pipelines.

JSONL Request Format

Each line in the batch input JSONL file represents one API request. Every line must contain three required fields and follows a specific structure.

custom_id β€” A unique identifier for each request. Used to match requests with responses. Can be any string up to 512 characters.
method β€” The HTTP method. Currently only POST is supported.
url β€” The API endpoint path. For chat completions: /v1/chat/completions. For embeddings: /v1/embeddings.
body β€” The request body. Same format as the corresponding API endpoint's request body.
Basic Request Structure
{"custom_id": "req-001", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "Hello"}]}}

Chat Completions Batch

The most common use case for the Batch API is sending multiple chat completion requests. Each line contains a full request with model, messages, and optional parameters like max_tokens or temperature.

Single Request

Each line contains a complete chat completion request with model, messages, and optional parameters.

Single Request
{"custom_id": "task-001", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-4o-mini", "messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Summarize the benefits of renewable energy."}], "max_tokens": 500}}

Multiple Requests JSONL File

A batch file typically contains hundreds or thousands of requests. Here is a file with three different tasks: summarization, classification, and translation.

Multiple Requests JSONL File
{"custom_id": "summary-001", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "Summarize: Solar energy is a renewable source of power that harnesses sunlight using photovoltaic cells."}], "max_tokens": 200}}
{"custom_id": "classify-001", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "Classify this review as positive or negative: Great product, works perfectly!"}], "max_tokens": 50}}
{"custom_id": "translate-001", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "Translate to French: Hello, how are you today?"}], "max_tokens": 100}}

Embeddings Batch

The Batch API also supports embedding requests, which is useful for processing large document collections. Embedding batches use the same JSONL structure but target the /v1/embeddings endpoint.

Embedding requests use a simpler body structure with model and input text.

Embeddings Request Format
{"custom_id": "embed-001", "method": "POST", "url": "/v1/embeddings", "body": {"model": "text-embedding-3-small", "input": "JSONL is a text format for storing structured data."}}
{"custom_id": "embed-002", "method": "POST", "url": "/v1/embeddings", "body": {"model": "text-embedding-3-small", "input": "Each line contains one valid JSON object."}}
{"custom_id": "embed-003", "method": "POST", "url": "/v1/embeddings", "body": {"model": "text-embedding-3-small", "input": "JSONL files use the .jsonl extension."}}

Response Format

When a batch job completes, OpenAI provides an output JSONL file where each line contains the response for one request. The response includes the original custom_id so you can match responses to requests.

Successful Response

A successful response includes the custom_id, response status code, and the full API response body.

Successful Response
{"id": "batch_req_abc123", "custom_id": "task-001", "response": {"status_code": 200, "body": {"id": "chatcmpl-xyz", "object": "chat.completion", "choices": [{"index": 0, "message": {"role": "assistant", "content": "Renewable energy provides numerous benefits including reduced greenhouse gas emissions, lower long-term costs, and energy independence."}}]}}, "error": null}

Error Response

Failed requests include an error object with a code and message explaining what went wrong.

Error Response
{"id": "batch_req_def456", "custom_id": "task-002", "response": null, "error": {"code": "invalid_request_error", "message": "The model 'gpt-5' does not exist."}}

Complete Batch API Workflow

Here is the complete five-step workflow for using the Batch API with the Python SDK, from creating the JSONL file to downloading and parsing results.

  1. 1Create a JSONL file with one request per line
  2. 2Upload the file using the Files API with purpose set to batch
  3. 3Create a batch job referencing the uploaded file ID
  4. 4Poll the batch status until it reaches completed, failed, or cancelled
  5. 5Download and parse the output JSONL file to extract results
Python β€” Batch API Workflow
from openai import OpenAI
import json
import time
client = OpenAI()
# Step 1: Create the JSONL batch file
prompts = [
"Summarize the benefits of renewable energy.",
"Classify this text as positive or negative: Great product!",
"Translate to French: Hello, how are you?",
]
requests = [
{
"custom_id": f"req-{i}",
"method": "POST",
"url": "/v1/chat/completions",
"body": {
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": prompt}],
"max_tokens": 200,
},
}
for i, prompt in enumerate(prompts)
]
with open("batch_input.jsonl", "w") as f:
for req in requests:
f.write(json.dumps(req) + "\n")
# Step 2: Upload the file
batch_file = client.files.create(
file=open("batch_input.jsonl", "rb"),
purpose="batch",
)
# Step 3: Create the batch
batch = client.batches.create(
input_file_id=batch_file.id,
endpoint="/v1/chat/completions",
completion_window="24h",
)
print(f"Batch created: {batch.id}")
# Step 4: Poll for completion
while True:
status = client.batches.retrieve(batch.id)
print(f"Status: {status.status}")
if status.status in ("completed", "failed", "cancelled"):
break
time.sleep(60)
# Step 5: Download results
if status.output_file_id:
content = client.files.content(status.output_file_id)
with open("batch_output.jsonl", "wb") as f:
f.write(content.read())

Batch API vs Real-time API

Understanding when to use the Batch API versus the standard real-time API helps you optimize both cost and performance.

Feature
Batch API
Real-time API
Cost
50% discount
Standard pricing
Latency
Up to 24 hours
Seconds
Rate Limits
Higher limits
Standard limits
Input Format
JSONL file upload
Individual API calls
Best For
Bulk processing, evaluation, data generation
Interactive apps, real-time chat, streaming

For details on JSONL format for OpenAI fine-tuning, see our OpenAI JSONL Format Guide.

Prepare Your Batch Files

Use our free tools to create, validate, and inspect your JSONL batch files before submitting to OpenAI.

Work with JSONL Files Online

View, validate, and convert JSONL files up to 1GB right in your browser. No uploads required, 100% private.

Frequently Asked Questions

OpenAI Batch API JSONL Format β€” Requests, Responses & Lim...