Ziex Try-On for developers¶
Ziex Try-On lets a shopper see a garment on their own photo. You add it to a shop in one of two ways:
- The widget on a product page. One script tag and one
TryOn.init(...)call. The shopper's browser talks to the Ziex Try-On API directly; your server is not involved. This is what the WooCommerce plugin and the 1C-Bitrix module do for you. - The API from your own server. You send the shopper's photo and the garment, get a job id, and read the result by polling or from a webhook. Use it when the photos come from your backend, from an app, or from a flow that is not a product page.
The two ways can be combined: the widget on the page, your server reading the same account's jobs.
The API reference is generated from the published OpenAPI document,
/api/v1/openapi.json. Base URL: https://api.ziex-tryon.com.
All API paths start with /api/v1/tryon.
Keys¶
Every request carries a key in the X-API-Key header. There are three kinds, and the difference matters.
| Secret key | Publishable key | Test keys | |
|---|---|---|---|
| Looks like | tryon_… |
pk_… |
tryon_test_… and pk_test_… |
| Where it may live | Your server only | A public page | Your server / a dev stand |
| Works on | Every endpoint | POST /tryon, GET /tryon/status/{job_id}, GET /tryon/attempts/{key}, GET /tryon/result/{job_id}, GET /tryon/domain-check |
Same as the live key it mirrors |
Needs Origin / Referer |
No | Yes, and a bound domain | Yes for pk_test_…; see Local development |
webhook_url in the request |
Allowed | Refused (403 WEBHOOK_NOT_ALLOWED) |
Allowed for tryon_test_… only |
| Shopper's photo | URL or upload | Upload only (422 PHOTO_UPLOAD_REQUIRED for a URL) |
Upload only, both kinds |
| Spends the plan | Yes | Yes | Never |
Secret key (tryon_…)¶
Use it from a server. Never put it in page source, in a mobile app, or in a repository that others can read: the same
key also signs you in to the client portal at https://app.ziex-tryon.com, where your shoppers' photos and results
are visible. A secret key that arrives with a browser Origin header is not refused, but your account marks it with a
warning.
A secret key sees the jobs of your whole account (live jobs only).
Publishable key (pk_…)¶
The only key a public page may carry. It is the same key as your secret key with fewer rights, and it is public by design: anyone can copy it from the page source. So it is fenced in:
- It works only from a browser page: every request must carry
OriginorReferer, and the key must be bound to your shop's domain. The domain,www.and any subdomain are accepted; another website gets403 DOMAIN_NOT_ALLOWED. A key with no bound domain gets403 KEY_NOT_BOUND. - It accepts only the five endpoints listed above, and reads only the jobs that this key created.
- It cannot ask for a webhook:
webhook_urlin the request is403 WEBHOOK_NOT_ALLOWED. - The shopper's photo must be sent as an upload (a data URI), never as a URL. The garment may stay a URL.
- It is limited per (key, client IP): 10 created jobs per 10 minutes.
- It cannot sign in to the portal.
Live and test keys¶
A test key (tryon_test_… secret, pk_test_… publishable) goes through the real API path - the same validation,
image checks, idempotency and answers - but spends no money and no plan: the "try-on" ends in a simulated result after
a few seconds. Test keys have their own isolation: a test key sees only its own test jobs, a live key never sees them,
and a test key cannot sign in to the portal. They are issued by you, in the client portal, up to 3 per account. See
Local development.
The life of a job¶
POST /api/v1/tryonwith the shopper's photo (model_image) and the garment (garment_image). The answer is201with ajob_id, the headerX-Job-Idand theLocationof the status URL. Send anIdempotency-Keyso that a repeated request can never create a second job.- The job is
pendingwhile it waits for a worker, thenprocessing. - It ends as
completed(with aresult_url), orfailed/interrupted(with anerror_codeand a safeerror_message). - You learn the outcome by polling
GET /api/v1/tryon/status/{job_id}, or from a webhook if you gave awebhook_url(secret key only). The widget polls for you.
Every job reaches a final state within 45 minutes, whatever happens. Webhooks are best effort: if yours is down, the status endpoint still tells the truth, so keep polling as the fallback.
If the answer to the POST is lost (a dropped connection, a timeout), do not submit again under a new key: ask
GET /api/v1/tryon/attempts/{idempotency_key} for the job instead. Both pages of the quickstart show the details.
Plan, limits and refunds as you see them¶
- Plan. Your plan gives a number of generations per period. A created job takes one; when the plan is used up,
POST /tryonanswers429 LIMIT_EXCEEDEDwith aRetry-Afteruntil the period resets. The plan figure is enforced with a small tolerance of 10 %. - Rate limits. There are per-IP limits (30 submits a minute, plus nginx's own request rates), a per-key hourly
limit and daily caps (no single key may use more than half of the platform's daily cap). Every
429,409and503carriesRetry-Afterin seconds: wait that long. A server that sends all its shoppers' requests from one address shares one per-IP budget. - Refunds. A job that ends
failedorinterruptedgives its generation back to your plan automatically, shortly after, once, and only in the period it was charged in. Acompletedjob is never refunded. A request that is refused before a job exists (a bad photo, a limit) takes nothing. - Cost. Ziex Try-On never shows what a generation costs us;
cost_creditsin the status is alwaysnull. - Photos. Uploaded photos and results are kept for 180 days and then deleted. Test uploads are kept for 72 hours.
Where to go next¶
| You want to… | Read |
|---|---|
| Put the widget on a page with plain HTML | Quickstart A - bare HTML |
| Submit try-ons from your server | Quickstart B - server-side |
Develop on localhost or a staging host with no cost |
Local development |
Look up widget options, events and update() |
Widget reference |
| Load the widget lazily without losing a try-on in progress | Lazy loading and pickup |
| Allow the widget under a Content Security Policy | Content Security Policy |
| Find every endpoint, field and error | API reference |
| Ask a question | Contact |
More pages cover webhooks, the full error and limit tables, test keys, identifying your integration, compatibility and the changelog, building a plugin, and the privacy text for shops.