Skip to content

API reference

Generated from the published OpenAPI document (/api/v1/openapi.json), version 1.1.0. Server: https://api.ziex-tryon.com. Every error answers ErrorResponse; decide by error.code.

Operations

POST /api/v1/tryon

Submit a virtual try-on job

Submit a try-on: the shopper's photo (model_image) and the garment (garment_image), each a data URI or an http(s) URL — with a publishable key the photo must be an upload. Send an Idempotency-Key: a repeat with it never creates a second job, and a lost answer is found again with GET /api/v1/tryon/attempts/{key}. Then poll GET /api/v1/tryon/status/{job_id} or receive a webhook (webhook_url, secret key only).

Authentication: X-API-Key header (secret or publishable key).

Parameters

Name In Required Type Description
Idempotency-Key header no string, pattern ^[A-Za-z0-9_-]{22,64}$ Optional, recommended: 22–64 characters of A-Z a-z 0-9 _ -, new for every try-on. A repeat with the same key answers the first job (200, Idempotent-Replayed: true) — never a second job or charge. Unique per API key and kind of key.

Request body (application/json): TryOnRequest

Responses

Status Description Headers Error codes
200 A repeat of an earlier submit with the same Idempotency-Key: that job, in its current status. — TryOnResponse Idempotent-Replayed, Location, X-Job-Id, X-Request-ID
201 The job was created. — TryOnResponse Location, X-Job-Id, X-Request-ID
400 Error. error.code is one of:
- INVALID_REQUEST — an image is a malformed data URI or base64. — ErrorResponse
X-Request-ID INVALID_REQUEST
401 Error. error.code is one of:
- INVALID_API_KEY — no X-API-Key, an unknown or revoked key, or a test key while test keys are off.
- KEY_EXPIRED — the key has expired. — ErrorResponse
X-Request-ID INVALID_API_KEY, KEY_EXPIRED
403 Error. error.code is one of:
- KEY_SUSPENDED — the key is suspended.
- CLIENT_SUSPENDED — the account is suspended.
- ORIGIN_REQUIRED — a publishable key without Origin/Referer (it works only from a browser page).
- KEY_NOT_BOUND — a live publishable key with no bound domain.
- DOMAIN_NOT_ALLOWED — the page's origin is not the key's domain (or, for a test key, not in its allowed hosts).
- WEBHOOK_NOT_ALLOWED — webhook_url with a publishable key — use a secret key from your server. — ErrorResponse
X-Request-ID KEY_SUSPENDED, CLIENT_SUSPENDED, ORIGIN_REQUIRED, KEY_NOT_BOUND, DOMAIN_NOT_ALLOWED, WEBHOOK_NOT_ALLOWED
409 Error. error.code is one of:
- IDEMPOTENT_IN_PROGRESS — a submit with this Idempotency-Key is still being processed — repeat with the same key after Retry-After. — ErrorResponse
Retry-After, X-Request-ID IDEMPOTENT_IN_PROGRESS
413 Error. error.code is one of:
- PAYLOAD_TOO_LARGE — the request body is over 12 MB (nginx; no X-Request-ID). — ErrorResponse
PAYLOAD_TOO_LARGE
422 Error. error.code is one of:
- VALIDATION_ERROR — the body or Idempotency-Key is malformed, webhook_url is not a public address, or an image is unsupported, over 10 MB, over 16 megapixels or under 256×256.
- CATEGORY_UNSUPPORTED — the category cannot be tried on now.
- PHOTO_UPLOAD_REQUIRED — the shopper's photo must be an upload (a data URI) with this key, not a URL. — ErrorResponse
X-Request-ID VALIDATION_ERROR, CATEGORY_UNSUPPORTED, PHOTO_UPLOAD_REQUIRED
429 Error. error.code is one of:
- RATE_LIMITED — too many submits: 30 a minute per IP address, 10 per 10 minutes per publishable key and IP (60 for a test key), or the key's hourly limit.
- LIMIT_EXCEEDED — the plan's generations for this period are used up (Retry-After: until the reset).
- DAILY_CAP_REACHED — the day's cap of the platform or of this key is reached (Retry-After: until 00:00 UTC). — ErrorResponse
Retry-After, X-Request-ID RATE_LIMITED, LIMIT_EXCEEDED, DAILY_CAP_REACHED
500 Error. error.code is one of:
- INTERNAL_ERROR — final: if the job had been created it is now failed (its quota comes back); a repeat with the same Idempotency-Key answers that job — a new try needs a new key. — ErrorResponse
INTERNAL_ERROR
502 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API is restarting or unreachable (nginx) — retry later. — ErrorResponse
SERVICE_UNAVAILABLE
503 Error. error.code is one of:
- SUBMIT_UNCONFIRMED — the job exists (X-Job-Id) but may or may not be queued — poll it or look the attempt up; never resubmit under a new key.
- OVERLOADED — busy, nothing was created or charged — repeat the same request with the same Idempotency-Key after Retry-After.
- SERVICE_UNAVAILABLE — the API is temporarily unavailable (nginx) — retry later. — ErrorResponse
Location, Retry-After, X-Job-Id, X-Request-ID SUBMIT_UNCONFIRMED, OVERLOADED, SERVICE_UNAVAILABLE
504 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API did not answer in time (nginx). — ErrorResponse
SERVICE_UNAVAILABLE

