Results
The output and error file formats. One JSONL line per request, joined back to your inputs by custom_id.
When a batch reaches completed (or expired with partial work), it produces
up to two result files, referenced on the batch object:
output_file_id: successful requests, one line each.error_file_id: failed requests, one line each. Present only if at least one request failed.
Download either with the Files content endpoint:
curl https://inference.openrelay.inc/v1/files/file-batch_9f8e7d6c5b4a-output/content \
-H "Authorization: Bearer $OPENRELAY_API_KEY" \
-o results.jsonlCLI: orl files content get file-batch_9f8e7d6c5b4a-output -o results.jsonl.
Result line shape
Every line in both files is one result object, matching the OpenAI batch output shape:
| Field | Type | Description |
|---|---|---|
id | string | A per-result id (batch_req_<custom_id>). |
custom_id | string | The custom_id from the matching input request. Use it to join results back to inputs. |
response | object or null | On success: { status_code, body }, where body is the full endpoint response (e.g. a chat completion). Null on failure. |
error | object or null | On failure: { code, message, status_code, body }. Null on success. |
Exactly one of response and error is set on each line. The result files are
not ordered to match the input file; always join by custom_id.
Output file line (success)
{
"id": "batch_req_req-1",
"custom_id": "req-1",
"response": {
"status_code": 200,
"body": {
"id": "chatcmpl-abc123",
"object": "chat.completion",
"model": "openrelay/gpt-oss-120b",
"choices": [
{ "index": 0, "message": { "role": "assistant", "content": "Red, blue, and yellow." }, "finish_reason": "stop" }
],
"usage": { "prompt_tokens": 17, "completion_tokens": 8, "total_tokens": 25 }
}
},
"error": null
}Error file line (failure)
{
"id": "batch_req_req-7",
"custom_id": "req-7",
"response": null,
"error": {
"code": "invalid_request_error",
"message": "messages: field required",
"status_code": 400
}
}A request whose 24-hour window elapsed before it ran gets an error line with
code: "batch_expired". A record that fails validation (for example one with
"stream": true, which is not allowed in a batch) also lands in the error
file rather than failing the whole batch.
Reconciling usage
Each successful response.body carries its own usage object, billed exactly
like an online request but at the batch rate. The batch object also exposes a
rolled-up usage (input_tokens, output_tokens, cost_nano_usd) so you can
read total spend without summing every line. See
Pricing & billing.