The Tracer rules engine lets you build powerful validation logic without writing code. Using CEL (Common Expression Language)—a type-safe expression language developed by Google—you can create sophisticated rules that evaluate in under 1ms, automate complex business decisions, and adapt quickly to new requirements.
Why use the rules engine
| Benefit | Description |
|---|
| Flexibility | Create and modify rules without code deploys |
| Performance | Compiled expressions evaluate in under 1ms each |
| Type safety | Expression syntax validated at rule creation |
| Complete evaluation | All active rules evaluated for comprehensive audit trail |
| Scope-based | Apply rules to specific segments, accounts, or transaction types |
By the end of this guide, you will:
- Understand rule engine concepts and evaluation flow
- Create and test expression-based rules
- Manage the rule lifecycle (DRAFT, ACTIVE, INACTIVE, DELETED)
- Apply best practices for rule management
What is the rules engine
The rules engine is the Tracer component responsible for evaluating expressions during transaction validation. It enables fraud analysts and risk managers to configure business logic that executes in real time—without requiring code deployments or engineering support.
How it works
In this flow:
- Load rules fetches all active rules from cache (or database on cache miss)
- Evaluate expressions runs all CEL expressions against the transaction context
- Collect matches gathers all rules that matched and determines the decision
Evaluation pattern
All active rules are evaluated against every transaction. There is no priority ordering or short-circuit evaluation. This ensures:
- Complete audit trail (all matching rules recorded)
- No information loss (analysts can see all triggers)
- Simple logic (no priority conflicts)
Decision precedence:
- If any DENY rule matches, Tracer returns a DENY decision
- If only ALLOW rules match, Tracer returns an ALLOW decision
- If no rules match, Tracer returns the configured default (typically ALLOW for fail-open behavior)
Tracer returns decisions; it does not block transactions directly. Your system receives the decision and is responsible for taking the appropriate action (e.g., blocking, allowing, or queuing for review).
Core concepts
Before creating rules, understand the foundational elements.
Rules
A rule is a unit of business logic composed of:
- Expression - A type-safe expression that evaluates to true or false
- Action - What decision to return when the expression is true
- Scopes - Which transactions the rule applies to
- Status - The rule’s lifecycle state
Expressions
Expressions are written in CEL (Common Expression Language), a type-safe language that evaluates transaction context and returns a boolean value (true or false). CEL provides compile-time validation, so syntax errors are caught when you create the rule—not when transactions are being processed.
Example expressions:
transaction.amount > 10000
account.segmentId == "high-risk-segment" && transaction.amount > 5000
merchant.category == "gambling"
Expressions have access to the full transaction context including:
transaction - Amount, currency, type, subType, timestamp
account - AccountId, segmentId, portfolioId
segment - SegmentId and segment metadata
portfolio - PortfolioId and portfolio metadata
merchant - MerchantId, category, country, riskLevel (optional)
metadata - Custom fields passed in the request
Expression examples by use case
Here are practical examples organized by business scenario:
Amount-based rules
// Block transactions above a threshold
transaction.amount > 10000
// Block high-value international transfers
transaction.type == "WIRE" && transaction.subType == "international" && transaction.amount > 50000
// Review large cryptocurrency transactions
transaction.type == "CRYPTO" && transaction.amount > 5000
Merchant-based rules
// Block gambling merchants
merchant.category == "7995"
// Block high-risk merchant categories
merchant.category in ["7995", "5967", "5966"]
// Review transactions from new merchant countries
merchant.country != "BR" && transaction.amount > 1000
Account-based rules
// Block suspended accounts
account.status == "suspended"
// Review transactions from newly created accounts
metadata.accountAgeDays < 30 && transaction.amount > 500
// Block closed accounts
account.status == "closed"
Combined conditions
// High-value transaction from high-risk segment
account.segmentId == "high-risk-segment-uuid" && transaction.amount > 5000
// International PIX above threshold
transaction.type == "PIX" && transaction.subType == "international" && transaction.amount > 10000
// Large card transaction to foreign merchant
transaction.type == "CARD" && merchant.country != "BR" && transaction.amount > 3000
// Block transactions from untrusted devices
metadata.deviceTrust == "untrusted"
// Review first-time purchases above threshold
metadata.isFirstPurchase == true && transaction.amount > 1000
// Block transactions outside business hours (using metadata)
metadata.isBusinessHours == false && transaction.amount > 5000
// VIP customers bypass certain restrictions
metadata.customerTier == "vip" && transaction.amount < 50000
Metadata fields are provided by your integration. Design your payload to include the context your rules need.
Actions
Actions determine the decision when an expression evaluates to true:
| Action | Description |
|---|
ALLOW | Allow the transaction |
DENY | Deny the transaction |
REVIEW | Route to manual review |
Scopes
Scopes define which transactions a rule applies to. A rule only evaluates against transactions that match at least one of its scopes.
Scope fields (all optional):
segmentId - Match transactions from a specific segment
portfolioId - Match transactions from a specific portfolio
accountId - Match transactions from a specific account
merchantId - Match transactions to a specific merchant
transactionType - Match specific transaction types (CARD, WIRE, PIX, CRYPTO)
subType - Match specific subtypes (debit, credit, instant, etc.)
If a scope field is not specified, it matches any value for that field.
Rule lifecycle
Rules progress through a defined lifecycle to ensure safe deployment.
States
| State | Description |
|---|
DRAFT | Not evaluated; expression can be modified freely |
ACTIVE | Evaluated during validations; expression is immutable |
INACTIVE | Not evaluated; preserved for audit trail; can be reactivated |
DELETED | Permanently removed; does not appear in listings; cannot be recovered |
Transitions
| Transition | From | To | Description |
|---|
activate | DRAFT, INACTIVE | ACTIVE | Start evaluation (validates expression) |
deactivate | ACTIVE | INACTIVE | Stop evaluation |
delete | DRAFT, INACTIVE | DELETED | Permanent removal (cannot delete ACTIVE rules) |
Active rules must be deactivated before deletion. This prevents accidental removal of rules that are currently being evaluated.
Create a rule
Create rules to automate validation decisions. Rules are created in DRAFT status by default.
Request
POST /v1/rules
X-API-Key: {api_key}
Content-Type: application/json
{
"name": "Block high-value transactions",
"description": "Deny transactions above BRL 10,000 for high-risk segment",
"expression": "transaction.amount > 10000 && account.segmentId == \"high-risk-uuid\"",
"action": "DENY",
"scopes": [
{
"segmentId": "high-risk-uuid",
"transactionType": "CARD"
}
]
}
Response
{
"ruleId": "rule-uuid-123",
"name": "Block high-value transactions",
"description": "Deny transactions above BRL 10,000 for high-risk segment",
"expression": "transaction.amount > 10000 && account.segmentId == \"high-risk-uuid\"",
"action": "DENY",
"scopes": [
{
"segmentId": "high-risk-uuid",
"transactionType": "CARD"
}
],
"status": "DRAFT",
"createdAt": "2026-01-29T10:00:00Z",
"updatedAt": "2026-01-29T10:00:00Z"
}
Rule fields
| Field | Type | Required | Description |
|---|
name | string | Yes | Unique rule name |
description | string | No | Purpose description |
expression | string | Yes | Boolean expression to evaluate |
action | enum | Yes | ALLOW, DENY, or REVIEW |
scopes | array | No | Scopes the rule applies to |
Activate and deactivate rules
After creating a rule, activate it to start evaluation. Deactivate rules to stop evaluation without deleting them.
Activate a rule
POST /v1/rules/{ruleId}/activate
X-API-Key: {api_key}
Response:
{
"ruleId": "rule-uuid-123",
"name": "Block high-value transactions",
"status": "ACTIVE",
"updatedAt": "2026-01-29T11:00:00Z"
}
Deactivate a rule
POST /v1/rules/{ruleId}/deactivate
X-API-Key: {api_key}
Response:
{
"ruleId": "rule-uuid-123",
"name": "Block high-value transactions",
"status": "INACTIVE",
"updatedAt": "2026-01-29T15:00:00Z"
}
Deactivating a rule preserves it for audit purposes. Use delete only when you want to permanently remove a rule.
List and query rules
Query rules for management and auditing.
List all rules
GET /v1/rules
X-API-Key: {api_key}
Query parameters:
| Parameter | Type | Description |
|---|
status | string | Filter by status (DRAFT, ACTIVE, INACTIVE) |
pageSize | integer | Items per page (default: 100, max: 1000) |
pageToken | string | Pagination token |
Response:
{
"data": [
{
"ruleId": "rule-uuid-123",
"name": "Block high-value transactions",
"description": "Deny transactions above BRL 10,000",
"action": "DENY",
"status": "ACTIVE",
"createdAt": "2026-01-29T10:00:00Z",
"updatedAt": "2026-01-29T11:00:00Z"
},
{
"ruleId": "rule-uuid-456",
"name": "Allow verified accounts",
"description": "Allow transactions from verified premium accounts",
"action": "ALLOW",
"status": "ACTIVE",
"createdAt": "2026-01-28T09:00:00Z",
"updatedAt": "2026-01-28T09:00:00Z"
}
],
"nextPageToken": null
}
Get a specific rule
GET /v1/rules/{ruleId}
X-API-Key: {api_key}
Response includes the full rule definition with expression and scopes.
Update a rule
Rules can be updated in any status. However, the expression field is immutable once the rule is ACTIVE—to change the expression, deactivate the rule first.
PATCH /v1/rules/{ruleId}
X-API-Key: {api_key}
Content-Type: application/json
{
"description": "Updated description",
"expression": "transaction.amount > 5000"
}
The expression field cannot be updated while a rule is ACTIVE. Deactivate the rule first to modify its expression.
Delete a rule
Delete rules that are no longer needed. Only DRAFT and INACTIVE rules can be deleted. ACTIVE rules must be deactivated first.
DELETE /v1/rules/{ruleId}
X-API-Key: {api_key}
Response: 204 No Content
Deletion is permanent. Deleted rules cannot be recovered and do not appear in any listings.
Best practices
Follow these practices for effective, maintainable rules.
Naming
- Use descriptive names - The name should clearly state what the rule does
- Include context - Mention the scenario or transaction type
- Avoid abbreviations - Prefer clarity over brevity
| Less clear | More clear |
|---|
Rule 1 | Block night transactions above BRL 5,000 |
Block high | Deny high-value weekend transactions |
PIX rule | Review PIX transfers to new recipients |
Expression design
- Keep expressions simple - Complex logic is harder to maintain
- Use scopes for filtering - Don’t repeat scope conditions in expressions
- Test edge cases - Consider boundary values and null fields
Lifecycle management
- Start in DRAFT - Test before activating
- Deactivate before editing - Never edit active rules
- Archive unused rules - Keep audit trail intact
- Delete only when certain - Deletion is permanent
Monitoring
- Review matched rules - Check which rules are triggering
- Monitor DENY rates - High deny rates may indicate overly aggressive rules
- Audit regularly - Ensure rules still align with business requirements
Common errors
Rule creation
| Code | Message | Resolution |
|---|
400 | Invalid expression syntax | Check expression syntax |
400 | Expression must return boolean | Ensure expression evaluates to true/false |
400 | Missing required field | Include all required fields |
409 | Rule name already exists | Use a unique rule name |
Rule activation
| Code | Message | Resolution |
|---|
400 | Invalid status transition | Check current rule status |
400 | Expression validation failed | Fix expression before activating |
Rule deletion
| Code | Message | Resolution |
|---|
400 | Cannot delete active rule | Deactivate before deleting |
404 | Rule not found | Verify the rule ID |
Quick reference
Endpoints
| Operation | Method | Endpoint |
|---|
| Create rule | POST | /v1/rules |
| List rules | GET | /v1/rules |
| Get rule | GET | /v1/rules/{id} |
| Update rule | PATCH | /v1/rules/{id} |
| Delete rule | DELETE | /v1/rules/{id} |
| Activate rule | POST | /v1/rules/{id}/activate |
| Deactivate rule | POST | /v1/rules/{id}/deactivate |
Actions
| Action | Description |
|---|
ALLOW | Allow the transaction |
DENY | Deny the transaction |
REVIEW | Route to manual review |
Statuses
| Status | Evaluated | Editable | Can delete |
|---|
DRAFT | No | Yes | Yes |
ACTIVE | Yes | Partial (expression immutable) | No (deactivate first) |
INACTIVE | No | Yes | Yes |
DELETED | No | No | N/A |