Signup Protection Pricing Documentation Sign up Log in

Gates

Management API

Note

Gates is available on all paid plans.

The Management API works with the same gates the dashboard edits. Use it to provision gates from code, keep rules in sync with configuration you store in your own repository, or pull decision logs into your own tooling.

These endpoints configure gates. To evaluate one, call the Decision Endpoint.

Authentication

All endpoints live under https://api.usercheck.com/v1/gates and expect your API key in the Authorization header:

Authorization: Bearer YOUR_API_KEY

The key determines both the account and the environment you are working in. A key only sees gates in its own environment: a gate that belongs to another environment (or another account) returns 404 gate_not_found. To manage a different environment, use a key issued for that environment.

Management requests do not consume credits. Only the Decision Endpoint consumes credits.

Rate limits

Management requests are rate limited per second at the same per-plan rate as the rest of the API, but in their own bucket: a burst of management calls does not slow down your live decision or data API traffic, and the other way around. Exceeding the limit returns 429 rate_limit_exceeded with a Retry-After header.

Endpoints

Method and path Purpose
GET /v1/gates List gates
POST /v1/gates Create a gate
GET /v1/gates/{gate_id} Get a gate
PATCH /v1/gates/{gate_id} Update a gate
DELETE /v1/gates/{gate_id} Delete a gate
GET /v1/gates/{gate_id}/rules List rules
POST /v1/gates/{gate_id}/rules Add a rule
GET /v1/gates/{gate_id}/rules/{rule_id} Get a rule
PUT /v1/gates/{gate_id}/rules/{rule_id} Replace a rule
PATCH /v1/gates/{gate_id}/rules/{rule_id} Update part of a rule
DELETE /v1/gates/{gate_id}/rules/{rule_id} Delete a rule
POST /v1/gates/{gate_id}/rules/reorder Reorder rules
GET /v1/gates/{gate_id}/decisions List decisions
GET /v1/gates/{gate_id}/decisions/{decision_id} Get a decision

A single gate, rule, or decision is returned as the object itself. Lists are wrapped in a top-level data array, and the paginated decision log adds links and meta next to it. Changes take effect immediately: the next decision request uses the rules as they exist at that moment.

The gate object

{
  "id": "01k2wjgq8rnv6t0aefy3s7xdhb",
  "name": "Signup Gate",
  "environment": "production",
  "default_action": "allow",
  "rules_count": 2,
  "created_at": "2026-08-12T09:15:27+00:00",
  "updated_at": "2026-08-12T09:15:27+00:00"
}
Field Type Description
id string Unique identifier of the gate. Used in every URL below and in the Decision Endpoint URL.
name string Display name.
environment string The environment the gate belongs to. Always the key's environment.
default_action enum allow, block, or challenge. Applied when no rule matches.
rules_count integer Number of rules in the gate.

List gates

GET /v1/gates

Returns every gate in the key's environment, newest first. The list is not paginated.

curl "https://api.usercheck.com/v1/gates" \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "data": [
    {
      "id": "01k2wjgq8rnv6t0aefy3s7xdhb",
      "name": "Signup Gate",
      "environment": "production",
      "default_action": "allow",
      "rules_count": 2,
      "created_at": "2026-08-12T09:15:27+00:00",
      "updated_at": "2026-08-12T09:15:27+00:00"
    }
  ]
}

Create a gate

POST /v1/gates
Field Type Required Description
name string Yes Display name, up to 255 characters.
default_action enum Yes allow, block, or challenge. Required so the fallback decision is explicit.
environment string No Must match the key's environment. The gate is created in the key's environment either way, so you can omit it.
curl -X POST "https://api.usercheck.com/v1/gates" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Signup Gate", "default_action": "allow"}'

Returns 201 with the new gate.

A gate created through the API starts with no rules. This differs from the dashboard, where a new gate comes with a set of starter rules. Until you add a rule, every decision falls through to default_action.

Creating a gate fails with 409 gate_limit_reached once the environment holds 100 gates.

Get a gate

GET /v1/gates/{gate_id}

Returns the gate object. The rules themselves are served by the rules endpoints.

Update a gate

PATCH /v1/gates/{gate_id}
Field Type Required Description
name string No New display name.
default_action enum No allow, block, or challenge.

Fields you omit keep their value. At least one writable field is required: a request naming none of them is rejected rather than answered with an unchanged gate. A gate's environment cannot be changed. Returns the updated gate.

Delete a gate

DELETE /v1/gates/{gate_id}

Deletes the gate and all of its rules. Returns 204 with no body. Decision requests for a deleted gate return 404 gate_not_found.

The rule object

