Limits keep the API responsive for everyone; idempotency keys make money-moving calls safe to retry.
Rate limits
Limits are counted per minute. Each operation in the reference shows the limit that applies to it; when several apply, all of them count and the strictest is reached first.
Calls | Limit | Counted per |
|---|---|---|
Reseller reads ( GET /reseller/…, availability check included) | 300 per minute | Account |
Price list ( GET /reseller/pricing) | 10 per minute, on top of the reads limit | Account |
Register, transfer, renew, restore, update the registrant | 30 per minute | Account |
Domain management calls ( /client/domains/…) | 120 per minute | API user |
- Per API user: all the tokens of the same user share one bucket, so creating more tokens does not raise the limit. A request without a valid token is counted per IP address.
- Per account: all the users and tokens of your account share the bucket. The availability check and the four money-moving calls have separate buckets: checks never use up your registrations.
429 and Retry-After
Over a limit, the API answers 429 with a Retry-After header: the number of seconds to wait before trying again. Wait at least that long; do not retry in a tight loop. The body is a plain {"message": "…"} (MessageError).
To stay under the limits, cache GET /reseller/pricing (prices change rarely), debounce availability checks in search boxes, and poll pending domains every minute or so rather than every second.
Idempotency-Key
Register, transfer, renew and restore move money. If a request times out, you cannot know whether it ran; retrying blindly could charge twice. Send an Idempotency-Key header to make the retry safe:
Idempotency-Key: 5f0c6a8e-3b2d-4c1a-9e7f-2a4b6c8d0e1f
- Use a new random value (a UUID is ideal) for each new operation, and the same value when you retry that operation.
- The key must be 1–255 printable ASCII characters, otherwise
422 invalid_idempotency_key. - Keys are scoped to your account: all its tokens share the same key space, so two integrations must not generate the same keys.
- A key belongs to one operation on one domain (register, transfer, renew or restore of a specific name) and one request body. The order of the JSON fields does not matter, and the Unicode, Punycode and trailing-dot spellings of the same domain are the same request.
- Keys are kept for 30 days.
Replays
You send | The API answers |
|---|---|
A new key | Runs the operation and stores the answer. |
The same key and the same request, finished with 200 or 202 | The stored answer again, byte for byte, with the header Idempotent-Replayed: true. Nothing runs and nothing is charged twice. |
The same key while the first request is still running | 409 idempotency_in_progress: retry after retry_after seconds. |
The same key on a different operation or domain, or with a different body | 422 idempotency_key_reused. |
Refusals that carry an error.code (every 4xx, and a 5xx with a code) are not replayed: the key is released and a retry with it runs again. After insufficient_credit, for example, top up and retry with the same key. The exception is a refusal where the money was kept, such as 424 registrar_unknown: it is stored and replayed like a success; do not retry it with a new key. Validation errors and 404 are never stored.
A key stuck in progress
A plain 500 without an error.code, or a request that crashes or times out on our side, keeps its key locked: a retry with it answers 409 idempotency_in_progress. Do not rotate to a new key to get past it: the first request may have run, and a new key could charge twice. Contact SupportHost with the key instead: after checking that nothing was charged, we release it by hand (usually once it has been stuck for an hour).