OTP Space takes just two API calls: send an OTP to your user's WhatsApp number, then verify the code they enter. That's it.
Want to try it directly in your browser? Open the interactive API Reference (Swagger UI), paste your sk_live_* key, and fire real requests without writing any code. The 10 free OTPs on every new account are plenty for a smoke test.
Register an account, grab your CLIENT_ID and CLIENT_SECRET from the API Keys page, then start sending:
# 1) Send OTP curl -X POST https://api.otpspace.com/v1/otp/send \ -H "Authorization: Bearer sk_live_xxx" \ -H "Content-Type: application/json" \ -d '{"phone":"6281234567890"}' # 2) Verify code curl -X POST https://api.otpspace.com/v1/otp/verify \ -H "Authorization: Bearer sk_live_xxx" \ -H "Content-Type: application/json" \ -d '{"phone":"6281234567890","code":"123456"}'
Every request must include the header Authorization: Bearer sk_live_xxx with your client secret.
Authorization: Bearer sk_live_xxxxxxxxxxxx
Send an OTP over WhatsApp (default) or email. Set channel to "email" and pass an email destination, or omit channel and it is inferred from the destination. The template_id, otp_length, expiry_seconds, and metadata fields are optional.
// Request { "phone": "6281234567890", "template_id": "default", "otp_length": 6, "expiry_seconds": 300 } // Response 202 { "success": true, "data": { "otp_id": "otp_abc123def456", "phone": "6281234***90", "status": "queued", "expires_at": "2026-05-15T14:35:00Z" }, "credits_remaining": 994 }
Verify the OTP code your user entered (WhatsApp or email).
// Request { "phone": "6281234567890", "code": "482916" } // Response 200 { "success": true, "data": { "otp_id": "otp_abc123def456", "phone": "6281234***90", "channel": "whatsapp", "status": "verified", "verified_at": "2026-05-15T14:33:42Z" } }
OTP Space can also deliver OTPs by email at 0.2 credit per send (WhatsApp is 1 credit). Use the same /v1/otp/send and /v1/otp/verify endpoints — set channel to "email" and pass an email destination. Everything else (rate limits, expiry, verification) behaves exactly like WhatsApp.
# Send an email OTP (0.2 credit) curl -X POST https://api.otpspace.com/v1/otp/send \ -H "Authorization: Bearer sk_live_xxx" \ -H "Content-Type: application/json" \ -d '{"channel":"email","email":"[email protected]"}' // Response 202 { "success": true, "data": { "otp_id": "otp_9f2c1a8b7d6e", "destination": "u***@acme.com", "channel": "email", "status": "delivered", "expires_at": "2026-05-15T14:40:00Z" }, "credits_remaining": 993.8 } # Verify uses the same endpoint; pass the email as the destination curl -X POST https://api.otpspace.com/v1/otp/verify \ -H "Authorization: Bearer sk_live_xxx" \ -H "Content-Type: application/json" \ -d '{"email":"[email protected]","code":"482916"}'
Check the status of a specific OTP.
// Response 200 { "success": true, "data": { "otp_id": "otp_abc123def456", "phone": "6281234***90", "status": "delivered", "created_at": "2026-05-15T14:30:00Z", "expires_at": "2026-05-15T14:35:00Z", "delivered_at": "2026-05-15T14:30:08Z", "verified_at": null } }
OTP delivery history. Supports status, channel, phone, from, and to filters, plus page and per_page for pagination.
Check your account's credit balance.
// Response 200 { "success": true, "data": { "credits_remaining": 8420, "credits_used": 1580, "tier": "growth" } }
| Code | Meaning | How to handle |
|---|---|---|
| 400 | Bad Request | Check the request payload format. |
| 401 | Unauthorized | Client secret is invalid. |
| 402 | Payment Required | Out of credits. Top up via the dashboard. |
| 404 | Not Found | OTP ID not found. |
| 410 | Gone | OTP has expired. |
| 422 | Unprocessable | Phone number is invalid or not on WhatsApp. |
| 429 | Too Many Requests | Rate limit reached. Retry after a few seconds. |
| 500 | Server Error | Retry with backoff. Contact support if persistent. |
Coming in Phase 2. You'll be able to register a URL to receive real-time event notifications (delivered, verified, expired, failed).