
Add Batch API requests from a JSONL file
Add Batch API requests from a JSONL file
For scripted or pipeline-built Batch jobs, upload a JSONL file through the Files API, then create the batch with input_file_id. Each line is one request. Caps: 200 MB and 50,000 requests. File-based batches are sealed — you cannot call AddBatchRequests afterward. Overview of create / poll / results: Run a Batch API job.
Line format
Each line is a JSON object with four fields:
| Field | Rule |
|---|---|
custom_id |
Unique in the file; maps to batch_request_id on results |
method |
Always "POST" |
url |
Endpoint path (/v1/responses, /v1/chat/completions, /v1/images/generations, …) |
body |
Payload for that endpoint |
You can mix endpoints in one file. Each line is routed on its own.
{"custom_id": "chat-1", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "grok-4.3", "messages": [{"role": "user", "content": "Classify: The product exceeded my expectations!"}]}}
{"custom_id": "search-1", "method": "POST", "url": "/v1/responses", "body": {"model": "grok-4.3", "tools": [{"type": "web_search"}, {"type": "x_search"}], "input": [{"role": "user", "content": "What are the latest SpaceX launches?"}]}}
{"custom_id": "img-1", "method": "POST", "url": "/v1/images/generations", "body": {"model": "grok-imagine-image-2.0", "prompt": "A futuristic city skyline at sunset"}}
Check each model page — unsupported models reject batch lines. Prefer a Batch-listed model such as grok-4.3 when the docs say grok-4.5 is unsupported for Batch.
Upload, then create
# 1) Upload the JSONL
curl -X POST https://api.x.ai/v1/files \
-H "Authorization: Bearer $XAI_API_KEY" \
-F file="@batch_requests.jsonl"
# 2) Create the batch with that file id
curl -X POST https://api.x.ai/v1/batches \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $XAI_API_KEY" \
-d '{"name": "sentiment_analysis", "input_file_id": "file-abc123"}'
import os
from xai_sdk import Client
client = Client(api_key=os.getenv("XAI_API_KEY"))
file = client.files.upload(file=open("batch_requests.jsonl", "rb"))
batch = client.batch.create(batch_name="sentiment_analysis", input_file_id=file.id)
print(batch.batch_id)
If any line is invalid, the batch is cancelled with an error. Poll and fetch results the same way as inline batches. Pricing: Batch API Pricing.
Pitfalls
- Duplicate
custom_idvalues in the file. - Calling AddBatchRequests on a file-based batch — sealed after create.
- Leaving Imagine result URLs un-downloaded (they expire about an hour after completion).