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.
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.
Headers
The request body is the raw binary file (not JSON, not multipart).
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
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
Polling: wait for ready
A simple polling loop, mirroring what the official widget does — it waits up to
about 2 minutes, checking every few seconds:
Poll until ready
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.