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 callPOST /v3/request or POST /v3/send, 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.
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
This limit applies only to OTP creation endpoints (
POST /v3/request and POST /v3/send). 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.

