Files and batches
The OpenAI shapes for a file and a batch, with the fields OpenFill adds. A file exists to be a batch input or a batch output; there is no other purpose.
Upload a file
curl https://api.openfill.ai/v1/files -H "Authorization: Bearer $OPENFILL_API_KEY" \ -F purpose=batch -F [email protected]Multipart, one file, purpose of batch. The content is checked when a batch starts rather than at upload. A file over 50 MB is refused with 413.
{"id": "file-...", "object": "file", "bytes": 1234, "created_at": 1756700000, "expires_at": 1756786400, "filename": "requests.jsonl", "purpose": "batch", "status": "processed"}expires_at is when the file is deleted: at least a day after upload, or your storage period. Both timestamps are epoch seconds.
Get a file and its content
curl https://api.openfill.ai/v1/files/<file_id> -H "Authorization: Bearer $OPENFILL_API_KEY"curl https://api.openfill.ai/v1/files/<file_id>/content -H "Authorization: Bearer $OPENFILL_API_KEY" -o output.jsonlThe content is served as application/jsonl with a filename in Content-Disposition. A file past its expiry answers 410 result_unavailable. Each download counts against the hourly allowance on limits.
Create a batch
curl https://api.openfill.ai/v1/batches -H "Authorization: Bearer $OPENFILL_API_KEY" -H "Content-Type: application/json" \ -d '{"input_file_id": "file-...", "endpoint": "/v1/chat/completions", "completion_window": "24h", "max_price": 0.02}'| Field | Type | Default | Meaning |
|---|---|---|---|
| input_file_id | string | required | A file uploaded with purpose batch. |
| endpoint | string | required | /v1/chat/completions or /v1/completions. Every line's url must match it. |
| completion_window | string | 24h | Only 24h is accepted, as OpenAI's shape has it. |
| max_price | number | key or account | The max price every line inherits. A line's own body.max_price wins over it. |
| max_wait | integer | a day | The deadline in seconds. Lines still queued at expires_at are expired unexecuted. |
| metadata | object | none | Up to 16 pairs; keys up to 64 characters, values up to 512. |
The batch is answered with status validating. With no max price on the batch, the key or the account it is 400 missing_bid; with too many batches already running it is 429 with Retry-After. Up to 10,000 lines per file.
The batch object
| Field | Meaning |
|---|---|
| id | batch_ and 24 characters. |
| endpoint | /v1/chat/completions or /v1/completions. |
| status | validating, in_progress, cancelling, completed, expired, cancelled or failed. |
| input_file_id, output_file_id, error_file_id | The files. Output and error are null until the batch finishes, and absent when empty. |
| errors | null, or {object: list, data: [{code: batch_error, message}]} when validation failed. |
| completion_window | Always 24h. |
| created_at, expires_at, completed_at | Epoch seconds. expires_at is the real deadline. |
| request_counts | {total, completed, failed}. failed folds in expired and cancelled lines. |
| metadata | Up to 16 string pairs, as sent. |
| x_market | {active, pending_result, expired, canceled, bid}. bid is the batch max_price, or null. |
| x_retention | {output_days, output_expires_at, output_deleted} for the output file. |
List, retrieve and cancel
curl "https://api.openfill.ai/v1/batches?limit=20" -H "Authorization: Bearer $OPENFILL_API_KEY"{"object": "list", "data": [ ...batches... ], "first_id": "batch_...", "last_id": "batch_...", "has_more": true}Newest first. Pass last_id as ?after= for the next page. has_more is true whenever a page is full, so the page after the last one is empty with has_more false.
curl https://api.openfill.ai/v1/batches/<batch_id> -H "Authorization: Bearer $OPENFILL_API_KEY"curl -X POST https://api.openfill.ai/v1/batches/<batch_id>/cancel -H "Authorization: Bearer $OPENFILL_API_KEY"Cancel answers the batch with status cancelling; queued lines are cancelled and executing ones finish. A batch in any other state answers 409 batch_not_cancelable.
Line formats
{"custom_id": "job-1", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "...", "messages": [{"role": "user", "content": "..."}], "max_price": 0.03}}{"id": "batch_req_...", "custom_id": "job-1", "response": {"status_code": 200, "request_id": "<order_id>", "body": { ...the completion... }}, "error": null}{"id": "batch_req_...", "custom_id": "job-2", "response": null, "error": {"code": "expired", "message": "..."}}The error codes, the statuses, and what a line cannot carry are on the batch page.