Skip to main content

Test Mode

Test mode lets you develop and test your Zyphr integration safely. Both notifications and Auth-as-a-Service support test mode with isolated data and restricted behavior.

Test Mode by Product

Zyphr has two test mode systems, each with its own key prefix:

ProductTest Key PrefixWhat Test Mode Does
Notificationszy_test_*Messages are stored but never delivered
Auth-as-a-Serviceza_test_*Users are isolated from production, limited to 10

Auth-as-a-Service Test Mode

When you create an Application, you receive both test and live key pairs:

za_test_pub_xxxx / za_test_sec_xxxx  ← Test keys
za_live_pub_xxxx / za_live_sec_xxxx ← Live keys

Isolated User Pools

Test and live keys operate on completely separate user pools, similar to Stripe's test/live modes:

  • A user registered with za_test_* keys does not exist in the live environment
  • The same email can be registered independently in both test and live
  • Login with test keys only finds test users; login with live keys only finds live users
  • JWTs include an environment_id claim so your backend can verify which environment a token came from
za_test_* keys → Test user pool (isolated, max 10 users)
za_live_* keys → Live user pool (production)

Test Environment Limits

The test environment is limited to 10 users per application. This is intentional — test mode is for integration development, not load testing. If you need more users for testing, use a separate application.

If you exceed the limit, registration returns:

{
"error": {
"code": "test_environment_limit",
"message": "Test environment is limited to 10 users. Current: 10. Use live keys for production.",
"limit": 10,
"current": 10
}
}

Using Test Keys

Set up your development environment to use test keys:

.env.development
ZYPHR_APP_PUBLIC_KEY=za_test_pub_xxxx
ZYPHR_APP_SECRET_KEY=za_test_sec_xxxx
.env.production
ZYPHR_APP_PUBLIC_KEY=za_live_pub_xxxx
ZYPHR_APP_SECRET_KEY=za_live_sec_xxxx

Register and login calls work identically with both key types:

# Register a test user — this user only exists in the test environment
curl -X POST https://api.zyphr.dev/v1/auth/users/register \
-H "X-Application-Key: za_test_pub_xxxx" \
-H "X-Application-Secret: za_test_sec_xxxx" \
-H "Content-Type: application/json" \
-d '{"email": "dev@example.com", "password": "SecurePass123!"}'

What Carries Over

All application-level configuration is shared between test and live environments:

  • Password policy
  • Session duration and refresh token settings
  • OAuth provider configuration
  • Lockout settings
  • Allowed origins and redirect URIs

Only the user data (registrations, sessions, OAuth connections, magic links) is isolated per environment.

Dashboard Visibility

In the dashboard's Users tab for an application:

  • Each user shows a Test (yellow) or Live (green) badge
  • Use the All / Live / Test filter to view users by environment
  • The test filter shows a reminder of the 10-user limit

Notifications Test Mode

When you use a zy_test_* API key for notifications:

  1. Messages are stored - All messages are saved to the database
  2. No delivery - Messages skip the actual delivery providers (SES, FCM, Twilio)
  3. Mock responses - You receive realistic API responses
  4. Events are tracked - Status changes and events are recorded
  5. Dashboard visibility - View test messages in the dashboard

Using Notification Test Mode

Create a Test API Key

  1. Go to SettingsAPI Keys
  2. Click Create API Key
  3. Select Test as the key type
  4. Copy your zy_test_* key

Send Test Messages

Use your test key in API requests:

curl -X POST https://api.zyphr.dev/v1/emails \
-H "X-API-Key: zy_test_your_key" \
-H "Content-Type: application/json" \
-d '{
"to": "anyone@example.com",
"subject": "Test Email",
"html": "<p>This won'\''t actually be delivered!</p>"
}'

Response includes is_test: true:

{
"data": {
"id": "msg_test123",
"to": "anyone@example.com",
"status": "sent",
"is_test": true,
"created_at": "2024-01-15T10:30:00Z"
}
}

What Happens to Test Messages

