Gates
Errors
Errors returned by the Gates v1 API use the same JSON body: a stable, machine-readable error code and a human-readable message.
{
"error": "gate_not_found",
"message": "Gate not found."
}
Match on error, not the wording of message, which can change.
Handling failures
Read the HTTP status first. Parse JSON defensively: an empty, invalid, or non-object body means no error code is available. For Gates v1, use this policy:
| Response | What to do |
|---|---|
429 with quota_exceeded |
Check your credits or enable overage. Repeated retries will not restore the quota |
Any other 429 |
Pause requests. Honor Retry-After when present; otherwise use exponential backoff with jitter |
500, 502, 503, 504 |
Retry with backoff, even if the body is empty or has no error code |
Other 4xx |
Fix the request or access problem before retrying |
Limit retry attempts. Only automatically retry requests that are safe to repeat: a failed response does not prove that a write was never applied. A missing Retry-After header alone does not mean credits are exhausted.
Errors before the API
Infrastructure failures can return 502, 503, or 504 with JSON, text, HTML, or no body. The handling policy above works without a JSON error code. Temporary IP blocks return 429 rate_limit_exceeded in the Gates v1 format and follow the same retry policy; see Rate Limits.
Cloudflare security rejections can return a non-JSON 403, such as error code: 1010. This does not indicate an invalid API key; 403 pro_only specifically means the account needs a plan that includes Gates. For an unexplained security rejection, contact us with the request URL (without credentials), timestamp, user-agent, and CF-Ray header if present. Do not include your API key.
Field validation
When individual fields are at fault, the body carries an errors object naming each one:
{
"error": "validation_failed",
"message": "Some input fields are invalid.",
"errors": {
"name": ["The name field is required."]
}
}
Codes on every endpoint
| Status | Code | Meaning |
|---|---|---|
401 |
unauthorized |
The API key is missing or invalid |
403 |
pro_only |
The account is not on a plan that includes Gates |
404 |
not_found |
No Gates endpoint at that path |
405 |
method_not_allowed |
The path exists, but not for that HTTP method. The response carries an Allow header listing the methods it does accept |
422 |
validation_failed |
One or more fields are invalid, see Field validation |
429 |
rate_limit_exceeded |
Throughput limit exceeded or a temporary IP block. See Rate Limits |
429 |
quota_exceeded |
Monthly credits are exhausted until the billing cycle resets or overage is enabled |
500 |
server_error |
The request failed on our side |
502, 503, 504 |
Not guaranteed | Infrastructure failure; the body may be empty or outside the JSON envelope. See Errors before the API |
Codes on specific endpoints
The Decision Endpoint and the Management API each list the codes only they return, such as invalid_email or rule_limit_reached.
The /v0 endpoint
POST /v0/gates/{gate_id}/decisions predates this contract and keeps its own:
- Input errors return
400where/v1returns422. Theerrorcodes are the same on both. - Exhausted monthly credits return
429 rate_limit_exceededwhere/v1returns429 quota_exceeded. - Some error bodies include a
metaobject; do not require it on every failure. - A wrong path or HTTP method returns the framework's default body rather than the envelope.
IP validation also applies to /v0: malformed ip values that previously returned 200 now return 400 invalid_ip (422 invalid_ip on /v1). This adds an error code while preserving the /v0 error response shape and input-error status. On both versions, ip: null is treated as absent and adds no IP signals or lookup credits.
Migrate from v0 to v1 covers the move.