Files & batches
POST /v1/files and POST /v1/batches — a JSONL file of requests, run in the background, results as files.
https://iranrouter.com/v1/filesUpload a file (multipart: file and purpose). Two uses: a batch input with purpose=batch, and referring to a file inside a conversation by file_id (below). The type is read from the CONTENT, not the extension: documents (PDF, Word, Excel, PowerPoint), images, audio and text (JSON, JSONL, CSV, Markdown) are accepted; an executable or an archive is refused with 415. A path in the filename (invoices/2026/march.pdf) or a `folder` field becomes the file's folder — a label to group and filter by (GET /v1/files?folder=…), not a real directory. The file is kept until you delete it (no expiry; up to 100 MB each and 10 GB per account by default (your account may be granted more) — past that, 413 with code file_quota_reached) and managed with GET /v1/files, GET /v1/files/{id}, GET /v1/files/{id}/content and DELETE /v1/files/{id} — OpenAI's shapes.
curl https://iranrouter.com/v1/files \ -H "Authorization: Bearer ir-..." \ -F purpose=batch \ -F file=@requests.jsonl
{ "id": "9c1e...-file-id", "object": "file", "bytes": 4210, "created_at": 1789000000, "filename": "requests.jsonl", "purpose": "batch", "status": "processed" }https://iranrouter.com/v1/batchesA JSONL file of requests for one endpoint runs in the background, line by line, through the ordinary path — each line an ordinary request with the ordinary bill and limits of that key — and the results come back as files. No discount: a batch is a convenience, not a different price. completion_window is accepted but not a promise: the batch starts at once.
{"custom_id": "q1", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "openai/gpt-4o-mini", "messages": [{"role": "user", "content": "سلام"}]}}
{"custom_id": "q2", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "openai/gpt-4o-mini", "messages": [{"role": "user", "content": "خداحافظ"}]}}curl https://iranrouter.com/v1/batches \ -H "Authorization: Bearer ir-..." \ -H "Content-Type: application/json" \ -d '{"input_file_id": "9c1e...-file-id", "endpoint": "/v1/chat/completions", "completion_window": "24h"}'
| Field | Notes |
|---|---|
endpoint | /v1/chat/completions · /v1/responses · /v1/messages · /v1/embeddings · /v1/completions · /v1/moderations · /v1/rerank |
status | validating → in_progress → finalizing → completed | failed | cancelling → cancelled |
request_counts | total, completed, failed — updated every ten lines. |
output_file_id / error_file_id | Successes and failures, each line {id, custom_id, response:{status_code, request_id, body}, error}. Content from GET /v1/files/{id}/content. |
POST /v1/batches/{id}/cancel | Stops after the lines in flight; the output so far is written. |
- Up to 1000 lines per batch; up to 5 open batches per user (past that, 429 batch_limit_reached).
- Each line's url must equal the batch endpoint; stream is switched off; an invalid line goes to the error file and the rest continue.
- A line refused with a 429 for rate is retried after retry-after, up to three times; a 402 for balance, or a 429 that persists, puts that line in the error file — the batch does not stop. A key revoked mid-run stops the batch, and the lines that did not run are listed in the error file.