{
  "id": "01k2wjgqv9y1b7t3e8fs64dnkm",
  "order": 1,
  "name": "Block disposable emails",
  "description": null,
  "message": "Please use a permanent email address.",
  "match": "all",
  "action": "block",
  "stop": true,
  "enabled": true,
  "conditions": [
    { "field": "email.disposable", "op": "eq", "value": true }
  ],
  "created_at": "2026-08-12T09:16:03+00:00",
  "updated_at": "2026-08-12T09:16:03+00:00"
}
Field Type Writable Description
id string No Unique identifier of the rule.
order integer No Position in the evaluation order. Changed with the reorder endpoint, not by editing the rule.
name string Yes Short label, up to 255 characters. Shown in the dashboard and in decision logs.
description string or null Yes Why the rule exists, up to 255 characters.
message string or null Yes Up to 255 characters. Returned in the decision response when this rule sets the decision.
match enum Yes all requires every condition to match (AND), any requires at least one (OR).
action enum Yes allow, block, or challenge.
stop boolean Yes When true, a match ends evaluation and this rule's action is final. Defaults to false.
enabled boolean Yes When false, the rule is skipped. Defaults to true.
conditions array Yes One or more conditions, each an object with field, op, and value.

How rules combine into a decision, and the full list of condition fields, are covered in Rules & Conditions.

Condition operators

The operators a condition accepts depend on the field's type:

Field type Operators
boolean eq, ne
number eq, ne, lt, lte, gt, gte
string eq, ne, contains, starts_with, ends_with, regex, not_regex, in, not_in, is_null, not_null

The value follows the field and operator:

  • Boolean fields take true or false; number fields take an integer.
  • in and not_in take an array of strings, for example {"field": "domain.tld", "op": "in", "value": ["xyz", "top"]}.
  • regex and not_regex take a bare PCRE pattern, such as ^admin$. Do not wrap it in delimiters or append flags: /^admin$/ and /foo/u are treated as pattern text, not as delimited expressions. Matching is case-insensitive by default (i); Unicode mode (u) is not enabled. PCRE inline options inside the pattern, such as (?s) or (?-i), are supported. By default, . and its quantifiers count bytes, not Unicode code points: ^.{21,}$ matches a string of at least 21 bytes, so it already matches 11 Cyrillic letters encoded as 22 UTF-8 bytes.
  • is_null and not_null need no value.
  • String comparisons are case-insensitive by default.

List rules

GET /v1/gates/{gate_id}/rules

Returns every rule of the gate in evaluation order. The list is not paginated.

Add a rule

POST /v1/gates/{gate_id}/rules

The body takes the writable fields of the rule object: name, match, action, and conditions are required, the rest are optional. The new rule is appended after the gate's last rule.

curl -X POST "https://api.usercheck.com/v1/gates/01k2wjgq8rnv6t0aefy3s7xdhb/rules" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Block disposable emails",
    "message": "Please use a permanent email address.",
    "match": "all",
    "action": "block",
    "stop": true,
    "conditions": [
      { "field": "email.disposable", "op": "eq", "value": true }
    ]
  }'

Returns 201 with the new rule, including its assigned order.

Adding a rule fails with 409 rule_limit_reached once the gate holds 200 rules.

Get a rule

GET /v1/gates/{gate_id}/rules/{rule_id}

Returns the rule object.

Replace a rule

PUT /v1/gates/{gate_id}/rules/{rule_id}

Replaces the whole rule. name, match, action, and conditions are required. Fields you omit are reset to their defaults: description and message to null, stop to false, enabled to true. The rule's order is not affected.

Update part of a rule

PATCH /v1/gates/{gate_id}/rules/{rule_id}

Changes only the fields you send; everything else keeps its value. At least one writable field is required. conditions is replaced as a whole when present: there is no way to edit a single condition in place.

curl -X PATCH "https://api.usercheck.com/v1/gates/01k2wjgq8rnv6t0aefy3s7xdhb/rules/01k2wjgqv9y1b7t3e8fs64dnkm" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"enabled": false}'

Delete a rule

DELETE /v1/gates/{gate_id}/rules/{rule_id}

Deletes the rule. Returns 204 with no body. The remaining rules keep their relative order. Decisions the rule made stay in the decision log and keep reporting its id and name.

Reorder rules

POST /v1/gates/{gate_id}/rules/reorder

Sets the evaluation order of the whole gate in one call. rule_ids must contain the id of every rule in the gate exactly once, in the desired order:

curl -X POST "https://api.usercheck.com/v1/gates/01k2wjgq8rnv6t0aefy3s7xdhb/rules/reorder" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "rule_ids": [
      "01k2wjgqvatb5x0hry2c9pmesw",
      "01k2wjgqv9y1b7t3e8fs64dnkm"
    ]
  }'

Returns the gate's rules in their new order. A list that misses a rule, repeats one, or includes a rule from another gate fails with 422 and no order is changed.

