Batch format and client example

The API follows the OpenAI batch workflow for text chat completions. Only the subset documented here is supported.

Input file

UTF-8 JSONL, one request per line. Each line needs a unique custom_id, method POST, url /v1/chat/completions and a body. Every line in a batch uses the same model.

{"custom_id": "q-0", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "Qwen/Qwen3-0.6B", "max_tokens": 64, "temperature": 0, "messages": [{"role": "user", "content": "What is a batch API?"}]}}

Supported request fields

model, messages (system, user and assistant roles with text content), max_tokens or max_completion_tokens, temperature, top_p, stop, seed, presence_penalty, frequency_penalty, and chat_template_kwargs.enable_thinking for Qwen3 models.

Rejected, never ignored

Images, audio, tools and function calling, streaming, n greater than 1, log probabilities and structured output are rejected with an error that names the field. A request longer than the model context is rejected on its own row; nothing is truncated.

Endpoints

POST   /v1/files                        upload a JSONL file (purpose "batch")
GET    /v1/files/{id}                   describe a file
GET    /v1/files/{id}/content           download input, output or error file
DELETE /v1/files/{id}                   delete the content now
POST   /v1/batches                      create (optional Idempotency-Key header)
GET    /v1/batches  |  /v1/batches/{id} list or poll
POST   /v1/batches/{id}/cancel          cancel

Complete Python example

Uses the official openai package with the same base URL and API key as real-time inference. Create a key on the API keys page of your console.

"""Upload a JSONL batch, create it, wait for it, and download results - with the official openai package.

Environment: BATCH_API_KEY (an API key from your console), BATCH_API_BASE (default: this site's API gateway),
BATCH_MODEL (a model listed on the Batches page of your console).
"""
import json
import os
import time

from openai import OpenAI

client = OpenAI(base_url=os.environ.get("BATCH_API_BASE", "https://api.reductionofstates.com/v1"),
                api_key=os.environ["BATCH_API_KEY"])
model = os.environ.get("BATCH_MODEL", "Qwen/Qwen3-0.6B")

questions = ["What is a batch API?", "Name three rivers in Europe.", "Explain JSONL in one sentence."]
with open("requests.jsonl", "w") as f:
    for i, question in enumerate(questions):
        f.write(json.dumps({"custom_id": f"q-{i}", "method": "POST", "url": "/v1/chat/completions",
                            "body": {"model": model, "max_tokens": 64, "temperature": 0,
                                     "messages": [{"role": "user", "content": question}]}}) + "\n")

batch_file = client.files.create(file=open("requests.jsonl", "rb"), purpose="batch")
batch = client.batches.create(input_file_id=batch_file.id, endpoint="/v1/chat/completions",
                              completion_window="24h",
                              extra_headers={"Idempotency-Key": f"example-{batch_file.id}"})
while batch.status not in ("completed", "failed", "cancelled", "expired"):
    time.sleep(2)
    batch = client.batches.retrieve(batch.id)
print(batch.status, batch.request_counts)
if batch.errors:
    for e in batch.errors.data:
        print("validation error:", e.line, e.code, e.message)
if batch.output_file_id:
    for line in client.files.content(batch.output_file_id).text.splitlines():
        row = json.loads(line)
        print(row["custom_id"], "->", row["response"]["body"]["choices"][0]["message"]["content"])
if batch.error_file_id:
    for line in client.files.content(batch.error_file_id).text.splitlines():
        row = json.loads(line)
        print(row["custom_id"], "error:", row["error"]["code"], row["error"]["message"])

Results

Successful rows are in the output file. Failed, cancelled and expired rows are in the error file with a typed code. Rows are matched by custom_id; their order is not guaranteed.

Differences from the OpenAI Batch API

Only /v1/chat/completions batches are supported. Completion windows are set by the operator. Batch objects add x_ fields with the internal state and token usage, and a queued batch reports in_progress. Each batch's charge appears on the Batches page of your console.

Local evaluation

Pilot participants can run the complete service and a small open model on one Apple Silicon Mac, without our infrastructure, to check the workflow before sending data.

Request pilot access

← Back to batch inference