GET /api/v1/tryon/attempts/{idempotency_key}

Find the job of a submit by its Idempotency-Key

Find the job a submit created, by the Idempotency-Key it carried — for when the answer to the POST was lost. Scoped to this API key and kind of key. A 404 is final only about 2 minutes after the submit was sent.

Authentication: X-API-Key header (secret or publishable key).

Parameters

Name In Required Type Description
idempotency_key path yes string

Responses

Status Description Headers Error codes
200 The job created by that submit. — TryOnStatusResponse Location, X-Job-Id, X-Request-ID
401 Error. error.code is one of:
- INVALID_API_KEY — no X-API-Key, an unknown or revoked key, or a test key while test keys are off.
- KEY_EXPIRED — the key has expired. — ErrorResponse
X-Request-ID INVALID_API_KEY, KEY_EXPIRED
403 Error. error.code is one of:
- KEY_SUSPENDED — the key is suspended.
- CLIENT_SUSPENDED — the account is suspended.
- ORIGIN_REQUIRED — a publishable key without Origin/Referer (it works only from a browser page).
- KEY_NOT_BOUND — a live publishable key with no bound domain.
- DOMAIN_NOT_ALLOWED — the page's origin is not the key's domain (or, for a test key, not in its allowed hosts). — ErrorResponse
X-Request-ID KEY_SUSPENDED, CLIENT_SUSPENDED, ORIGIN_REQUIRED, KEY_NOT_BOUND, DOMAIN_NOT_ALLOWED
404 Error. error.code is one of:
- NOT_FOUND — no try-on was created with this key — not final until about 2 minutes after the submit was sent. — ErrorResponse
X-Request-ID NOT_FOUND
409 Error. error.code is one of:
- IDEMPOTENT_IN_PROGRESS — the submit is still being processed — ask again after Retry-After. — ErrorResponse
Retry-After, X-Request-ID IDEMPOTENT_IN_PROGRESS
413 Error. error.code is one of:
- PAYLOAD_TOO_LARGE — the request body is over 12 MB (nginx; no X-Request-ID). — ErrorResponse
PAYLOAD_TOO_LARGE
422 Error. error.code is one of:
- VALIDATION_ERROR — the key is not 22–64 characters of A-Z a-z 0-9 _ -. — ErrorResponse
X-Request-ID VALIDATION_ERROR
429 Error. error.code is one of:
- RATE_LIMITED — nginx's per-IP rate of this path was exceeded (Retry-After: 1). — ErrorResponse
Retry-After, X-Request-ID RATE_LIMITED
502 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API is restarting or unreachable (nginx) — retry later. — ErrorResponse
SERVICE_UNAVAILABLE
503 Error. error.code is one of:
- ATTEMPT_LOOKUP_UNAVAILABLE — cannot tell now whether the submit is running — ask again after Retry-After.
- SERVICE_UNAVAILABLE — the API is temporarily unavailable (nginx) — retry later. — ErrorResponse
Retry-After, X-Request-ID ATTEMPT_LOOKUP_UNAVAILABLE, SERVICE_UNAVAILABLE
504 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API did not answer in time (nginx). — ErrorResponse
SERVICE_UNAVAILABLE

