Skip to content
RunAPI Developer Docs
Developer Resources
Developer Resources

Files and Uploads

Create, list, download, and delete persistent Files, or assemble a File from multipart Upload Parts.

The Files API stores immutable, Account-scoped user_data, batch, and batch_output Files and returns stable File IDs instead of storage URLs. Use a File ID when an API accepts a reusable File resource, and use the content endpoint when your application needs the exact stored bytes.

Choose an upload flow

  • Use POST /v1/files to create a File from one multipart request. A completed user_data File can contain up to 52,428,800 bytes.
  • Use POST /v1/files with purpose=batch for a direct batch input up to 95,000,000 bytes.
  • Use the Uploads API to send Parts before composing the final File. Each Part can contain up to 67,108,864 bytes; a completed user_data File is limited to 52,428,800 bytes and a completed batch File to 209,715,200 bytes. An unfinished Upload expires after one hour.
  • Active Files and in-progress reservations share an Account storage limit of 5,368,709,120 bytes.

POST /api/v1/files is a separate temporary upload flow that returns a temporary URL. SDK files.create and CLI runapi files create continue to use that flow. Use files.createFile or files.create_file, or CLI runapi files create-file, when you need a persistent File object.

Authenticate a request

Files and Uploads use a standard RunAPI API key. Send it as a Bearer token:

SHELL
export RUNAPI_API_KEY="runapi_..."

Every File, Upload, Part, and content request is scoped to the authenticated Account. An ID owned by another Account returns 404 without revealing whether that resource exists.

Create a File with a compatible client

Point an OpenAI-compatible client at the RunAPI /v1 base URL. No RunAPI-specific request fields are required:

PYTHON
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["RUNAPI_API_KEY"],
    base_url="https://runapi.ai/v1",
)

with open("knowledge.pdf", "rb") as source:
    file = client.files.create(file=source, purpose="user_data")

metadata = client.files.retrieve(file.id)
client.files.content(file.id).write_to_file("knowledge-copy.pdf")
client.files.delete(file.id)

The returned File never contains a storage identifier, backend, or bearer URL.

API Reference

  • Persistent Files API covers the File object and create, list, retrieve, content, and delete operations.
  • Uploads API covers the Upload object and create, add-part, complete, and cancel operations.
  • Batches API covers Moderation Batch creation, status, listing, and cancellation.

Run Moderation in a Batch

Create a JSONL input File with one moderation request per line. Each line uses the compatible Batch shape: custom_id, method, url set to /v1/moderations, and a body containing the moderation model and input. A purpose=batch File can contain up to 50,000 requests. The Batch capability currently accepts the /v1/moderations endpoint with a 24h completion window.

SHELL
INPUT_FILE_ID=$(curl -sS https://runapi.ai/v1/files \
  -H "Authorization: Bearer $RUNAPI_API_KEY" \
  -F purpose=batch \
  -F [email protected] | jq -r .id)

BATCH_ID=$(curl -sS https://runapi.ai/v1/batches \
  -H "Authorization: Bearer $RUNAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --arg file "$INPUT_FILE_ID" '{input_file_id:$file,endpoint:"/v1/moderations",completion_window:"24h"}')" \
  | jq -r .id)

curl -sS "https://runapi.ai/v1/batches/$BATCH_ID" \
  -H "Authorization: Bearer $RUNAPI_API_KEY"

Use GET /v1/batches to list work, repeat GET /v1/batches/{batch_id} until the status is terminal, or call POST /v1/batches/{batch_id}/cancel while it is still running. Completed output and error JSONL are exposed as batch_output Files; retrieve their metadata with GET /v1/files/{file_id} and exact bytes with GET /v1/files/{file_id}/content.

Multipart Upload lifecycle

Create an Upload with the final byte count, filename, MIME type, and purpose=user_data. Add one or more Parts, then pass their IDs to complete in composition order. Completion returns the Upload with its finished File.

SHELL
UPLOAD_ID=$(curl -sS https://runapi.ai/v1/uploads \
  -H "Authorization: Bearer $RUNAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"bytes":1048576,"filename":"archive.bin","mime_type":"application/octet-stream","purpose":"user_data"}' \
  | jq -r .id)

PART_ID=$(curl -sS "https://runapi.ai/v1/uploads/$UPLOAD_ID/parts" \
  -H "Authorization: Bearer $RUNAPI_API_KEY" \
  -F [email protected] | jq -r .id)

curl -sS "https://runapi.ai/v1/uploads/$UPLOAD_ID/complete" \
  -H "Authorization: Bearer $RUNAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"part_ids\":[\"$PART_ID\"]}"

Cancel an unfinished Upload with POST /v1/uploads/{upload_id}/cancel. Repeating the same completion intent or cancellation is safe; a competing completion, cancellation, or expiry returns 409 upload_state_conflict when another terminal outcome already won.

CLI and SDK resources

The CLI exposes the complete lifecycle:

SHELL
runapi files create-file knowledge.pdf
runapi files list --order desc
runapi files retrieve file_123
runapi files content file_123 --output knowledge-copy.pdf
runapi files delete file_123

runapi uploads create --bytes 1048576 --filename archive.bin --mime-type application/octet-stream
runapi uploads add-part upload_123 archive.part-01
runapi uploads complete upload_123 --part-id part_123
runapi uploads cancel upload_123

Every Provider Client exposes files and uploads. JavaScript and PHP use createFile / deleteFile / addPart; Python and Ruby use create_file / delete_file / add_part; Go uses CreateFile / DeleteFile / AddPart; Java uses createFile / deleteFile / addPart. List, retrieve, content, create, complete, and cancel follow each language’s normal naming convention. See SDKs for package installation.

Lifecycle behavior

File content is immutable. Deleting a File removes it from active listings immediately and schedules storage cleanup. Upload completion composes Parts only in the supplied order, and a successful completion creates one File. Keep the original Part ID order when retrying an uncertain completion response.