Skip to main content
The Batch and Files APIs share one data model. You upload an input file, create a batch that points at it, and when the batch finishes the service writes result and error files back. This page describes those two objects, the lifecycle a batch moves through, and where each endpoint lives. For request and response details, every endpoint has an interactive page under API Reference, linked from the tables below. To run a batch end to end, start with the Quickstart.

Authentication

Both APIs authenticate with headers, not a bearer token:
x-api-key:    <your-api-key>
x-project-id: <your-project-uuid>
Missing either header returns 401; a key that is invalid, inactive, or does not belong to the supplied project returns 403; an organization with no balance and no free credits returns 429 with insufficient_quota. See the Errors reference for the complete list.

Endpoints

The Files API stores the JSONL that drives a batch:
MethodPathReference
POST/v1/filesUpload file
GET/v1/filesList files
GET/v1/files/{file_id}Retrieve file
GET/v1/files/{file_id}/contentDownload file
DELETE/v1/files/{file_id}Delete file
The Batches API submits and monitors the jobs:
MethodPathReference
POST/v1/batchesCreate batch
GET/v1/batchesList batches
GET/v1/batches/{batch_id}Retrieve batch
POST/v1/batches/{batch_id}/cancelCancel batch
Both APIs are wire-compatible with OpenAI’s /v1/files and /v1/batches, so the official SDKs work once pointed at the ZeroGPU base URL. The ZeroGPU specifics are: completion_window must be "24h", endpoint must be /v1/chat/completions (the only batchable endpoint), files are soft-deleted, and error files carry an is_error flag (below).

The File object

Returned by upload and retrieve, and inside data[] on list.
{
  "id":         "file-abc123...",
  "object":     "file",
  "bytes":      12345,
  "created_at": 1736290000,
  "filename":   "input.jsonl",
  "purpose":    "batch",
  "status":     "processed",
  "expires_at": 1738882000
}
FieldTypeDescription
idstringFile identifier, always prefixed file-. Legacy file_ ids written before the prefix was normalised remain resolvable.
objectstringAlways "file".
bytesintegerSize in bytes measured by the server after upload.
created_atintegerUnix timestamp (seconds).
filenamestringThe filename you uploaded, or {file_id}.jsonl if none was supplied.
purposestring"batch" for uploads; "batch_output" for both result and error files the service writes.
statusstring"processed" today. The wider uploaded / processed / error union matches OpenAI’s published type for forward compatibility.
expires_atinteger | omittedWhen the file is removed. Uploads expire 30 days after upload; may be absent on server-written files.
is_errorboolean | omittedZeroGPU extension. Present and true only on the error file referenced by Batch.error_file_id. OpenAI SDKs ignore it unless explicitly read.
Output and error files are both written with purpose: "batch_output"; the is_error: true flag is what distinguishes the error file when you GET /v1/files?purpose=batch_output.

The Batch object

Returned by create, retrieve, and cancel, and inside data[] on list.
{
  "id":                "batch_01HZX...",
  "object":            "batch",
  "endpoint":          "/v1/chat/completions",
  "errors":            null,
  "input_file_id":     "file-abc123...",
  "completion_window": "24h",
  "status":            "in_progress",
  "output_file_id":    null,
  "error_file_id":     null,
  "created_at":        1736290000,
  "in_progress_at":    1736290001,
  "expires_at":        1736376400,
  "finalizing_at":     null,
  "completed_at":      null,
  "failed_at":         null,
  "expired_at":        null,
  "cancelling_at":     null,
  "cancelled_at":      null,
  "request_counts":    { "total": 1500, "completed": 0, "failed": 0 },
  "metadata":          { "job": "nightly-classify" }
}
FieldTypeDescription
idstringBatch identifier, prefix batch_.
objectstringAlways "batch".
endpointstringThe endpoint every line in this batch targets.
errorsobject | nullWhen status is failed, holds { object: "list", data: [BatchError] } describing the validation failure. Each BatchError is { code, message, line, param }. null otherwise.
input_file_idstringThe file- id you supplied at creation.
completion_windowstringAlways "24h".
statusstringLifecycle state, see below.
output_file_idstring | nullFile of successfully completed lines, populated when status is completed. Download via GET /v1/files/{id}/content.
error_file_idstring | nullFile of failed lines, populated when at least one line failed. Listed with purpose: "batch_output", is_error: true.
created_atintegerWhen the batch was created.
in_progress_atinteger | nullWhen validation finished and processing started.
expires_atinteger24 hours after created_at; anything unfinished by then becomes expired.
finalizing_atinteger | nullWhen all lines finished and the output files began writing.
completed_at / failed_at / expired_at / cancelling_at / cancelled_atinteger | nullTimestamps for each terminal or transitional state; null until reached.
request_countsobject{ total, completed, failed }. completed + failed equals total only once the batch is terminal.
metadataobjectArbitrary JSON you supplied at creation, echoed back unchanged. Empty {} when omitted, never null.

Status lifecycle

StatusMeaning
validatingRow persisted; the JSONL is being streamed and validated synchronously. Transient.
in_progressValidation succeeded; lines are being processed.
finalizingAll lines processed; output and error files are being written. Transient.
completedTerminal. output_file_id (and error_file_id if any line failed) are populated.
failedTerminal. JSONL validation rejected the input; errors holds the offending line(s). Still retrievable so SDKs can introspect.
expiredTerminal. The 24-hour window elapsed first. Whatever finished is in output_file_id / error_file_id; the rest is in the error file with code: "batch_expired".
cancellingCancellation requested. Dispatched lines finish; pending lines are short-circuited to the error file with code: "batch_cancelled".
cancelledTerminal. Cancellation drained; files reflect whatever processed before the request.
Validation is synchronous, processing is asynchronous: the create call returns only after the JSONL passes (or fails) validation, and lines are then worked through an internal queue. Once a batch is terminal, no further state changes occur, so stop polling. Retrieve returns live request_counts; the list endpoint may lag by a few seconds, so poll a specific batch for accurate progress.

Reading results

When status is completed:
  • output_file_id is set if any line returned 2xx. Download it and match results to inputs by custom_id, order is not preserved.
  • error_file_id is set if any line failed. Partition by error.code to decide what to retry.
Both files follow the same 30-day retention as your uploads, and the line schemas live in JSONL format. Deleting an input file does not stop a running batch, the input is read at creation time. For size and rate limits, see the Overview quick facts.

Next steps

JSONL format →

Exact line schema for input, output, and error files.

Errors reference →

Every status, validation message, and error-file code, with recovery steps.