Skip to content
OpenRelay is in early access, and the /v1 API is stable. New capabilities ship in the changelog.
Inference APIBatch API

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.jsonl

CLI: 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:

FieldTypeDescription
idstringA per-result id (batch_req_<custom_id>).
custom_idstringThe custom_id from the matching input request. Use it to join results back to inputs.
responseobject or nullOn success: { status_code, body }, where body is the full endpoint response (e.g. a chat completion). Null on failure.
errorobject or nullOn 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.

On this page