Skip to main content
Before a user can generate a try-on, they need a usable base image: a clear, full-body-ish photo that has finished preprocessing. This page walks through the whole sequence — checking the profile, uploading a photo, confirming it, waiting for it to become ready, and displaying it back to the user.
Every endpoint on this page is user-scoped. Each request needs both headers:
  • x-api-key: <your_publishable_key> — identifies your store.
  • Authorization: Bearer <access_token> — the signed-in user’s session token from Authentication.
All requests and responses are JSON, with one exception: the direct upload (step 3) is a PUT of raw binary bytes to a signed storage URL.

The upload sequence

1

Check the profile

Call GET /user/profile. If has_base_image is false, the user has no photo yet and you should prompt for one.
2

Request a signed upload URL

Call POST /user/profile/upload-url with the file’s content type and size. You get back a short-lived upload_url and a storage path.
3

Upload the photo directly to storage

PUT the raw image bytes to upload_url. This goes straight to storage — it is not a call to the Souldi API.
4

Confirm the upload

Call PATCH /user/profile with the path from step 2. This kicks off background preprocessing and sets base_image_status to processing.
5

Poll until ready

Poll GET /user/profile until base_image_status is ready. Only then is the user ready to generate a try-on.

GET /user/profile

Fetch the authenticated user’s profile and the status of their base image. Use this both to decide whether the user needs to upload a photo and to poll preprocessing status. Required headers: x-api-key, Authorization: Bearer <access_token> This endpoint takes no body and no parameters.

Response fields

string
The user’s UUID.
string
The user’s email address.
boolean
true once the user has uploaded a base photo, false if they haven’t uploaded one yet. Pair it with base_image_status to know whether that photo is usable.
string
One of processing, ready, or rejected. Drives whether the user can generate (see Polling below).
200 OK
The profile may also include optional body-measurement fields. These are secondary — they’re not required for the upload or generation flow, so you can safely ignore them.

POST /user/profile/upload-url

Get a short-lived signed URL that lets you upload a photo directly to storage, keeping the file off the Souldi API path entirely. Required headers: x-api-key, Authorization: Bearer <access_token>

Body parameters

Response fields

string
A pre-signed URL. PUT your raw image bytes here (step 3). It expires quickly, so upload right away.
string
The storage path of the uploaded file. Pass this to PATCH /user/profile to confirm the upload.
200 OK

PUT {upload_url}

Upload the raw image bytes directly to storage using the upload_url from the previous step.
This PUT targets the signed storage URL returned above — not a Souldi API path. Do not send x-api-key or Authorization headers here; the signed URL already authorizes the upload.

Headers

The request body is the raw binary file (not JSON, not multipart).
Storage returns a 200 or 201 on success with no JSON body to read. If the PUT fails, request a fresh upload_url and retry — signed URLs are short-lived.

PATCH /user/profile

Confirm the uploaded image and trigger preprocessing. This is what actually attaches the photo to the user’s profile. Required headers: x-api-key, Authorization: Bearer <access_token>

Body parameters

The response is the updated profile, with base_image_status now processing.
200 OK
Confirming kicks off background preprocessing — for example, removing the background and preparing the model image used for generation. The status becomes ready when it finishes, or rejected if the photo is unusable. You can call PATCH /user/profile again later with a new path to replace the photo.

GET /user/signed_user_image_url

Get a short-lived signed URL to display the user’s stored image in the browser — for example, to show their current photo before they generate. Required headers: x-api-key, Authorization: Bearer <access_token>

Query parameters

Response fields

string
The user’s UUID.
string
A temporary signed URL pointing at the requested image. It has a short expiry, so request a fresh one each time you render rather than caching it.
200 OK
Requesting variant=no_bg before preprocessing has produced the background-removed image returns 404. Wait until base_image_status is ready before requesting the no_bg variant.

Polling: wait for ready

After PATCH /user/profile, poll GET /user/profile until base_image_status is ready before attempting generation. A try-on request is rejected while the image is still processing, and a rejected status means the user must upload a different photo.
A simple polling loop, mirroring what the official widget does — it waits up to about 2 minutes, checking every few seconds:
Poll until ready
Surface a friendly “preparing your photo…” state to the user while you poll. Most photos finish well within the window.

Next steps

Generate a try-on

Once base_image_status is ready, send garment URL(s) to start a try-on job and track it to completion.