Skip to main content
POST
Start an image upload (get a presigned PUT URL)
Step one of the image upload. Send the filename, the content_type (image/jpeg, image/png, or image/webp), and the file’s exact size in size_bytes. The response returns 201 Created with the new image_id, a presigned upload_url (valid 1 hour), its expires_at, the max_bytes limit, and the allowed_content_types. Next, PUT the raw file bytes to upload_url with the same Content-Type and no Authorization header:
Then call POST /images/uploads/{image_id}/complete.
size_bytes is required and must be the exact file size (at most 10,485,760 bytes): it is signed into upload_url, so a PUT of any other length is rejected. You can have at most 20 uploads awaiting completion; above that, prepare returns 429 too_many_pending_uploads. Requires any one of the images.edit, images.transform, or videos.generate scopes. Free.

Authorizations

Authorization
string
header
required

Organization API key (Authorization: Bearer samsa_sk_...) or OAuth 2.1 access token (Authorization: Bearer samsa_at_...).

Body

application/json

POST /images/uploads/prepare body — describe the file you will PUT.

filename
string
required

Original filename. Stored as the image name; never used as the storage key.

Required string length: 1 - 255
content_type
string
required

MIME type of the file — one of: image/jpeg, image/png, image/webp. Send the SAME value as the Content-Type header of the PUT; complete refuses bytes that are a different format.

size_bytes
integer
required

The EXACT size of the file in bytes (at most 10485760). It is signed into upload_url: a PUT of any other length is rejected by storage. curl --data-binary @file sends the file's real length.

Required range: 1 <= x <= 10485760
width
integer | null

Optional width in pixels. Only used to refuse an image over the 32 MP limit early; the stored dimensions are measured from the uploaded bytes at complete.

Required range: x >= 1
height
integer | null

Optional height in pixels (see width).

Required range: x >= 1

Response

Successful Response

201 body for POST /images/uploads/prepare — where and how to PUT the file.

image_id
string<uuid>
required

The new image's id. Send it to POST /images/uploads/{image_id}/complete after the PUT.

upload_url
string
required

Presigned URL. PUT the raw file bytes here with the header Content-Type: <content_type> (no Authorization header).

expires_at
string
required

UTC instant (ISO 8601) after which upload_url stops accepting the PUT (1 hour after prepare).

max_bytes
integer
required

Largest accepted file size in bytes; complete refuses a bigger file.

allowed_content_types
string[]
required

The accepted MIME types.