stile
Guides

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 prefixModeBehavior
vk_test_ / pk_test_TestNo real verifications are processed. Sessions complete instantly when skip_verification is set.
vk_live_ / pk_live_LiveReal 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 endpoint

Dashboard 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.

On this page