Test mode
Build and run CI against FaceCard with test keys. Free, separate from live data, and capped.
Test mode lets you build your sign in and run your tests without spending your plan's auths and without mixing test people into your real users. The routes, requests and responses are the same as live. The key decides the mode.
Test keys and live keys
Every key is either live or test. The prefix tells you which:
| Secret key | Publishable key | |
|---|---|---|
| Live | fc_sk_live_ + 32 characters | fc_pk_live_ + 24 characters |
| Test | fc_sk_test_ + 32 characters | fc_pk_test_ + 24 characters |
You choose Live or Test when you create a key in the developer portal. A key keeps its mode for life. To change mode, create a new key. Each mode counts on its own toward your plan's keys per app limit (the Free plan allows 3 live and 3 test keys per app).
Test data is separate
Users, face templates, challenges and sign in events each belong to one mode, taken from the key on the request.
- A test key only creates, matches, lists, gets, verifies and deletes test users. A live key only touches live users.
- The same email can be a live user and a test user of one app at the same time. They are two different users with different ids.
- A challenge only works in the mode that created it. Using a test challenge with a live key (or the reverse) returns
400 challenge_invalid. - A face is only compared with faces of the same mode, so a test enrollment can never sign someone in to your live app.
Free, with caps
Test calls never count toward your monthly auths and never return plan_limit_reached. Instead, each app has its own test mode limits:
| Limit | Value | Error |
|---|---|---|
| Test users at once | 100 per app | 403 test_limit_reached on enroll |
| Enrolls per day | 200 per app | 429 rate_limited with Retry-After |
| Matches per day | 1,000 per app | 429 rate_limited with Retry-After |
| Email code requests per day | 200 per app | 429 rate_limited with Retry-After |
The per minute limits, the per IP limits, the failed match limit and the per user lockout work exactly as in live mode. See Plans and limits.
If you reach 100 test users, delete some (DELETE /v1/users/{id} with your test secret key), or wait for the cleanup below.
Test users are deleted after 30 days
A test user, with their face templates, consents and sign in events, is deleted 30 days after they enrolled. A daily job does this. Test mode is for building and CI. Never use it for real sign ins.
No email, and the code is 000000
Test mode never sends email. For a test user, POST /v1/email-codes stores the fixed code 000000 instead of a random one, and sends nothing. Verify with 000000.
Everything else about email code sign in works as in live mode: the code still expires, works once, dies after 5 wrong attempts, and counts toward the per user lockout. The same applies to the email change code on POST /v1/me/email.
Localhost origins are accepted
A publishable key must normally be used from an origin on your app's allow list. A test publishable key also accepts any http://localhost:<port> and http://127.0.0.1:<port> origin, without adding it to the allow list, so local development and CI just work. Live keys still need an exact match. See Apps and keys.
Tokens carry livemode
Every user token has a livemode claim: true for a live key, false for a test key. A token issued before test mode existed has no livemode claim and counts as live.
Test tokens also have their own audience. A live token's aud is ["facecard", "<app id>"]; a test token's is ["facecard_test", "<app id>"]. So a verifier that only accepts the facecard audience, such as an SDK older than 4.4.0 or JWKS code written before test mode, rejects every test token instead of letting it through.
A test token must never pass a live server check. If the token's mode differs from the secret key's mode:
POST /v1/tokens/verifyanswers{ "valid": false, "reason": "mode_mismatch" }.- The SDK's
verifyTokenOfflineandtokens.verifyreturn{ valid: false, reason: 'mode_mismatch' }. The SDK reads the mode from your secret key prefix.
If you verify tokens with your own JWKS code, require the audience of your mode (facecard in production, facecard_test in test) and check the claim too: treat the token as valid only if (livemode ?? true) equals your key's mode. See User tokens and JWKS.
Usage in test mode
GET /v1/usage reports the mode of the key you call it with. With a test key it returns "livemode": false, your test counts, and "limit": null, because test mode has no plan limit. Test traffic is never added to your live numbers. See usage.
Switch to live keys before launch
Before you go live:
- Create a live publishable key and a live secret key in the portal.
- Replace the
fc_pk_test_...andfc_sk_test_...values in your production settings with the live keys. - Add your production origin to the app's allow list. Test keys' localhost shortcut does not apply to live keys.
- Have your users enroll again. Test users do not exist in live mode.
Keep the test keys for local work and CI.