Skip to content

Test keys

A test key lets you build and check a whole integration - a CMS module, a custom server, the widget on a development stand - without spending money and without waiting for us. A try-on made with a test key goes through the real API path: the same validation, image checks, idempotency and answers as a live key. Only the end is different: it finishes with a simulated result instead of a real generation.

What a test key is

Secret test key Publishable test key
Looks like tryon_test_ + 32 characters pk_test_ + 32 characters
Where it may live Your server or dev stand A page on a development host
Needs Origin / Referer No Yes (but no bound domain)
  • No plan, no money. A test try-on is free. It does not use your plan's quota, does not count against the daily caps and is not billed.
  • Always a simulated result. After a few seconds the job ends completed with a placeholder: either the photo you uploaded or a fixed sample picture. Nothing is generated and no provider is called.
  • It is never a way to a live job. A test key cannot read live jobs, and a live key cannot read test jobs (see What a test key can see).

The shop-facing widget shows a TEST badge in the header of its window when its key is a test key, so nobody mistakes a test page for a real one.

Get a test key

Test keys are issued by you, in the client portal at https://app.ziex-tryon.com:

  1. Sign in with your live secret key. (A test key cannot sign in to the portal: see below.)
  2. Open the API keys page and create a test key. Give it a name and, if you need them, its allowed hosts.
  3. Copy the secret. It is shown once, in the dialog that creates the key. The publishable key (pk_test_…) stays visible in the list.

Rules:

  • Up to 3 test keys per account. Creating a fourth answers 409 TEST_KEY_LIMIT. Delete one to make room.
  • When a new account is created, one test key can be issued with it automatically; its secret is shown once, with the new account.
  • A test key is not rotated. To replace it, delete it and create another.
  • A test key cannot sign in to the portal: the login answers 401 TEST_KEY_NOT_ALLOWED. This is deliberate - a test key must never open the shop's live photos. The shop's owner signs in with the live key, creates test keys and hands one to the developer, who never needs the portal.

Where a test key works

A live publishable key works only from the shop's own domain. A test key is built for development, so it is also accepted from:

  • Development hosts: localhost and *.localhost, loopback addresses (127.0.0.0/8, ::1), private networks (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), and the names *.test, *.local and *.internal.
  • A page with no origin: Origin: null, which is what a file:// page or a sandboxed iframe sends.
  • Any domain of your account, with www. and subdomains.
  • The test key's own allowed hosts - a list you set when you create or edit the key, up to 20 hosts, with www. and subdomains. Put there a staging host such as staging.shop.example. Write a host as a name only; a scheme, a path and a port are removed. An internationalized name such as магазин.рф is stored in its ASCII form.

A live key used from a development host is refused. Use a test key there. See Local development for the setup step by step.

GET /api/v1/tryon/integration accepts a test key too. It answers with key.mode set to "test" and an empty plan, and site.allowed follows the same host rules, so a CMS module can verify a test key on a local site. GET /api/v1/tryon/domain-check returns mode (live or test), which a publishable key may read.

Send a test try-on

Use the API as for a live key. Three things differ.

1. The photo must be an upload. Both kinds of test key require model_image to be a data URI. A URL answers 422 PHOTO_UPLOAD_REQUIRED. The garment image may stay a URL. Nothing fetches a URL in test mode.

2. You can choose how it ends. Add test_outcome to the body:

test_outcome Result
completed (default) The job ends completed.
failed The job ends failed with error_code GENERATION_FAILED and the message TEST: simulated failure.

Any other value is treated as completed and never refuses the request. A live key ignores the field: it is not a free way to fail a real job.

3. Webhooks. webhook_url works with a test secret key and is signed the same way as for a live job (see Webhooks); a pk_test_… key that sends it gets 403 WEBHOOK_NOT_ALLOWED, like any publishable key.

curl -X POST https://api.ziex-tryon.com/api/v1/tryon \
  -H "X-API-Key: tryon_test_YOUR_TEST_KEY" \
  -H "Idempotency-Key: 8d1f0a52c7e94b6f9a3e5c21d4b70f88" \
  -H "User-Agent: MyShop/1.0" \
  -H "Content-Type: application/json" \
  -d '{
        "model_image": "data:image/jpeg;base64,/9j/4AAQSkZJRg...",
        "garment_image": "https://shop.example/images/linen-shirt.jpg",
        "category": "tops",
        "test_outcome": "completed"
      }'

Then follow the job as usual with GET /api/v1/tryon/status/{job_id}; it ends within a few seconds.

What a test key can see

The two modes never mix, in either direction.

  • A test key - secret or publishable - sees only the test jobs of its own key: GET /api/v1/tryon/status/{job_id}, GET /api/v1/tryon/result/{job_id} and GET /api/v1/tryon/attempts/{key}. A secret test key's job list (GET /api/v1/tryon/jobs) holds only its own test jobs.
  • A live key sees no test job. Asking a live key for a test job's id answers 404 NOT_FOUND, not 403.

A test job carries test: true in a webhook body. Webhook endpoints have a mode too: an endpoint created in mode test receives only the events of test jobs, and an endpoint in mode live receives none of them. Register a separate test endpoint for development. See Webhooks.

Files

The photos of a test job are stored for 72 hours and are then deleted. Live photos are kept for 180 days; test files never are. The result URL of a test job can stop working after that, so do not store it.

Limits

A test key has limits of its own, so test traffic from your office never uses up that office's live budget.

Limit Value
Submits per client address, all test keys 30 per minute (a separate counter from the live one)
pk_test_… per (key, client address) 60 created jobs per 10 minutes (live: 10)
The key's hourly limit The key's own, 100 per hour by default
Plan quota, daily caps None

A refusal carries Retry-After, as on the Limits page.

Moving to live

Nothing in your code changes except the keys: replace the test keys by your live ones, and for the widget use the live pk_… bound to the shop's domain. A page that still carries a test key shows the TEST badge, which is the easy way to notice a key left behind.