Email

  • Stored in database with is_test = true
  • Status progresses: queuedsendingsent
  • No email is sent via SES
  • Mock message ID: test_mock_<message_id>

Push Notifications

  • Stored with is_test = true
  • Status: queuedsendingsent
  • No push sent via FCM/APNs
  • Mock message ID generated

SMS

  • Stored with is_test = true
  • Status: queuedsendingsent
  • No SMS sent via Twilio
  • Mock segment count: 1

In-App Notifications

  • Created normally in the inbox
  • Visible to subscribers if they exist
  • Marked with is_test = true

Identifying Test Messages

In API Responses

All responses include the is_test flag:

{
"data": {
"id": "msg_123",
"is_test": true
}
}

In the Dashboard

Test messages are clearly labeled in the dashboard with a "Test" badge. You can filter to show only test or only live messages.

In the Database

Query test messages:

SELECT * FROM messages WHERE is_test = true;

Best Practices

Use Test Keys in Development

Set up your development environment to always use test keys:

.env.development
ZYPHR_API_KEY=zy_test_development_key
.env.production
ZYPHR_API_KEY=zy_live_production_key

Test All Channels

Verify your integration works for all channels you plan to use:

// Test email
await zyphr.emails.send({
to: 'test@example.com',
subject: 'Test',
html: '<p>Test</p>'
});

// Test push
await zyphr.push.send({
userId: 'test_user',
title: 'Test Push',
body: 'Test notification'
});

// Test SMS
await zyphr.sms.send({
to: '+14155551234',
body: 'Test SMS'
});

Verify Webhook Handling

Test webhooks work the same in test mode. Configure a webhook endpoint and verify you receive events:

{
"event": "message.sent",
"data": {
"message_id": "msg_test123",
"is_test": true
}
}

Automatic Cleanup

Test data is automatically cleaned up after 30 days to keep your account tidy. If you need longer retention for testing, contact support.

Switching to Production

When you're ready to go live:

Notifications

  1. Verify your domain (required for email)
  2. Configure push credentials (FCM, APNs)
  3. Configure SMS credentials (Twilio)
  4. Swap your test key for a live key
  5. Test with a single real recipient first
- ZYPHR_API_KEY=zy_test_your_key
+ ZYPHR_API_KEY=zy_live_your_key

Auth-as-a-Service

  1. Verify your integration works with test keys
  2. Swap to live application keys
  3. Your first live user registration creates the production user pool
- ZYPHR_APP_PUBLIC_KEY=za_test_pub_xxxx
- ZYPHR_APP_SECRET_KEY=za_test_sec_xxxx
+ ZYPHR_APP_PUBLIC_KEY=za_live_pub_xxxx
+ ZYPHR_APP_SECRET_KEY=za_live_sec_xxxx
info

Test users are not migrated to the live environment. Your live user pool starts empty — this is by design. Users must register fresh with the live keys.

FAQ

Can I mix test and live keys?

Each API request uses exactly one key. You cannot mix test and live operations in a single request. For Auth-as-a-Service, test and live keys access completely separate user pools.

Do test messages count against my quota?

Test messages do not count against your monthly message quota.

Do test auth users count against my MAU quota?

No. Test environment activity (registrations, logins, token refreshes, OAuth, magic links) does not count toward your auth request quota or MAU tracking. Test mode is completely free to use.

Can I test webhooks?

Yes! Webhooks fire for test messages just like live messages. The webhook payload includes is_test: true. Auth webhooks (user.created, user.login, etc.) fire for both test and live environments.

Are test and live auth users completely separate?

Yes. A user registered with za_test_* keys cannot log in with za_live_* keys and vice versa. The same email can be registered independently in both environments. This mirrors Stripe's test/live isolation model.

Why is the test environment limited to 10 users?

The test environment is designed for integration development and verification, not for staging or load testing. If you need a larger user pool for QA, create a separate Application dedicated to that purpose.

How do I clean up old test data?

Test notification data older than 30 days is automatically deleted. For Auth-as-a-Service test users, you can delete them individually via the dashboard or API. For immediate cleanup, contact support.