GET /api/v1/tryon/capabilities

What the model can try on — categories, labels, unsupported items, photo tips

What the service can try on: the categories (labels and examples in English and Russian), auto, the items it cannot try on and photo tips for the shopper. No key; a cache may keep it 5 minutes.

Authentication: None — no key.

Responses

Status Description Headers Error codes
200 The capabilities document. — CapabilitiesDocument Cache-Control, X-Request-ID
413 Error. error.code is one of:
- PAYLOAD_TOO_LARGE — the request body is over 12 MB (nginx; no X-Request-ID). — ErrorResponse
PAYLOAD_TOO_LARGE
429 Error. error.code is one of:
- RATE_LIMITED — nginx's per-IP rate of this path was exceeded (Retry-After: 1). — ErrorResponse
Retry-After, X-Request-ID RATE_LIMITED
502 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API is restarting or unreachable (nginx) — retry later. — ErrorResponse
SERVICE_UNAVAILABLE
503 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API is temporarily unavailable (nginx) — retry later. — ErrorResponse
Retry-After, X-Request-ID SERVICE_UNAVAILABLE
504 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API did not answer in time (nginx). — ErrorResponse
SERVICE_UNAVAILABLE

GET /api/v1/tryon/domain-check

Verify domain is whitelisted for this API key

Whether this key may be used on the calling page (Origin/Referer) and whether its plan still has generations. A publishable key gets only limit_exceeded.

Authentication: X-API-Key header (secret or publishable key).

Responses

Status Description Headers Error codes
200 The key may be used here. — DomainCheckResponse X-Request-ID
401 Error. error.code is one of:
- INVALID_API_KEY — no X-API-Key, an unknown or revoked key, or a test key while test keys are off.
- KEY_EXPIRED — the key has expired. — ErrorResponse
X-Request-ID INVALID_API_KEY, KEY_EXPIRED
403 Error. error.code is one of:
- KEY_SUSPENDED — the key is suspended.
- CLIENT_SUSPENDED — the account is suspended.
- ORIGIN_REQUIRED — a publishable key without Origin/Referer (it works only from a browser page).
- KEY_NOT_BOUND — a live publishable key with no bound domain.
- DOMAIN_NOT_ALLOWED — the page's origin is not the key's domain (or, for a test key, not in its allowed hosts). — ErrorResponse
X-Request-ID KEY_SUSPENDED, CLIENT_SUSPENDED, ORIGIN_REQUIRED, KEY_NOT_BOUND, DOMAIN_NOT_ALLOWED
413 Error. error.code is one of:
- PAYLOAD_TOO_LARGE — the request body is over 12 MB (nginx; no X-Request-ID). — ErrorResponse
PAYLOAD_TOO_LARGE
422 Error. error.code is one of:
- VALIDATION_ERROR — a parameter is malformed; details names it. — ErrorResponse
X-Request-ID VALIDATION_ERROR
429 Error. error.code is one of:
- RATE_LIMITED — nginx's per-IP rate of this path was exceeded (Retry-After: 1). — ErrorResponse
Retry-After, X-Request-ID RATE_LIMITED
502 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API is restarting or unreachable (nginx) — retry later. — ErrorResponse
SERVICE_UNAVAILABLE
503 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API is temporarily unavailable (nginx) — retry later. — ErrorResponse
Retry-After, X-Request-ID SERVICE_UNAVAILABLE
504 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API did not answer in time (nginx). — ErrorResponse
SERVICE_UNAVAILABLE

GET /api/v1/tryon/integration

Verify a secret API key and return what a plugin needs to connect a site

Secret key only, from a server: verifies the key, tells whether site_url is the key's domain and returns what a plugin needs — the publishable key, the widget's script URL, the plan's usage and the capabilities.

Authentication: X-API-Key header (secret or publishable key).

Parameters

Name In Required Type Description
site_url query yes string

Responses

