Testing & Sandbox
Use test mode and the skip_verification flag to build and test your integration without real verifications.
Test vs Live mode
Every Stile account has two sets of API keys:
| Key prefix | Mode | Behavior |
|---|---|---|
vk_test_ / pk_test_ | Test | No real verifications are processed. Sessions complete instantly when skip_verification is set. |
vk_live_ / pk_live_ | Live | Real verifications. At least one active webhook endpoint is required before you can create sessions. |
Use test keys for development, CI pipelines, and staging environments. Switch to live keys only when you're ready to verify real users.
Live mode requires webhooks
Creating a verification session with a live key will fail with webhook_required if your account has no active webhook endpoints. Register one in the dashboard or via the Webhook Endpoints API before going live.
The skip_verification flag
In test mode, pass skip_verification: true when creating a session to skip the entire camera/ID scanning flow. The session transitions straight to verified, fires webhooks, and issues a VP token — all without user interaction.
This is useful for:
- Testing webhook handlers end-to-end
- Validating VP token flows and returning-user logic
- Exercising checkout integrations in CI
- Verifying email binding and OTP behavior
curl -X POST https://api.stile.dev/v1/verification_sessions \
-H "Authorization: Bearer vk_test_..." \
-H "Content-Type: application/json" \
-d '{
"type": "age",
"use_case": "alcohol_delivery",
"email": "test@example.com",
"skip_verification": true
}'The response is identical to a real verified session — same shape, same webhook events, same VP token issuance.
Test mode only
The skip_verification flag is ignored in live mode. Attempting to use it with a vk_live_ key will create a normal session that requires full verification.
Local webhook testing
During development your server runs on localhost, which isn't reachable by Stile's webhook infrastructure. Use a tunnel to expose it.
Using ngrok
# 1. Start your local server
npm run dev # listening on port 3000
# 2. In a separate terminal, start ngrok
ngrok http 3000
# 3. Copy the forwarding URL (e.g. https://abc123.ngrok-free.app)
# 4. Register it as a webhook endpoint:
curl -X POST https://api.stile.dev/v1/webhook_endpoints \
-H "Authorization: Bearer vk_test_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://abc123.ngrok-free.app/api/webhooks",
"enabled_events": ["verification_session.verified"]
}'Using Cloudflare Tunnel
# 1. Start your local server
npm run dev # listening on port 3000
# 2. Start the tunnel
cloudflared tunnel --url http://localhost:3000
# 3. Use the generated *.trycloudflare.com URL as your webhook endpointDashboard shortcut
You can also register webhook endpoints directly in the dashboard instead of using the API.
E2E testing with Playwright
The codebase includes a Playwright test suite at apps/e2e/ that covers the full API lifecycle:
- Session creation and status transitions
- VP token issuance and reuse
- Email binding and OTP flows
- Widget rendering and client-side events
Use these tests as a reference when building your own E2E suite. They rely on skip_verification: true to avoid real camera interactions in CI.
Test data cleanup
A few best practices to keep your test environment clean:
- Use unique emails per test run — append a timestamp or UUID (e.g.
test+1712345678@example.com) to avoid collisions with previous runs. - Test sessions expire after 24 hours — unverified test sessions are automatically cleaned up, so you don't need to delete them manually.
- Isolate test data by key — each API key has its own session namespace. Use a dedicated test key for CI to avoid interfering with manual testing.
Related
- Webhooks — setting up webhook endpoints and handling events
- Error Handling — handling API errors and retries
- Returning Users — VP tokens and credential reuse