Skip to main content

Security Groups

A Security Group is where Sentinel's request-handling behavior is configured. The server's behavior is driven by Rules assigned to a Security Group — they decide what happens to a given request, and every API Key inherits the rules of the Security Group it's assigned to.

Rules

Rules let you:

  • Allow or deny access based on specific conditions.
  • Set internal state — for example, adjusting proof-of-work complexity or enabling Adaptive Captcha.
  • Apply penalties, rate limits, and algorithm preferences.
  • Customize the response message returned when a request is denied.

Rule conditions support wildcard matching, so a single rule can apply across a group of routes, hostnames, or values rather than needing one rule per exact match.

Access levels

Every Security Group has an access level, which determines what its API Keys are allowed to do:

  • Public — access to public-facing endpoints only. Use this level for keys embedded in the ALTCHA widget, since the key is visible client-side.
  • Restricted — access to non-administrative API endpoints. Recommended for server-to-server integrations that need more than public access but shouldn't manage the account itself.
  • Full — administrative access to all API endpoints, including data management. Reserve this for trusted backend systems only.

Endpoints

Which endpoints a key can call is determined by its Security Group's access level:

Public (used by the ALTCHA widget):

  • /v1/challenge
  • /v1/inspect
  • /v1/verify

Restricted (server-side integrations):

  • /v1/blobs/*
  • /v1/classifier
  • /v1/context/*
  • /v1/eml
  • /v1/ip
  • /v1/language
  • /v1/phishing
  • /v1/similarity
  • /v1/timezone
  • /v1/user-agent

Every other endpoint requires Full access.

Sentinel determines a request's origin from the Origin header, falling back to Referer if Origin isn't present — relevant if you write an origin condition (see Examples below).

Autopilot

Autopilot is configured per Security Group — leave it on to let Sentinel tune challenge difficulty and policy automatically, or set bounds it can't cross.

Examples

Rules are evaluated as { action, conditions, ... } objects. A few common patterns:

Allow only internal traffic

{
  "name": "Allow internal traffic",
  "action": "allow",
  "conditions": [{ "field": "ip", "operator": "=", "value": ["10.0.0.0/24"] }]
}

Block high-risk countries

{
  "name": "Deny high-risk countries",
  "action": "deny",
  "conditions": [{ "field": "country", "operator": "=", "value": ["list:high_risk"] }]
}

Block bots and AI agents

{
  "name": "Deny bots",
  "action": "deny",
  "conditions": [{ "field": "bot", "operator": "=", "value": ["true"] }]
}

Allow only a specific origin (conditionsOperator combines multiple conditions with or/and; note the wildcard subdomain match)

{
  "name": "Allow origins",
  "action": "allow",
  "conditionsOperator": "or",
  "conditions": [
    { "field": "origin", "operator": "=", "value": ["https://example.com"] },
    { "field": "origin", "operator": "=", "value": ["https://*.example.com"] }
  ]
}

Deny a user agent matched from request headers

{
  "name": "Deny bot User-Agent",
  "action": "deny",
  "conditions": [{ "field": "headers", "operator": "=", "value": ["User-Agent: *bot/*"] }]
}

Apply a penalty for Tor traffic (set actions adjust internal state instead of allowing/denying outright)

{
  "name": "Set penalty to TOR users",
  "action": "set",
  "conditions": [{ "field": "tor", "operator": "=", "value": ["true"] }],
  "set": [{ "field": "penalty", "value": "+5" }]
}

Custom denial message

{
  "name": "Allow internal traffic",
  "action": "allow",
  "conditions": [{ "field": "ip", "operator": "=", "value": ["10.0.0.0/24"] }],
  "message": "IP denied."
}

Wildcards

Since version 1.12.0, condition values support wildcard matching:

  • * matches any sequence of characters — e.g. https://*.example.com matches any subdomain.
  • ? makes the immediately preceding character optional — e.g. colou?r matches both color and colour.

Schema

interface Rule {
  action: 'allow' | 'deny' | 'set';
  conditionsOperator?: 'and' | 'or';
  conditions: Condition[];
  message?: string;
  name?: string;
  set?: Set[];
}

interface Condition {
  field: ConditionField;
  operator: Operator;
  value: string[];
}

interface Set {
  field: SetField;
  value: string;
}

type ConditionField =
  | 'bot'
  | 'country'
  | 'headers'
  | 'hosting'
  | 'ip'
  | 'language'
  | 'malicious'
  | 'mobile'
  | 'origin'
  | 'penalty'
  | 'proxy'
  | 'tor';

type Operator = '=' | '!=' | '>' | '<' | '<=' | '>=';

type SetField =
  | 'algorithm'
  | 'autopilot'
  | 'classifyFields'
  | 'codeChallenge'
  | 'codeChallengeAlphabet'
  | 'codeChallengeMaxLength'
  | 'codeChallengeMinLength'
  | 'complexity'
  | 'cost'
  | 'counter'
  | 'disableClassificationRules'
  | 'enableClassificationRules'
  | 'expires'
  | 'headerEntropyLimit'
  | 'headerEntropyRiskFactor'
  | 'highRiskCountries'
  | 'his'
  | 'hisBlockThreshold'
  | 'hisHashTTL'
  | 'key'
  | 'maxComplexity'
  | 'memoryCost'
  | 'parallelism'
  | 'penalty'
  | 'powVersion'
  | 'probabilistic'
  | 'rateLimit'
  | 'supportedAlgorithms'
  | 'threats'
  | 'widgetConfiguration';

ConditionField covers what a rule can match on (IP, country, bot/proxy/Tor/hosting-provider detection, headers, origin, language, an accumulated penalty score, and more). SetField covers what a set action can adjust — proof-of-work parameters (complexity, cost, memoryCost, parallelism, algorithm, supportedAlgorithms, powVersion, probabilistic), HIS behavior (his, hisBlockThreshold, hisHashTTL), the code challenge (codeChallenge*), Autopilot, rate limits, classification behavior (classifyFields, enableClassificationRules, disableClassificationRules), and more.

  • API Keys — keys are created under a Security Group and inherit its access level and rules.
  • Forms — form submissions are also subject to their Security Group's rules.
  • Get Started — creating your first Security Group.

Start typing to search...

Navigate Select