Status Description Headers Error codes
200 What a plugin needs to connect this site. — IntegrationResponse X-Request-ID
401 Error. error.code is one of:
- INVALID_API_KEY — no X-API-Key, an unknown or revoked key, or a test key while test keys are off.
- KEY_EXPIRED — the key has expired. — ErrorResponse
X-Request-ID INVALID_API_KEY, KEY_EXPIRED
403 Error. error.code is one of:
- KEY_SUSPENDED — the key is suspended.
- CLIENT_SUSPENDED — the account is suspended.
- ORIGIN_REQUIRED — a publishable key without Origin/Referer (it works only from a browser page).
- KEY_NOT_BOUND — a live publishable key with no bound domain.
- DOMAIN_NOT_ALLOWED — the page's origin is not the key's domain (or, for a test key, not in its allowed hosts).
- SECRET_KEY_REQUIRED — a publishable key — this call needs the secret key, from a server. — ErrorResponse
X-Request-ID KEY_SUSPENDED, CLIENT_SUSPENDED, ORIGIN_REQUIRED, KEY_NOT_BOUND, DOMAIN_NOT_ALLOWED, SECRET_KEY_REQUIRED
413 Error. error.code is one of:
- PAYLOAD_TOO_LARGE — the request body is over 12 MB (nginx; no X-Request-ID). — ErrorResponse
PAYLOAD_TOO_LARGE
422 Error. error.code is one of:
- VALIDATION_ERROR — site_url is missing or not an http(s) URL. — ErrorResponse
X-Request-ID VALIDATION_ERROR
429 Error. error.code is one of:
- RATE_LIMITED — nginx's per-IP rate of this path was exceeded (Retry-After: 1). — ErrorResponse
Retry-After, X-Request-ID RATE_LIMITED
502 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API is restarting or unreachable (nginx) — retry later. — ErrorResponse
SERVICE_UNAVAILABLE
503 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API is temporarily unavailable (nginx) — retry later. — ErrorResponse
Retry-After, X-Request-ID SERVICE_UNAVAILABLE
504 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API did not answer in time (nginx). — ErrorResponse
SERVICE_UNAVAILABLE

GET /api/v1/tryon/jobs

List the jobs of the calling secret API key, newest first (keyset pages)

The jobs of the calling key, newest first: a live secret key lists its live jobs, a test key its test jobs — never another key's. Needs the secret key (a publishable key is refused). Filter by since (ISO 8601, inclusive), status and product_url; page with cursor (the next_cursor of the previous page) and limit (1–100, 50 by default). At most 60 requests a minute per key. Use it to reconcile after missed webhooks.

Authentication: X-API-Key header (secret or publishable key).

Parameters

Name In Required Type Description
since query no string | null
status query no "pending" | "processing" | "completed" | "failed" | "interrupted" | null
product_url query no string | null
cursor query no string | null
limit query no integer

Responses

Status Description Headers Error codes
200 A page of the key's jobs, newest first; next_cursor is null on the last page. — PublicJobList X-Request-ID
401 Error. error.code is one of:
- INVALID_API_KEY — no X-API-Key, an unknown or revoked key, or a test key while test keys are off.
- KEY_EXPIRED — the key has expired. — ErrorResponse
X-Request-ID INVALID_API_KEY, KEY_EXPIRED
403 Error. error.code is one of:
- KEY_SUSPENDED — the key is suspended.
- CLIENT_SUSPENDED — the account is suspended.
- ORIGIN_REQUIRED — a publishable key without Origin/Referer (it works only from a browser page).
- KEY_NOT_BOUND — a live publishable key with no bound domain.
- DOMAIN_NOT_ALLOWED — the page's origin is not the key's domain (or, for a test key, not in its allowed hosts).
- SECRET_KEY_REQUIRED — a publishable key — this call needs the secret key, from a server. — ErrorResponse
X-Request-ID KEY_SUSPENDED, CLIENT_SUSPENDED, ORIGIN_REQUIRED, KEY_NOT_BOUND, DOMAIN_NOT_ALLOWED, SECRET_KEY_REQUIRED
413 Error. error.code is one of:
- PAYLOAD_TOO_LARGE — the request body is over 12 MB (nginx; no X-Request-ID). — ErrorResponse
PAYLOAD_TOO_LARGE
422 Error. error.code is one of:
- VALIDATION_ERROR — since is not an ISO 8601 date-time, cursor is not one this endpoint returned, limit is outside 1–100, or status is not a job status. — ErrorResponse
X-Request-ID VALIDATION_ERROR
429 Error. error.code is one of:
- RATE_LIMITED — more than 60 list requests a minute for this key (Retry-After). — ErrorResponse
Retry-After, X-Request-ID RATE_LIMITED
502 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API is restarting or unreachable (nginx) — retry later. — ErrorResponse
SERVICE_UNAVAILABLE
503 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API is temporarily unavailable (nginx) — retry later. — ErrorResponse
Retry-After, X-Request-ID SERVICE_UNAVAILABLE
504 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API did not answer in time (nginx). — ErrorResponse
SERVICE_UNAVAILABLE

