Skip to main content
Upload a local image file to Samsa and get an image_id. Use the image_id as the source image of a Magic Edit, img2img, variations, resize, upscale, background removal, vectorization, or an image-to-video generation. The MCP server has the same flow as two tools, prepare_image_upload and complete_image_upload — see MCP tools. Uploads are free — they cost no credits.

The three steps

1

Prepare

Call POST /images/uploads/prepare with the filename, the content_type, and the exact file size in size_bytes. The response gives you the image_id and a presigned upload_url.
2

PUT the file

PUT the raw file bytes to upload_url with the same Content-Type. Do not send an Authorization header to this URL.
3

Complete

Call POST /images/uploads/{image_id}/complete within the hour. Samsa verifies the file and returns the image with its measured width and height. The image_id is usable from now on.
curl --data-binary @file sends the real file length, so it always matches size_bytes when you measured the same file.

Limits

The file must be the format you declared in content_type. width and height are optional hints at prepare: Samsa uses them only to refuse an image over 32 MP early. The stored dimensions are always measured from the uploaded bytes. An upload that is never completed is discarded after its URL expires.

Lifecycle and errors

  • Not usable before complete. Until complete succeeds, the image_id returns 404 not_found everywhere.
  • Complete is idempotent. Calling it again returns the same result and changes nothing. A later PUT to the same upload_url does not replace a completed image.
  • 422 validation_error — there is no file yet, or the file is empty, has a different size than size_bytes, is too large, cannot be read, is a different format, or is over 32 MP. Samsa discards a refused file: PUT a valid file to the same upload_url while it is still valid, then call complete again.
  • 404 not_found — the image_id is unknown, expired, belongs to another user, or was not created by prepare.
  • 409 upload_in_progress — another complete call for the same upload is running. Retry in a few seconds; if it continues for minutes, prepare a new upload.
  • 429 too_many_pending_uploads — you have 20 uploads awaiting completion. Complete them, or wait until unfinished ones expire (see Retry-After).

Scope and ownership

Both endpoints accept a key with any one of the images.edit, images.transform, or videos.generate scopes — the scopes of the operations that take a source image_id. There is no separate upload scope, so existing keys work. A key with none of the three gets 403 missing_scope. The uploaded image belongs to the calling user — the API key’s creator, or the user of an OAuth token. Other members of your organization cannot use its image_id.

Provenance

An uploaded image is not marked as AI-generated: Samsa did not produce it. An image that a Samsa operation produces from an upload is an AI-modified output and is marked like every other edit — see Content provenance.