POST/api/v1/uploads
Presign a single PUT, or start a multipart upload, for a file (step 1 of creating an asset with a file)
PUT the file's bytes to upload_url with headers, then create the asset with file.upload_id (or attach it to an existing asset with POST /assets/{id}/files). A single PUT carries up to 5 GiB. With multipart: true (required above 5 GiB, allowed from 5 MiB, up to 5 TiB) the answer has method: MULTIPART, no upload_url or headers, and multipart: the server-chosen part_size_bytes and part_count. Sign the parts' URLs with POST /uploads/{id}/parts, PUT each part, then POST /uploads/{id}/complete.
Scopes: assets:write
Parameters
Idempotency-Keyheader · stringMakes a retry safe: the same key and request within 24 hours replays the first response. 1–255 characters.
Request bodyCreateUploadRequest
filenamestringrequiredThe file's name; its extension is what slots match on.
content_typestringrequiredThe MIME type the PUT will send.
size_bytesintegerrequiredThe exact size of the file. Required: a single PUT's URL is bound to it, and a multipart upload is checked against it when completed. At most 5 GiB for a single PUT, 5 TiB with
multipart.multipartbooleanUpload in parts (required above 5 GiB, allowed from 5 MiB). The response's
multipartgives the part size and count; sign the parts' URLs with POST /api/v1/uploads/{id}/parts, PUT each part, then POST /api/v1/uploads/{id}/complete. Default false: one PUT.
Response 201Upload
upload_idstring (uuid)requiredupload_urlstring or nullrequiredPUT the file's bytes here, with
headers. Null for a multipart upload: its parts' URLs come frommultipart.parts_url.method"PUT" | "MULTIPART"requiredPUT: one PUT to upload_url. MULTIPART: parts, see
multipart.headersmap of string or nullrequiredHeaders the PUT must send. Null for a multipart upload (a part's PUT needs none).
url_expires_atstring (date-time) or nullrequiredWhen upload_url stops accepting a new PUT (15 minutes). Null for a multipart upload: each part URL carries its own expiry.
expires_atstring (date-time)requiredWhen the upload must be used by (24 hours).
max_bytesintegerrequiredstatus"pending"requiredmultipartUploadMultipart or nullrequiredSet for a multipart upload; null for a single PUT.
part_size_bytesintegerrequiredEvery part is exactly this size except the last, which is the remainder. Chosen by the server: at least 8 MiB, a whole number of MiB, at most 10 000 parts.
part_countintegerrequiredHow many parts: ceil(size_bytes / part_size_bytes). Part numbers run 1..part_count; part n is bytes (n-1)·part_size_bytes onward.
parts_urlstringrequiredWhere to sign the parts' upload URLs (POST,
{ part_numbers }).
Other responses
- 401 unauthenticated — no key, or an unknown, revoked or expired one.
- 403 insufficient-scope — the key lacks a required scope.
- 404 not-found.
- 409 idempotency-in-flight.
- 422 validation (e.g. size_bytes over 5 GiB without
multipart,multipartunder 5 MiB), or idempotency-mismatch. - 429 rate-limited — the key's request budget is spent; wait Retry-After seconds.
- 500 internal.
- 503 storage-unavailable.