Rate Limits
Request rate limits and 429 handling.
Requests to the API are limited to 100 requests per 60-second window, per endpoint, per calling IP address. The same limit applies in Sandbox and production.
What that means in practice:
- Per endpoint. Each method and path (for example
GET /v2/api-gateway/cardsandPOST /v2/api-gateway/cards) has its own budget. Exhausting one endpoint's budget does not affect calls to another. - Per calling IP address. The budget is counted for the address your requests arrive from, not for your API key. Several servers calling from different addresses each get their own budget; several API keys used from one address share one.
- Every request counts, including requests that fail validation or authentication and calls to the endpoints that do not need an API key.
- The headers are authoritative. Read
X-RateLimit-Remainingand theRetry-Afteron a429rather than counting requests against the figure yourself; the headers describe the window that is actually in force for your traffic.
Response headers
Every response that was allowed through carries the current state of the window for that endpoint:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 60X-RateLimit-Limit— requests allowed per window.X-RateLimit-Remaining— requests left in the current window.X-RateLimit-Reset— seconds until the window resets.
When you exceed the limit
The API responds with 429 Too Many Requests, a Retry-After header (seconds to wait) and the standard error body. The X-RateLimit-* headers are not sent on the 429 itself.
GET https://api.themooncard.com/v1/api-gateway/moon-reserveHTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json; charset=utf-8
{"message":"ThrottlerException: Too Many Requests","code":"HTTP_EXCEPTION"}The code on this response is the generic HTTP_, so detect rate limiting from the 429 status, not from code. Wait for the number of seconds in Retry-After before sending the next request to that endpoint. Other endpoints remain available. See Errors for the error body format.
Other limits that return 429 or 400
These are attempt limits on specific flows, independent of the per-endpoint window:
| Flow | Limit | Response |
|---|---|---|
Cardholder login (POST /v2/api-gateway/cardholders/auth/login, step 2) | 5 wrong codes for the current login code | 429 { "message": "Too many attempts. Please try again later.", "code": "TOO_. No Retry-After. Request a new code (step 1) to reset the count. |
Card activation with a one-time code (POST /v1/public/2fa/card/activate) | 3 attempts per session | 400 { "message": "Maximum attempts exceeded", "code": "MAX_ on the fourth attempt; the session is discarded. Start a new session and request a new code. |
Recommendations
- Implement exponential backoff with jitter on
429responses, and honourRetry-Afteras the minimum wait. - Prefer webhooks over polling for transaction and balance updates — see Webhooks.
- Batch or space out bulk operations (for example issuing many cards) so that no single endpoint receives more than 100 requests per minute from one address; watch
X-RateLimit-Remainingand slow down before it reaches zero.
Last updated August 17, 2026