GET /api/v1/tryon/result/{job_id}

Fetch a completed job's result image bytes

The bytes of a completed job's result image — for a gallery that keeps its own copy (the media host sends no CORS headers). Same scope as the status; every «cannot» (no such job, not completed, file gone) is a 404.

Authentication: X-API-Key header (secret or publishable key).

Parameters

Name In Required Type Description
job_id path yes string

Responses

Status Description Headers Error codes
200 The result image. (application/json, image/jpeg, image/png, image/webp) X-Request-ID
400 Error. error.code is one of:
- INVALID_REQUEST — job_id is not a UUID. — ErrorResponse
X-Request-ID INVALID_REQUEST
401 Error. error.code is one of:
- INVALID_API_KEY — no X-API-Key, an unknown or revoked key, or a test key while test keys are off.
- KEY_EXPIRED — the key has expired. — ErrorResponse
X-Request-ID INVALID_API_KEY, KEY_EXPIRED
403 Error. error.code is one of:
- KEY_SUSPENDED — the key is suspended.
- CLIENT_SUSPENDED — the account is suspended.
- ORIGIN_REQUIRED — a publishable key without Origin/Referer (it works only from a browser page).
- KEY_NOT_BOUND — a live publishable key with no bound domain.
- DOMAIN_NOT_ALLOWED — the page's origin is not the key's domain (or, for a test key, not in its allowed hosts). — ErrorResponse
X-Request-ID KEY_SUSPENDED, CLIENT_SUSPENDED, ORIGIN_REQUIRED, KEY_NOT_BOUND, DOMAIN_NOT_ALLOWED
404 Error. error.code is one of:
- NOT_FOUND — no result for this key: no such job, not completed yet, or the file is gone. — ErrorResponse
X-Request-ID NOT_FOUND
413 Error. error.code is one of:
- PAYLOAD_TOO_LARGE — the request body is over 12 MB (nginx; no X-Request-ID). — ErrorResponse
PAYLOAD_TOO_LARGE
422 Error. error.code is one of:
- VALIDATION_ERROR — a parameter is malformed; details names it. — ErrorResponse
X-Request-ID VALIDATION_ERROR
429 Error. error.code is one of:
- RATE_LIMITED — nginx's per-IP rate of this path was exceeded (Retry-After: 1). — ErrorResponse
Retry-After, X-Request-ID RATE_LIMITED
502 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API is restarting or unreachable (nginx) — retry later. — ErrorResponse
SERVICE_UNAVAILABLE
503 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API is temporarily unavailable (nginx) — retry later. — ErrorResponse
Retry-After, X-Request-ID SERVICE_UNAVAILABLE
504 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API did not answer in time (nginx). — ErrorResponse
SERVICE_UNAVAILABLE

GET /api/v1/tryon/status/{job_id}

Check the status of a try-on job

The job's status and progress; result_url once it is completed, error_code and a safe error_message once it is failed or interrupted. Every job is final within 45 minutes. A publishable key sees only its own jobs, a secret key those of its account; a test key only its own test jobs.

Authentication: X-API-Key header (secret or publishable key).

Parameters

Name In Required Type Description
job_id path yes string

Responses

