Ingramdomains.ingram.tech

Guides

.md

Errors & idempotency

The envelope

Every /api/v1 error is:

{ "error": "<machine_code>", "details": { "message": "human explanation", … } }

Branch on error — it is stable API contract. details.message is for humans and may change; other details fields are documented per code below.

Error catalog

CodeStatusMeaningRecovery
missing_token401No Authorization: Bearer headerSend the token
invalid_token401Token not recognizedCheck the value; mint a new token if lost
revoked_token401Token was revokedMint a new token
insufficient_scope403Token scope too narrow (e.g. read on a mutation)Use a write token
not_found404Domain not in your workspace's portfolio, or unknown routeCheck the domain and workspace
bad_request400Body/params failed validationFix per details
price_changed409confirm_price ≠ live priceRe-quote; retry with details.current_price if acceptable
insufficient_balance402Wallet can't cover the priceTop up, or pass payment_method / shared_payment_token; details.required and details.available are in cents
payment_failed402/422Pay-as-you-go charge declined402 = card declined (details.kind); fix the instrument and retry
email_taken409Signup email already registeredSign in / use the existing account
no_hosted_zone409Zone operation on a domain with external nameserversManage DNS at the delegated provider, or switch to ns1/ns2.ingram.tech
delete_failed422Registry rejected the deleteSee details.message (often TLD policy)
registration_failed / renew_failed / transfer_failed422Registry rejected the operationdetails.message carries the registry's reason — often user-actionable (e.g. contact field policy)
internal500Unexpected registry/server errorRetry with the same Idempotency-Key

Registry mutations are asynchronous: a success response with registry status Pending means the registry accepted the operation and is processing it. The change (new expiry date, transferred status, …) becomes visible when the registry completes — usually seconds to minutes, up to days for transfers.

Idempotency

Every mutating route accepts an Idempotency-Key header (any unique string; a UUID is conventional):

-H 'idempotency-key: 0e8f3b7c-renew-example-com-2027'

Semantics:

  • The first request with a key executes; its response is stored.
  • A replay with the same key returns the stored response without re-executing — a network timeout can never double-charge or double-register.
  • Successes (2xx) and rejections (4xx) are cached; 5xx responses are not, so retrying a transient failure with the same key re-executes safely.

The CLI generates a fresh key per mutation automatically. For direct API use, derive the key from your own operation identity (order id, task id) so your retries collapse naturally.