List decisions

GET /v1/gates/{gate_id}/decisions

Returns the gate's decision log, newest first, with cursor pagination.

Parameter Type Required Description
period enum No Lookback window: 24h, 7d, or 30d (default).
per_page integer No Results per page, 1 to 100. Defaults to 25.
cursor string No Opaque cursor from a previous response. Omit for the first page.

Filters

Every filter is a plain query parameter matching one exact value. Filters on different fields combine with AND:

Parameter Value
action allow, block, or challenge
rule_id A rule id of the gate, or default for decisions that fell through to the gate's default action. Ids of deleted rules stay valid, since their decisions outlive them.
domain A domain. Normalized before matching, so case and format variants find the same rows.
email A complete email address.
ip An IP address.
anonymity vpn, proxy, tor, or relay: decisions whose IP had that anonymity type detected.
country A two-letter country code.

The parameters are validated strictly: a value that cannot match anything (a malformed email, an unknown rule id, a made-up anonymity type) fails with 422, and so does a query parameter the endpoint does not know. A misspelled filter can therefore never answer 200 with an unfiltered list.

curl "https://api.usercheck.com/v1/gates/01k2wjgq8rnv6t0aefy3s7xdhb/decisions?period=7d&action=block&country=RU" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "data": [
    {
      "id": "01K2WJH8Y4VD0BS2R8Q1KTHVGR",
      "action": "block",
      "rule": {
        "id": "01k2wjgqv9y1b7t3e8fs64dnkm",
        "name": "Block disposable emails"
      },
      "domain": "mailinator.com",
      "email": "[email protected]",
      "ip": "1.1.1.1",
      "country": "HK",
      "anonymity": [],
      "created_at": "2026-08-18T06:24:09+00:00"
    }
  ],
  "links": {
    "next": null
  },
  "meta": {
    "period": "30d",
    "per_page": 25,
    "next_cursor": null
  }
}

List entries are summaries. rule is the rule that decided the entry, or null when the decision fell through to the gate's default_action. country is the two-letter country code of the evaluated IP, and anonymity lists what was detected on it, from vpn, proxy, tor, and relay. The full input and evaluated signals are returned by Get a decision.

To fetch the next page, pass meta.next_cursor as the cursor parameter, or follow links.next. A next_cursor of null means there are no further pages. A malformed cursor fails with 422 invalid_cursor.

Get a decision

GET /v1/gates/{gate_id}/decisions/{decision_id}

Returns one decision in full, in the same shape the Decision Endpoint returned when the decision was made: your application can parse one schema whether it is handling a live decision or reading one back. The decision id is the id field of that response.

{
  "id": "01K2WJH8Y4VD0BS2R8Q1KTHVGR",
  "gate_id": "01k2wjgq8rnv6t0aefy3s7xdhb",
  "action": "block",
  "rule": {
    "id": "01k2wjgqv9y1b7t3e8fs64dnkm",
    "name": "Block disposable emails",
    "message": "Please use a permanent email address."
  },
  "input": {
    "email": "[email protected]",
    "ip": "1.1.1.1"
  },
  "signals": {
    "email": { ... },
    "domain": { ... },
    "ip": { ... }
  },
  "duration_ms": 52.62,
  "created_at": "2026-08-18T06:24:09+00:00"
}

rule.name and rule.message are the wording captured when the decision was made; editing a rule later does not rewrite them. input is the request body the decision was made for, and signals holds the email, domain, and IP signal objects the rules ran against.

Decisions are written to the log asynchronously, moments after the decision response returns. Fetching a decision immediately after receiving it can return 404 decision_not_found for that short window; retrying resolves it.

Errors

Errors return the matching HTTP status code and a JSON body with a stable error code and a human-readable message:

{
  "error": "gate_not_found",
  "message": "Gate not found."
}

Codes specific to these endpoints:

  • 404 gate_not_found: Unknown gate_id, or a gate outside the key's environment
  • 404 rule_not_found: Unknown rule_id, or a rule belonging to a different gate
  • 404 decision_not_found: Unknown decision_id
  • 409 gate_limit_reached: The environment already holds 100 gates
  • 409 rule_limit_reached: The gate already holds 200 rules
  • 422 invalid_cursor: The cursor parameter is not a cursor from a previous response

Invalid input, including an unknown or malformed query parameter, fails with 422 validation_failed and an errors object naming the fields at fault:

{
  "error": "validation_failed",
  "message": "Some input fields are invalid.",
  "errors": {
    "name": ["The name field is required."]
  }
}

On top of those, these endpoints return the codes shared by every Gates endpoint, including 401 unauthorized, 403 pro_only, and 429 rate_limit_exceeded. See Errors for the full list.

Previous
Decision Endpoint