Guides
TypeScript SDK
Rules
Decide specific cases yourself, like "block sign-ups with a disposable email from a data center".
The score weighs every signal together. When you know exactly what you want for a case, write a
rule. Rules are checked after your lists and before the score
thresholds. The first enabled rule (lowest position, then oldest) whose conditions match the event
decides, and the assessment gets a rule.matched reason naming it.
const { : } = await ...({
: "Disposable email from a data center",
: 10,
: ["signup"],
: [
{ : "email.disposable", : "is", : true },
{ : "ip.hosting", : "is", : true },
],
: "block",
});
// Checked first (lower position): trust logins from your office network.
await ...({
: "Office network",
: 0,
: ["login"],
: [{ : "ip.asn", : "in", : ["64500", "64501"] }],
: "allow",
});match: "all"(the default) needs every condition;match: "any"needs one.eventslimits a rule to some events; empty means every event.- A field without a value never matches, whatever the operator: a rule about
ip.countrydoesn't fire for an assessment without an IP address, andneqdoesn't fire either. - Rules see the facts behind disabled reasons, so you can turn a reason off for the score and still use it in a rule.
- An environment has at most 50 rules. Edit them in the dashboard (Risk → Rules) or with
coss.risk.rules.update(id, { enabled: false }).
Fields
String comparisons ignore case; in and not_in take a list of up to 100 strings.
| Field | Type | Operators | Meaning |
|---|---|---|---|
email.valid | boolean | is | Email is valid |
email.disposable | boolean | is | Email is disposable |
email.undeliverable | boolean | is | Email domain can't receive mail |
email.role_account | boolean | is | Email is a role account |
email.free_provider | boolean | is | Email is at a free provider |
email.typo | boolean | is | Email domain looks like a typo |
email.domain_new | boolean | is | Email domain is new |
email.domain | string | eq, neq, in, not_in | Email domain |
email.domain_age_days | number | eq, neq, gt, gte, lt, lte | Email domain age (days) |
ip.tor | boolean | is | IP is a Tor exit |
ip.hosting | boolean | is | IP is a cloud or hosting network |
ip.vpn | boolean | is | IP is a VPN network |
ip.private | boolean | is | IP is private |
ip.country | string | eq, neq, in, not_in | IP country (ISO code) |
ip.asn | string | eq, neq, in, not_in | IP network (AS number) |
ip.hosting_provider | string | eq, neq, in, not_in | IP hosting provider |
captcha.passed | boolean | is | Captcha passed |
duplicate.canonical_mailbox | boolean | is | Mailbox already has an account |
history.fraud | boolean | is | Seen in fraud before |
login.new_country | boolean | is | Login from a new country |
login.new_network | boolean | is | Login from a new network |
score | number | eq, neq, gt, gte, lt, lte | Score (0-1) |
velocity.ip_1h | number | eq, neq, gt, gte, lt, lte | Events from the IP (1 h) |
velocity.ip_24h | number | eq, neq, gt, gte, lt, lte | Events from the IP (24 h) |
velocity.subnet_1h | number | eq, neq, gt, gte, lt, lte | Events from the subnet (1 h) |
velocity.subnet_24h | number | eq, neq, gt, gte, lt, lte | Events from the subnet (24 h) |
velocity.email_domain_1h | number | eq, neq, gt, gte, lt, lte | Events with the email domain (1 h) |
velocity.email_domain_24h | number | eq, neq, gt, gte, lt, lte | Events with the email domain (24 h) |
velocity.mailbox_1h | number | eq, neq, gt, gte, lt, lte | Events with the mailbox (1 h) |
velocity.mailbox_24h | number | eq, neq, gt, gte, lt, lte | Events with the mailbox (24 h) |
velocity.user_1h | number | eq, neq, gt, gte, lt, lte | Events of the user (1 h) |
velocity.user_24h | number | eq, neq, gt, gte, lt, lte | Events of the user (24 h) |
On This Page