Status Description Headers Error codes
200 The job's status. — TryOnStatusResponse X-Request-ID
400 Error. error.code is one of:
- INVALID_REQUEST — job_id is not a UUID. — ErrorResponse
X-Request-ID INVALID_REQUEST
401 Error. error.code is one of:
- INVALID_API_KEY — no X-API-Key, an unknown or revoked key, or a test key while test keys are off.
- KEY_EXPIRED — the key has expired. — ErrorResponse
X-Request-ID INVALID_API_KEY, KEY_EXPIRED
403 Error. error.code is one of:
- KEY_SUSPENDED — the key is suspended.
- CLIENT_SUSPENDED — the account is suspended.
- ORIGIN_REQUIRED — a publishable key without Origin/Referer (it works only from a browser page).
- KEY_NOT_BOUND — a live publishable key with no bound domain.
- DOMAIN_NOT_ALLOWED — the page's origin is not the key's domain (or, for a test key, not in its allowed hosts). — ErrorResponse
X-Request-ID KEY_SUSPENDED, CLIENT_SUSPENDED, ORIGIN_REQUIRED, KEY_NOT_BOUND, DOMAIN_NOT_ALLOWED
404 Error. error.code is one of:
- NOT_FOUND — no such job for this key. — ErrorResponse
X-Request-ID NOT_FOUND
413 Error. error.code is one of:
- PAYLOAD_TOO_LARGE — the request body is over 12 MB (nginx; no X-Request-ID). — ErrorResponse
PAYLOAD_TOO_LARGE
422 Error. error.code is one of:
- VALIDATION_ERROR — a parameter is malformed; details names it. — ErrorResponse
X-Request-ID VALIDATION_ERROR
429 Error. error.code is one of:
- RATE_LIMITED — nginx's per-IP rate of this path was exceeded (Retry-After: 1). — ErrorResponse
Retry-After, X-Request-ID RATE_LIMITED
502 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API is restarting or unreachable (nginx) — retry later. — ErrorResponse
SERVICE_UNAVAILABLE
503 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API is temporarily unavailable (nginx) — retry later. — ErrorResponse
Retry-After, X-Request-ID SERVICE_UNAVAILABLE
504 Error. error.code is one of:
- SERVICE_UNAVAILABLE — the API did not answer in time (nginx). — ErrorResponse
SERVICE_UNAVAILABLE

Webhooks

WEBHOOK job.completed

A job completed

Sent when a job ends completed: result_url is set.

Delivery is at least once. Attempt 1 goes out as soon as the job ends (normally within about 10 s); a failed attempt is retried after 1 min, 5 min, 30 min and 2 h. The endpoint's retry_count (1–5, default 3) is the number of attempts in all. Retried: a network error, a timeout (10 s for the whole request), any 5xx, 408 and 429; a Retry-After on 429 or 503 is honoured when it is longer, up to 6 h; any other 4xx is final. The same delivery_id is sent on every attempt — deduplicate by it. Webhooks are best effort: reconcile by polling GET /api/v1/tryon/status/{job_id}.

Verify X-TryOn-Signature-V2 over the raw request body exactly as received: sha256= + hex HMAC-SHA256(endpoint secret, X-TryOn-Timestamp + "." + body). Reject a timestamp more than 5 minutes away from your clock. X-TryOn-Signature (HMAC of the body alone) is kept for older receivers.

Authentication: Signed by Ziex Try-On — verify X-TryOn-Signature-V2 (see Webhooks).

Parameters

Name In Required Type Description
X-TryOn-Event header yes string The event name: job.completed.
X-TryOn-Timestamp header yes string Unix seconds of this attempt.
X-TryOn-Signature-V2 header yes string sha256= + hex HMAC-SHA256(secret, <X-TryOn-Timestamp>.<raw body>) — verify this one.
X-TryOn-Signature header yes string sha256= + hex HMAC-SHA256(secret, raw body) — legacy.

Request body (application/json): JobEvent

Responses

Status Description Headers Error codes
200 Any 2xx acknowledges the delivery; answer within 10 s. (application/json)
default Any other answer is a failed attempt: 5xx, 408 and 429 are retried, other 4xx are final.

WEBHOOK job.failed

A job failed

Sent when a job ends failed or interrupted: error_code and error_message are set.

Delivery is at least once. Attempt 1 goes out as soon as the job ends (normally within about 10 s); a failed attempt is retried after 1 min, 5 min, 30 min and 2 h. The endpoint's retry_count (1–5, default 3) is the number of attempts in all. Retried: a network error, a timeout (10 s for the whole request), any 5xx, 408 and 429; a Retry-After on 429 or 503 is honoured when it is longer, up to 6 h; any other 4xx is final. The same delivery_id is sent on every attempt — deduplicate by it. Webhooks are best effort: reconcile by polling GET /api/v1/tryon/status/{job_id}.

