Signup protection Pricing Documentation Sign up Log in

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. If it arrives on your very first requests, check your API key
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.

In a signup or other request a user is waiting on, don't retry a decision. Fall back and log it, as described in Timeouts and failures.

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
400 invalid_json A non-empty request body could not be parsed as JSON. Set Content-Type: application/json and check the body syntax
401 unauthorized The API key is missing, mistyped, or revoked. After 5 such requests per hour from one IP, the API answers 429 rate_limit_exceeded instead, with a Retry-After of up to an hour
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, a temporary IP block, or too many requests without a valid API key. See Rate Limits
429 quota_exceeded Decision Endpoint only. Monthly credits are used up until the billing cycle resets or overage is enabled. Management requests use no credits and never return it
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, including invalid_ip, return 400 where /v1 returns 422. The error codes are the same on both.
  • An email or domain that is null, empty, not a string, or longer than 255 characters returns 422 with message and errors, but no error code.
  • There is no invalid_json. /v0 accepts form-encoded and multipart bodies, and a malformed JSON body returns 400 missing_input.
  • Exceeding the per-second rate limit returns 429 with {"status": 429, "error": "Too many requests"}.
  • Used-up monthly credits return 429 rate_limit_exceeded where /v1 returns 429 quota_exceeded.
  • Some error bodies include a meta object; do not require it on every failure.
  • A wrong path or HTTP method returns a generic 404 or 405 response without an error code.

On both versions, ip: null is treated as absent and adds no IP signals or credits.

Migrate from v0 to v1 covers the move.

Previous
Management API