Local development¶
Build and test an integration on your own machine, a staging host or a stand, without spending money or plan generations: use test keys. A test job goes through the real API - the same validation, image checks, idempotency and answers - and ends in a simulated result.
Get a test key¶
You issue test keys yourself, in the client portal:
- Sign in at
https://app.ziex-tryon.comwith your live secret key (tryon_…). - Open the API Keys page and use the test keys block. Create a key; its secret (
tryon_test_…) is shown once - copy it then. The list afterwards shows only the publishable half (pk_test_…). - You can hold up to 3 test keys per account (a fourth is
409 TEST_KEY_LIMIT). To rotate one, delete it and create another.
A test key can not sign in to the portal (401 TEST_KEY_NOT_ALLOWED) - that is why you issue it from the live key's
session and hand the test key to a developer, who never needs the portal.
| Test secret key | Test publishable key | |
|---|---|---|
| Looks like | tryon_test_ + 32 characters |
pk_test_ + 32 characters |
| Use it from | Your server or a local script | A page in a browser |
Needs Origin / Referer |
No | Yes (but no bound domain) |
If test keys are not available for your account, the key is refused as an unknown one (401 INVALID_API_KEY) and the
portal block is hidden.
What a test try-on does¶
Use the API exactly as in Quickstart B, with a test key. What differs:
- No money, no plan. A test job takes no generation, no daily cap and no share of anyone's limits, and is left out of all statistics. It is never refunded because nothing was taken.
- The shopper's photo must be an upload - a data URI - for a test secret key as well as for a publishable key. A
URL is
422 PHOTO_UPLOAD_REQUIRED. The garment may be a URL: nothing is downloaded in test mode. - The result is simulated. After about 3 seconds the job completes with your own uploaded photo as
result_url, or, if that is not possible, with a fixed placeholder image (https://api.ziex-tryon.com/embed/test-result.png). The category is still checked: an unknown one is422 CATEGORY_UNSUPPORTED. - Simulate a failure. Add
"test_outcome": "failed"to the body; the job endsfailedwitherror_codeGENERATION_FAILED. Any other value counts ascompleted. A live key ignores this field. - Isolation. A test key reads only the test jobs of its own key; a live key never sees a test job, and the other way
round. A job of the other mode is
404, not403. - Own limits. 30 submits a minute per IP (counted apart from your live traffic), 60 created jobs per 10 minutes per (test publishable key, IP), and the key's hourly limit (100 by default).
- Files you upload with a test key are deleted after 72 hours.
- The widget shows a TEST ribbon when its key starts with
pk_test_, andGET /api/v1/tryon/domain-checkreturns"mode": "test".
import base64
import uuid
import requests
API = "https://api.ziex-tryon.com/api/v1/tryon"
HEADERS = {"X-API-Key": "tryon_test_YOUR_TEST_KEY", "User-Agent": "shop-example-dev/1.0"}
with open("shopper.jpg", "rb") as f:
photo = "data:image/jpeg;base64," + base64.b64encode(f.read()).decode("ascii")
r = requests.post(
API,
json={
"model_image": photo, # a test key needs an upload
"garment_image": "https://shop.example/images/linen-shirt.jpg",
"category": "tops",
"test_outcome": "completed", # or "failed"
},
headers={**HEADERS, "Idempotency-Key": uuid.uuid4().hex},
timeout=60,
)
print(r.status_code, r.json())
Hosts a test key accepts¶
A browser call always names its page in the Origin (or Referer) header. The key's rule judges that host.
A live key works only on its bound domain (the domain itself, www. and any subdomain). A test key works from:
-
any development host, with no registration:
Host Examples localhostand*.localhostlocalhost,bitrix.localhost*.test,*.local,*.internalshop.test,my-shop.local,stand.internalLoopback and private IP addresses 127.0.0.1,[::1],10.0.0.5,172.16.4.2,192.168.1.10The opaque origin nulla page opened from file://, a sandboxed iframe -
any domain registered for your account (with
www.and subdomains); - any host in the key's own
allowed_hostslist (up to 20), edited in the portal's test keys block.
Anything else is 403 DOMAIN_NOT_ALLOWED. A test publishable key with no Origin or Referer at all is
403 ORIGIN_REQUIRED.
A live key used from a development host is refused with 403 DOMAIN_NOT_ALLOWED - on a local machine, use a test
key.
How a host is compared¶
The same rule applies to the Origin, to allowed_hosts and to the site address you send to GET /integration:
- The port is ignored.
http://localhost:3000andhttp://localhost:8080are bothlocalhost. Do not write a port intoallowed_hosts; if you do, it is dropped. - Internationalised names are compared as a browser writes them (UTS #46, punycode).
магазин.рфis stored and matched asxn--80aairftm.xn--p1ai, and the portal shows both. Upper case, a trailing dot and a scheme are removed;straße.debecomesxn--strae-oqa.de, as in a browser. - A name covers its
www.and its subdomains.shop.examplealso admitswww.shop.exampleandstaging.shop.example. Wildcards such as*.shop.exampleare not accepted - the plain name already covers them. - An IP address matches only itself.
203.0.113.5does not admit1.203.0.113.5. - At most 20 entries in
allowed_hosts.
Pages from file://¶
A page opened straight from the disk sends Origin: null. A test key accepts it, so a plain HTML file with a
pk_test_… key works without a web server. A live key does not (403). Serving the same folder from localhost works
too.
Webhooks on your own machine¶
A webhook is never delivered to localhost or a private address. The delivery refuses every address that is not
public (loopback, private ranges, link-local and cloud-metadata addresses, and names that resolve to them), and the
same check runs when you register the address - a webhook_url that is not public is 422 VALIDATION_ERROR. The
refusal is not retried.
Two ways to develop against webhooks:
- A tunnel. Run a tunnelling tool that gives your local port a public HTTPS address, and use that address as
webhook_url. Receivers on a laptop behind a router work this way. - Polling. Skip the webhook while developing and poll
GET /api/v1/tryon/status/{job_id}. A test job completes in a few seconds, so this is the quickest loop.
A per-request webhook_url works with a test secret key and is signed like a live one. Webhook endpoints you
register in the portal have a mode, live or test, chosen when you create them: a test job calls only test
endpoints, and a live job only live ones. A test publishable key cannot send webhook_url at all
(403 WEBHOOK_NOT_ALLOWED).
Worked example: a 1C-Bitrix stand¶
A developer runs a 1C-Bitrix demo on http://bitrix.localhost:8588 and installs the Ziex Try-On module. The module
has to check that its key may be used on this site. It calls GET /api/v1/tryon/integration with the test secret
key and the site address:
curl -sS 'https://api.ziex-tryon.com/api/v1/tryon/integration?site_url=http://bitrix.localhost:8588' \
-H 'X-API-Key: tryon_test_YOUR_TEST_KEY' \
-H 'User-Agent: shop-example-dev/1.0'
{
"key": { "mode": "test", "publishable_key": "pk_test_…", "domain": null },
"site": { "url": "http://bitrix.localhost:8588", "host": "bitrix.localhost", "allowed": true, "reason": null },
"plan": { "name": null, "generations_limit": null, "generations_remaining": null, "generations_used": 0, "resets_at": null }
}
The answer is shortened: it also carries the client name, the widget address and the capabilities document. The port
is ignored and bitrix.localhost is a development host, so site.allowed is true and the module can print the test
publishable key into the page. The widget then runs from bitrix.localhost with pk_test_…, shows the TEST ribbon,
and every try-on ends in a simulated result without touching the plan.
With the same site address and a live key the answer would be site.allowed: false with site.reason dev_host
(DOMAIN_NOT_ALLOWED for a request). When you move from the stand to the real shop, switch the module to the live
secret key and bind the live key to the shop's domain.
Checklist before going live¶
- Replace
pk_test_…with the livepk_…andtryon_test_…with the livetryon_…. - Confirm the live key is bound to the shop's domain: domain check.
- Create live webhook endpoints, or keep per-request
webhook_urlon a public address. - Remove the secret key from anything that runs in a browser.