Verify X-TryOn-Signature-V2 over the raw request body exactly as received: sha256= + hex HMAC-SHA256(endpoint secret, X-TryOn-Timestamp + "." + body). Reject a timestamp more than 5 minutes away from your clock. X-TryOn-Signature (HMAC of the body alone) is kept for older receivers.

Authentication: Signed by Ziex Try-On — verify X-TryOn-Signature-V2 (see Webhooks).

Parameters

Name In Required Type Description
X-TryOn-Event header yes string The event name: job.failed.
X-TryOn-Timestamp header yes string Unix seconds of this attempt.
X-TryOn-Signature-V2 header yes string sha256= + hex HMAC-SHA256(secret, <X-TryOn-Timestamp>.<raw body>) — verify this one.
X-TryOn-Signature header yes string sha256= + hex HMAC-SHA256(secret, raw body) — legacy.

Request body (application/json): JobEvent

Responses

Status Description Headers Error codes
200 Any 2xx acknowledges the delivery; answer within 10 s. (application/json)
default Any other answer is a failed attempt: 5xx, 408 and 429 are retried, other 4xx are final.

Schemas

AutoCategory

Field Type Required Description
available boolean | null no Present and false only when auto cannot be served now.
id string yes Always auto: the model decides from the garment photo.
label LocalizedText yes

CapabilitiesDocument

What the service can try on: the categories, the auto choice, what it cannot try on, and photo tips.

Field Type Required Description
auto AutoCategory yes
categories array of CapabilityCategory yes
model PublicModel yes
photo_tips LocalizedList yes How to take a photo that works, for the shopper.
unsupported LocalizedList yes Items the model cannot try on, for the shopper.
updated_at string | null no ISO 8601: when the category list last changed.

CapabilityCategory

Field Type Required Description
examples LocalizedText yes
id string yes The platform category id to send as category in POST /api/v1/tryon.
keywords LocalizedList | null no Hints for mapping a shop's own categories to this one.
label LocalizedText yes
new boolean | null no true while the category is newly published.

DomainCheckResponse

Response from GET /api/v1/tryon/domain-check.

Field Type Required Description
allowed boolean yes
client_name string | null no
domain string | null no
limit_exceeded boolean no
limit_remaining integer | null no
mode string no
plan_id string | null no

ErrorBody

Field Type Required Description
code string yes Machine-readable code — decide by it, never by message.
details array of object | null no Only on a 422 VALIDATION_ERROR: one item per invalid field (loc, msg, type).
message string yes Human-readable text; may change at any time.

ErrorResponse

Every error answer of the API, nginx's own answers included.

Field Type Required Description
error ErrorBody yes

IntegrationClientInfo

Field Type Required Description
name string yes

IntegrationKeyInfo

Field Type Required Description
domain string | null no
last_integration string | null no
mode string no
publishable_key string yes

IntegrationManifestEntry

One entry of the integrations manifest (U6): the latest release of a plugin/module, where to get it (null when we hand the archive over ourselves) and its documentation.

Field Type Required Description
docs_url string yes
download_url string | null no
latest_version string yes

IntegrationPlanInfo

Field Type Required Description
generations_limit integer | null no
generations_remaining integer | null no
generations_used integer yes
name string | null no
resets_at string (date-time) | null no

IntegrationPluginInfo

Field Type Required Description
download_url string yes
latest_version string yes

IntegrationResponse

Field Type Required Description
capabilities object yes
client IntegrationClientInfo yes
integrations object of IntegrationManifestEntry yes
key IntegrationKeyInfo yes
plan IntegrationPlanInfo yes
plugin IntegrationPluginInfo yes
site IntegrationSiteInfo yes
widget IntegrationWidgetInfo yes

IntegrationSiteInfo

Field Type Required Description
allowed boolean yes
host string | null no
reason string | null no
url string yes

IntegrationWidgetInfo

Field Type Required Description
api_url string yes
script_url string yes

JobEvent

The body of job.completed and job.failed — one shape for both events.

