Analyze skin images

Upload and analyze skin images using AI to provide skin assessment.

Recent Requests
Log in to see full request history
TimeStatusUser Agent
Retrieving recent requests…
LoadingLoading…
Body Params
images
array of objects
required
length between 1 and 6

Skin images to analyze. A face scan requires exactly 3 (front, left, right); a body scan (hands/feet) takes 1–6 per-region images (e.g. feet: top + sole per side).

images*
file
required

Skin image file (jpeg, png, jpg, webp, max 2MB)

string

Optional unique identifier for the image

string

Optional label for the image

string
enum

Body scans only. The sub-region the user chose to capture in this image (guided capture, e.g. palm vs back of hand, sole vs top of foot). Must be a sub-region of body_part; omit for face scans and for free body capture (the analyzer then infers the region). The user's declared value is authoritative over the inferred one.

string
enum

The skin part being analyzed (defaults to 'face')

Allowed:
uuid | null

For a body add-on (hands/feet): the face scan's returned batch_id. Links the add-on to its face scan so face + body read back as ONE scan — one completion email/notification and one merged result (fetching the face batch_id returns both skin_concerns and body_concerns, and a body add-on id resolves to the face root). Omit for a face/primary scan.

string
enum

The channel through which the analysis was performed (defaults to 'mobile-app' if not provided)

Allowed:
uuid

Optional scan session ID from a QR code flow. When provided, the analysis results will be linked to this session and real-time status updates will be broadcast via WebSocket.

string | null

Optional email for guest/unauthenticated scans

string | null

Optional customer first name. When provided, used instead of guessing from email address.

string | null

Optional customer last name. When provided, used instead of guessing from email address.

string | null
enum

Context in which the scan is being performed. clinical_trial routes the
scan through the dedicated clinical-trial analyzer (grades extra clinical
biomarkers); sent by the clinical-trial participation link. in_store is
a staff-operated walk-in scan run from the vendor dashboard; the customer
resolves to a vendor-customer identity like widget_only.

Allowed:
string | null

Reference of a successful scan PaymentTransaction (purpose=scan), required when the
vendor's scan_payment_bearer is customer AND the request originates from the
embedded scan widget without a batch_id (mobile-capture continuation) and without
scan_context=appointment_booking. See POST /scan-payments/initialize.

Single-use per bundle: the payment covers one analysis AND the product
recommendations generated from it. It is spent once those recommendations
are delivered (POST /skin/care-routine), after which requests carrying the
reference return 402. Until then it stays valid, so a customer whose
recommendations failed can resume without paying twice.

Resuming returns the analysis already paid for. If this reference has
already produced an analysis, that analysis is returned as-is and no new one
is run — submitted images are ignored, and the response is the same shape as
GET /skin/analysis/{batch_id}. Proceed straight to POST /skin/care-routine
with the returned batch_id. Resuming requires email to match the email on
the original payment; a mismatch is treated as a new scan rather than
disclosing the payer's results.

uuid | null

UUID the widget generated at scan start and sent to
POST /scan-payments/initialize. Used solely to prove this request belongs to
the referenced payment — it is matched against the transaction's
skin_image_analysis_batch_id and a mismatch is a 422.

It is NOT the id of the resulting analysis: a new scan is created under its
own server-generated batch_id, returned in the response. Always read the
returned batch_id and use that for POST /skin/care-routine.

uuid | null

Body add-ons only (body_part = hands or feet). The client_batch_id of
the paid face scan this add-on belongs to. For a customer-bears-cost vendor
the add-on then rides on that payment instead of needing its own, so one face
payment covers both hands and feet.

Coverage expires 24h after the face payment (configurable via
FEATURE_SKIN_ANALYSIS_BODY_ADDON_COVERAGE_HOURS). Body captures follow the
face scan within the same sitting, so this only bounds replay; an expired
add-on isn't rejected outright, it just has to pay its own way (402).

string | null

The customer's phone number, collected by the widget's pre-scan form when the
vendor enabled phone collection (collectPhoneNumber on GET /widget/config,
set under categories.collection.collect_phone_number in scan settings). The
widget makes the field required when that toggle is on; this endpoint simply
records what it was given.

Stored per-vendor, against the vendor-customer, for the same reason consent is:
a number given to one brand's widget must not surface in another brand's
customer list. The shared users.phone identity is filled in as well, but only
when it is empty — the newest scan never overwrites a number the customer set
themselves elsewhere.

Formatting is stripped on the way in (+20 10 1234 5678 stores as
+201012345678); a leading + is kept. Deliberately not format-validated —
numbering plans vary by country and the widget is embedded worldwide. Optional
everywhere: omitting it (or sending blank) means "not collected on this
request" and leaves any existing number untouched rather than clearing it.

date-time | null
date-time | null
boolean | null
Responses

Language
Credentials
Bearer
JWT
LoadingLoading…
Response
Click Try It! to start a request and see the response here! Or choose an example:
application/json