All errors return a JSON body with a single error field describing what went wrong. Status codes follow the client-vs-server distinction: 4xx means the request was malformed and should be corrected before retry; 5xx means we failed and the same request will be honored once we recover.
| Code | Name | Meaning |
|---|---|---|
| 400 | Bad Request | Validation error — missing parameter, malformed value, or invalid service ID. The error message tells you exactly what's wrong; the call is safe to retry once corrected. |
| 403 | Forbidden | Account suspended. Contact support — retries will keep failing until the suspension is lifted. |
| 429 | Too Many Requests | Rate limit exceeded. See the X-RateLimit-DeniedBy header for which layer (ip / key / tier). Sleep until X-RateLimit-Reset before retrying. |
| 500 | Internal Server Error | Unexpected server-side failure. Errors with sensitive details are sanitized to a generic message in the response body — the full stack is captured in our Sentry instance for diagnosis. Retries with the same idempotency key are safe (they will return the original response if the operation succeeded). |
{
"error": "Missing required parameter: service"
}The action requires a parameter that wasn't included. Add it to the request body and retry.
{
"error": "Invalid API key"
}Wrong key, revoked key, or missing key. Check the value matches what's shown in /dashboard/api. The error is identical for missing and invalid to prevent enumeration attacks.
{
"error": "Insufficient balance"
}Your account balance is below the order's total charge. Top up via /dashboard/wallet, or apply a coupon.
{
"error": "Service not found"
}The service ID doesn't exist or has been deactivated. Re-fetch the service catalog with action=services and pick a current ID.
{
"error": "Rate limit exceeded"
}One of the three rate limits depleted. See X-RateLimit-DeniedBy and sleep until X-RateLimit-Reset.
The order-placement action requires a caller-supplied request_id (idempotency key) on every call. Retries with the same request_id always return the same response — the original order, not a duplicate. This makes 5xx errors safe to retry without ever placing the same order twice. For other actions (status, balance, refill, cancel) retries are inherently safe — they don't mutate state or they mutate idempotently.