Signup Protection Pricing Documentation Sign up Log in

Gates

Migrate from Email & Domain

The Gates Decision API replaces manual logic built around the /email and /domain endpoints. Instead of pulling raw signals and writing your own logic, you define reusable rules directly in the dashboard and let the gate decide.

This guide shows how to migrate existing integrations in a few steps.

1. Create a gate

Start by creating a gate for the flow you want to protect. See Quickstart for setup.

2. Rebuild your checks as rules

Take the logic you currently apply after calling /email or /domain, for example:

  • block when disposable is true
  • block when spam is true

Then recreate it as rules inside your gate. Each rule checks one or more fields (like domain.mx or email.role_account) and chooses an action: allow, block, or challenge. See Rules & Conditions for the fields a condition can use.

3. Update your API integration

Replace your GET /email or GET /domain calls with a POST to your gate's Decision endpoint:

curl -X POST "https://api.usercheck.com/v1/gates/{gate_id}/decisions" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "email": "[email protected]" }'

Swap "email" for "domain" if that's your input.

The response puts the verdict at the top. Shortened here to the fields this migration cares about:

{
  "action": "block",
  "rule": { "name": "Block domains with no MX records", "message": null },
  "signals": {
    "email": { "disposable": false },
    "domain": { "mx": false }
  }
}
  • action: the gate's decision (allow, block, or challenge)
  • rule: which rule decided it, including its name and optional message; null when the gate's default action applied
  • signals: the same intelligence you would get from /email or /domain

The full response shape is documented on the Decision Endpoint page.

Note

The gate already applies your rules and returns a verdict. Treat signals as informational only.

4. Example migration

Before: manual logic

response = requests.get(
    f"https://api.usercheck.com/email/{email}",
    headers={"Authorization": f"Bearer {API_KEY}"},
)
data = response.json()

if data.get("disposable"):
    raise SignUpError("Disposable emails are not allowed.")

if data.get("relay_domain"):
    raise SignUpError("Please use your real email address to register.")

normalized_email = data.get("normalized_email", email)

# Proceed with signup

After: gate decision

response = requests.post(
    f"https://api.usercheck.com/v1/gates/{GATE_ID}/decisions",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json={"email": email},
)
data = response.json()

if data.get("action") == "block":
    message = (data.get("rule") or {}).get("message")
    raise SignUpError(message)

if data.get("action") == "challenge":
    tagAccountAsHighRisk()

normalized_email = data.get("signals", {}).get("email", {}).get("normalized", email)

# Proceed with signup

5. Using rule messages in your UI

Each decision includes an optional rule.message field when a rule matched. If you want to show context to your users, surface this message in your own interface.

Typical usage:

  1. Inspect action (allow, block, or challenge)
  2. Optionally read rule.message for user-facing context

How you handle that information is entirely up to your application.

6. Need help?

For complex migrations or multi-condition logic, contact [email protected].

Previous
Errors