Field Type Required Description
api_key_id string yes The API key the job was submitted with.
category string | null yes The platform category the job ran with.
created_at string (date-time) yes
delivery_id string yes Stable across every attempt of this delivery — deduplicate by it.
error_code string | null yes GENERATION_FAILED, INVALID_IMAGE, CONTENT_BLOCKED, TIMEOUT or INTERRUPTED; null on success.
error_message string | null yes A safe text for the error code; never the provider's raw error.
event "job.completed" | "job.failed" yes
idempotency_key string | null yes The submit's Idempotency-Key; unique only together with api_key_id and key_kind.
integration string | null yes The name/version label the submit carried, if any.
job_id string yes The job's id (UUID).
key_kind "secret" | "publishable" | null yes Which key of that row submitted it; null when the submit had no Idempotency-Key.
occurred_at string (date-time) yes When the job reached this state.
processing_time_ms integer | null yes
product_title string | null yes
product_url string | null yes
result_url string | null yes The result image; null unless status is completed.
status "completed" | "failed" | "interrupted" yes
test boolean yes true for a job of a test key (sent only to test endpoints).

LocalizedList

Field Type Required Description
en array of string yes
ru array of string yes

LocalizedText

Field Type Required Description
en string yes
ru string yes

PublicJobItem

Field Type Required Description
category string | null no
completed_at string (date-time) | null no
created_at string (date-time) yes
error_code string | null no
integration string | null no
job_id string yes
processing_time_ms integer | null no
product_title string | null no
product_url string | null no
result_url string | null no
status string yes
test boolean yes

PublicJobList

Field Type Required Description
items array of PublicJobItem yes
next_cursor string | null no

PublicModel

Field Type Required Description
id string yes A stable public id of the try-on model; it does not follow the provider.
name string yes

TryOnRequest

Field Type Required Description
category string, pattern ^[a-z0-9][a-z0-9_-]{0,31}$ no Platform category id from GET /api/v1/tryon/capabilities (e.g. tops, outerwear, bottoms, one-pieces) or auto; legacy alias dresses → one-pieces. An id no model covers gets 422 CATEGORY_UNSUPPORTED
garment_image string yes Base64-encoded data URI or image URL of the garment to try on (max 10 MB binary)
integration string | null no Optional label of the plugin or module that sends the try-on, name/version (e.g. woocommerce/1.4.0, bitrix/0.1.0, widget/1.0.0): a lowercase name of up to 32 characters, /, a version of up to 32 of 0-9A-Za-z.+-, 64 in all. Stored on the job and shown in the admin. A value that does not fit — or is not a string — is dropped (null) and the try-on goes ahead; it is never a 422
mode "balanced" | "quality" no Quality mode: quality (default, higher fidelity) or balanced (faster)
model_image string yes Base64-encoded data URI (data:image/png;base64,...) or image URL of the person's photo (max 10 MB binary)
product_title string | null no Optional name of the product being tried on, shown next to the job in the admin and the client portal. Up to 1000 characters are accepted (422 above); control characters and most invisible ones are removed (zero-width joiners, direction marks and tag characters that real text needs are kept), whitespace is collapsed and the text is cut to 200 characters. Nothing visible left, or a value that is not a string -> null
product_url string | null no Optional link to the product page. Up to 4096 characters are accepted (422 above); stored only if it is a plain http(s) URL with a plain host name (no IP literal), no credentials, no whitespace or control characters, none of \ " < > ` { } | ^ and at most 2048 characters — otherwise it is dropped (null) and the try-on goes ahead. With a publishable key the link must also be on the key's bound domain (the domain itself, www. or a subdomain), else it is dropped. A value that is not a string is dropped too
test_outcome "completed" | "failed" no Test keys only: how the simulated try-on ends, completed (default) or failed. Any other value is ignored (completed) and a live key ignores the field altogether - it is never a 422
webhook_url string | null no Optional URL to notify when the job completes or fails

TryOnResponse

Field Type Required Description
estimated_seconds integer | null no
job_id string yes
poll_url string yes
request_id string | null no
status string yes

TryOnStatusResponse

Field Type Required Description
cost_credits number | null no
error_code string | null no
error_message string | null no
job_id string yes
processing_time_ms integer | null no
progress integer | null no
result_url string | null no
status string yes