Skip to main content

Reserve an upload and get a PUT URL

POST /v1/uploads

Reserves a private object for this org and returns a time-limited PUT URL. PUT exactly size_bytes with content_type, then pass ref to a job as input_ref. Objects are private to the org and are only ever read by the worker.

Credential. An API key (jean_live_…) or a dashboard session token.

curl --fail-with-body -X POST "https://api-833252724876.us-central1.run.app/v1/uploads" \
-H "Authorization: Bearer $JEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"kind": "predictions",
"size_bytes": 2048
}'

Body

FieldTypeRequiredNotes
kind"outputs", "panel", "predictions"yespredictions (JSON list for POST /v1/evals), outputs (JSONL), panel (CSV).
content_type"application/json", "application/x-ndjson", "text/csv"noDefault "application/json".
size_bytesintegeryesExact size you will PUT. Range: −∞–209715200.

Response · 201

{
"id": "upl_a1b2c3d4e5f6g7h8i9j0",
"org_id": "org_k3j2h4g5f6d7s8a9q0w1",
"kind": "predictions",
"content_type": "application/json",
"size_bytes": 2048,
"ref": "upload:upl_a1b2c3d4e5f6g7h8i9j0",
"put_url": "https://storage.googleapis.com/jean-uploads/...",
"put_headers": {
"Content-Type": "application/json"
},
"expires_at": "2026-01-15T09:30:00Z"
}

Errors

StatusMeaning
401Unauthenticated, invalid token or revoked key.
403Forbidden, session required or org required.
422Validation failed.
429Quota or rate limit exceeded; error.details says which, and when.
500Internal error; quote error.request_id when reporting it.

Every one carries the same envelope.

API overview · Full contract