Skip to content
Documentation menu

Documentation

Testing in sandbox

Use a test key to build and test your integration end to end without sending real messages or spending balance.

Every test key (otp_test_…) runs in the sandbox. The full flow works exactly as in production, but nothing is delivered and nothing is charged, so you can wire up send and verify with confidence before going live.

What the sandbox does

  • POST /otp/send returns a real otp_id and a pending status, but no message is delivered.
  • POST /otp/verify accepts the fixed code 123456 as correct. Any other code is treated as a miss, so you can test both the success and failure paths.
  • On the WhatsApp channel, send returns a sample action_url so you can see the shape. The link is not live and no code is delivered over WhatsApp in the sandbox, so the OTP stays pending. To finish a sandbox flow, move it onto SMS with a resend ({"channel":"sms"}, code is then the fixed 123456), or use a live key against your business number to test WhatsApp end to end.
  • Resend and status behave as in production, minus real delivery.

A full sandbox run

# send (sandbox: no real message)
curl -X POST https://api.otp.com/api/v1/otp/send \
  -H "Authorization: Bearer otp_test_•••" \
  -H "Content-Type: application/json" \
  -d '{"recipient":"+14155552671","locale":"en"}'
# -> { "otp_id": "9f3c1b2a-…", "status": "pending", "channel": "sms" }

# verify with the fixed sandbox code
curl -X POST https://api.otp.com/api/v1/otp/verify \
  -H "Authorization: Bearer otp_test_•••" \
  -H "Content-Type: application/json" \
  -d '{"otp_id":"9f3c1b2a-…","code":"123456"}'
# -> { "otp_id": "9f3c1b2a-…", "status": "approved", "matched": true }

Testing the failure path

Send any code other than 123456 to POST /otp/verify to see matched: false and exercise your retry and error handling. Exhaust the attempts to see the OTP move to failed.

Going live

When your integration works in the sandbox, create a live key (otp_live_…) on the API Keys screen and swap it in. The requests are identical; only the key changes. There is no separate base URL and no code path to flip.