Skip to navigation

Test mode

Build and test your integration with a test key. Jobs run the full lifecycle, return fixture results and charge nothing.

A test key starts with pk_test_. A live key starts with pk_live_. Both use the same header, the same base URL and the same operations, so your integration code does not change between them. Only the key does.

Test mode is available only where it is turned on for your account. When it is, the API keys page of the Platform shows a Live / Test switch, and the create form lets you choose the key’s environment. Keys created under Test have a TEST badge.

Same lifecycle, fixture results

A test job goes through the same steps as a live job. It is queued, picked up, moves to running, settles, writes its result assets and expires on the same schedule. Polling, Retry-After, idempotency and result downloads behave as they do for live jobs.

Only the analysis is different. A test job never runs the real analysis. It returns a fixed fixture result instead:

ProductFixture result
Skin Analysisevery concern at a fixed score, and a fixed overall score and face quality, with small placeholder mask images
Makeup try-onone PNG the size of your input, with a fixed stripe pattern
Hair try-onone PNG the size of your input, with a fixed stripe pattern

The values and image sizes are the same every time. The image bytes can change between releases, so compare values and shapes, not image bytes. Fixture images are placeholders, not a realistic preview.

What is not charged

A test job places no credit hold and moves no balance, whatever its outcome. Test usage does not appear in your live usage figures. Test keys and test jobs belong to a separate test environment of your account.

Telling test from live

While test mode is on, every Job and Asset carries livemode:

{
"id": "job_...",
"status": "succeeded",
"livemode": false
}

false means a test object. true means a live one. Where test mode is off, the field is left out.

Both SDKs expose it as livemode on a job and an asset, and it is None (Python) or null (TypeScript) when absent. To check which kind of key a client holds without making a request, read client.is_test_mode (Python) or client.isTestMode (TypeScript).

Error responses carry no livemode; the key prefix you sent already tells you which environment answered.

Isolation

The two environments cannot see each other. A test key reading a live job id or asset id gets 404, as if the id did not exist, and a live key reading a test id does too. An idempotency key used with a test key does not replay a live job.

Choosing an outcome with a magic image

By default a test job succeeds. To get another outcome, upload one of the magic images below as the job’s input. The service recognises the exact bytes of each file. Download the file and upload it unchanged; any re-encoding gives a different file and the default outcome.

ScenarioImageSHA-256What happens
succeededsucceeded.pngb924ad8177d49670aeecc725f8872c173e80391d9935d6daffe6e8b30cf145afThe job succeeds with the fixture result. Any other image does the same.
input_unprocessableinput_unprocessable.png8435773607d1587beb9a3b1e72692e1edf138aeba62b9e374ae98d5597e23b02The job fails with INPUT_UNPROCESSABLE, as for a photo with no usable face.
processing_failedprocessing_failed.png1b50094df98ac57e3f15bc6008119e927cee88c891d597dbb6a8a0a7ceb015bcThe job fails with PROCESSING_FAILED.
slowslow.png065a7bdd98cfaa94a68a7aac3f9849af8a7ae445a81bb72444e359ddacd2b8eeThe job stays running for a few seconds (5 by default), then succeeds. Use it to test your polling and timeouts.
concern_unavailableconcern_unavailable.png8b28b8f21922a774af125dc4fc24a0c3df10ebe489aff9575e747b5b6ec90eaaSkin Analysis only: the job succeeds, but the wrinkles concern is reported as not measured.

Each image is a plain 64×64 square of one colour. If a job has several inputs, the first magic one decides the scenario.

A magic image only selects a scenario for a test key. Uploaded with a live key, it is an ordinary image and runs the real analysis.

Limits and retention

Test keys have their own rate-limit and queue buckets, so test traffic never uses up your live limits. Test jobs and assets are kept for the same time as live ones and are deleted on the same schedule.