403 and IP_NOT_ALLOWED; they do not become 429 rate-limit responses. See the API V3 IP allowlist guide.
Summary
Global per-API-key limit
Every request you make to any/v3/* endpoint counts toward your global rate limit. The window is a fixed 1-second bucket. If your API key sends more than 20 requests within that second — across POST /v3/request, POST /v3/send, POST /v3/verify, GET /v3/otp/{otp_id}, or any other v3 endpoint — all additional requests within that window are rejected.
Error response:
Handling RATE_LIMITED
Implement exponential backoff when you receive this error. A simple strategy:
- On the first
RATE_LIMITEDresponse, wait ~100 ms and retry. - On each subsequent failure, double the wait time (200 ms, 400 ms, 800 ms…).
- Add a small random jitter (±20%) to prevent synchronized retries from multiple instances of your service all hitting the limit at the same moment.
- Set a maximum retry count (e.g., 5 attempts) and surface an error to the user if all retries are exhausted.
Per-destination limit
When you call an OTP creation endpoint, OTP.ID also enforces a per-destination limit. This limit applies to the combination of your API key (merchant) and the destination phone number or email address — so separate merchants are counted independently. The limit is channel-specific because Missed Call has a four-digit caller-ID OTP that is more susceptible to guessing. For standard channels (whatsapp, sms, and email), two windows are enforced simultaneously:
- Short window: No more than 5 OTPs per 10 minutes to the same destination
- Long window: No more than 10 OTPs per hour to the same destination
misscall, which is available only through POST /v3/request, the stricter policy is:
- Short window: No more than 2 OTPs per 10 minutes to the same destination
- Long window: No more than 4 OTPs per hour to the same destination
This limit applies only to OTP creation endpoints. For Missed Call, that means
POST /v3/request only. Calls to POST /v3/verify and GET /v3/otp/{otp_id} are not subject to the per-destination policy.Why this limit exists
The per-destination limit protects your users from OTP flooding — a situation where an attacker (or a bug in your application) repeatedly triggers OTP messages to the same phone number or email address. Without this limit, a single user could receive dozens of messages in quick succession, which is a poor experience and a potential harassment vector.Handling DESTINATION_RATE_LIMITED
Unlike the global limit, you cannot simply retry immediately — you must wait for the current window to expire before sending another OTP to that destination.
Recommended approach:
- Track OTP send counts on your side. Maintain a counter per destination in your own cache or database so you can check the limit before calling the API and show users a friendly waiting message instead of an opaque error.
- Surface a user-facing message. Tell the user something like “Too many OTP requests. Please wait a few minutes before requesting a new code.”
- Do not retry automatically. This error is not a transient failure — retrying the same destination will continue to fail until the window resets.
Both limits together
It is possible to receive either limit in a single high-traffic session. The table below summarises how to differentiate them:
If you need to increase the global rate limit beyond 20 requests/second, contact OTP.ID support. Per-destination limits are fixed and cannot be adjusted.

