What Is the Purpose of the Rules Engine API in Securo?
The rules engine API in Securo enables users to define, manage, and automatically apply categorization rules to financial transactions through a comprehensive set of CRUD, preview, import/export, and bulk operation endpoints.
The rules engine API serves as the programmatic interface for Securo's transaction categorization system. Located in the backend FastAPI application, this API allows users to create declarative rules that automatically tag and organize financial transactions based on configurable conditions. This article examines the implementation in backend/app/api/rules.py and its supporting service layer to explain exactly how the rules engine functions.
Core Purpose: Automated Transaction Categorization
The rules engine solves a fundamental problem in personal finance management: manually categorizing hundreds or thousands of transactions is tedious and error-prone. The API provides a programmable, user-editable system where rules evaluate transaction fields (description, amount, merchant, etc.) and apply actions like setting a category or adding tags.
According to the Securo source code, the rules engine supports:
- Rule lifecycle management — Create, read, update, and delete categorization rules
- Immediate application — Apply rules to existing transactions upon creation or modification
- Safe experimentation — Preview rule effects without persisting changes
- Data portability — Export and import rule sets as JSON
- Pre-built rule packs — Install country-specific or domain-specific rule collections
- Bulk reprocessing — Re-run all active rules against the entire transaction history
CRUD Operations for Rules
The foundation of the rules engine API is standard resource management for rule objects. These endpoints interact with the rule service to persist rule definitions and enforce workspace-level isolation.
List and Create Rules
The GET /api/rules endpoint retrieves all rules for the current workspace. The POST /api/rules endpoint creates new rules with optional immediate application to existing transactions.
# backend/app/api/rules.py
@router.get("/api/rules")
async def list_rules(
workspace_ctx: WorkspaceContext = Depends(get_workspace_context),
rule_service: RuleService = Depends(get_rule_service)
):
"""Retrieve all rules for the current workspace."""
return await rule_service.list_rules(workspace_ctx.workspace_id)
When creating a rule, the API accepts a boolean apply_to_existing flag. If true, the service immediately applies the new rule to all matching transactions in the workspace:
# backend/app/api/rules.py (simplified)
@router.post("/api/rules")
async def create_rule(
rule_data: RuleCreate,
workspace_ctx: WorkspaceContext = Depends(get_workspace_context),
rule_service: RuleService = Depends(get_rule_service)
):
created_rule = await rule_service.create_rule(
workspace_id=workspace_ctx.workspace_id,
user_id=workspace_ctx.user_id,
data=rule_data
)
# Conditionally apply to existing transactions
if rule_data.apply_to_existing:
applied_count = await rule_service.apply_single_rule(
rule=created_rule,
workspace_id=workspace_ctx.workspace_id,
overwrite_existing=rule_data.overwrite_existing_categories
)
created_rule.applied_count = applied_count
return created_rule
The service call to apply_single_rule (backend/app/api/rules.py#L96-L107) ensures that rule changes take effect immediately rather than only applying to future transactions.
Preview Rules Without Persistence
The POST /api/rules/preview endpoint addresses a critical user need: testing rule logic before committing changes. This endpoint accepts a rule definition identical to the create payload but does not persist anything to the database.
# Example preview request
import requests
preview_payload = {
"conditions_op": "any",
"conditions": [
{"field": "description", "op": "contains", "value": "Netflix"}
],
"actions": [
{"type": "category", "value": "Entertainment"}
],
"is_active": True,
"apply_to_existing": False,
"limit": 10 # Restrict preview to N matching transactions
}
response = requests.post(
"https://api.securo.finance/api/rules/preview",
json=preview_payload,
headers={"Authorization": "Bearer <TOKEN>"}
)
# Response includes matched transactions and proposed changes
print(response.json())
The preview logic (backend/app/api/rules.py#L13-L33) executes the rule's condition matching against actual transaction data but returns only a projection of what would change—no writes occur.
Export and Import Rule Sets
Data portability is essential for backup, migration, and sharing configurations. The rules engine API provides bidirectional JSON serialization.
Export Rules
The GET /api/rules/export endpoint generates a downloadable JSON file containing all rules in the workspace:
# backend/app/api/rules.py (simplified)
@router.get("/api/rules/export")
async def export_rules(
workspace_ctx: WorkspaceContext = Depends(get_workspace_context),
rule_service: RuleService = Depends(get_rule_service)
):
"""Export all workspace rules as JSON."""
rules_data = await rule_service.export_rules(workspace_ctx.workspace_id)
return Response(
content=json.dumps(rules_data, indent=2, default=str),
media_type="application/json",
headers={"Content-Disposition": "attachment; filename=securo-rules.json"}
)
Implementation at backend/app/api/rules.py#L38-L49.
Import Rules
The POST /api/rules/import endpoint accepts a previously exported JSON payload and recreates rules in the target workspace:
import json
import requests
with open("my-securo-rules.json") as f:
rules_content = f.read()
import_payload = {
"payload": rules_content,
"overwrite": True # Replace existing rules with same name
}
response = requests.post(
"https://api.securo.finance/api/rules/import",
json=import_payload,
headers={"Authorization": "Bearer <TOKEN>"}
)
The import handler at backend/app/api/rules.py#L52-L73 validates the schema, handles duplicate detection based on the overwrite flag, and reports import statistics.
Rule Packs: Pre-Built Categorization Logic
Securo ships with rule packs—curated collections of rules for specific countries or financial domains. The API exposes endpoints to discover and install these packs.
List Available Packs
The GET /api/rules/packs endpoint enumerates installable rule packs with metadata (country code, description, rule count).
Install a Rule Pack
The POST /api/rules/packs/{pack_code}/install endpoint applies a complete rule set to the workspace. The implementation (backend/app/api/rules.py#L48-L70) optionally creates missing default categories referenced by the pack's rules:
# Example: Install Brazil-specific rules
response = requests.post(
"https://api.securo.finance/api/rules/packs/BR/install",
json={"create_missing_categories": True},
headers={"Authorization": "Bearer <TOKEN>"}
)
This feature enables rapid onboarding for users in supported markets without requiring manual rule configuration.
Bulk Re-Application with Apply-All
The POST /api/rules/apply-all endpoint provides a nuclear option: re-run every active rule against every transaction in the workspace. This is essential after:
- Bulk transaction imports
- Rule pack installations
- Changing category structures
- Recovering from data inconsistencies
# Trigger full re-categorization
response = requests.post(
"https://api.securo.finance/api/rules/apply-all",
headers={"Authorization": "Bearer <TOKEN>"}
)
# Response typically includes statistics on matches and updates
print(response.json())
The endpoint at backend/app/api/rules.py#L78-L85 delegates to the rule service's bulk application logic, which processes rules in priority order and handles conflicts when multiple rules match the same transaction.
Rule Service: The Implementation Layer
The API layer in backend/app/api/rules.py is a thin wrapper around backend/app/services/rule_service.py. The service encapsulates:
| Method | Purpose |
|---|---|
create_rule |
Persist new rule with validation and uniqueness checks |
apply_single_rule |
Execute one rule against matching transactions ([rule_service.py](https://github.com/securo-finance/securo/blob/main/backend/app/services/rule_service.py)) |
preview_rule |
Simulate rule execution without persistence |
export_rules |
Serialize workspace rules to portable JSON |
import_rules |
Deserialize and validate rule imports with duplicate handling |
install_rule_pack |
Expand pack templates into workspace rules |
apply_all_rules |
Orchestrate bulk re-application with priority ordering |
The service uses WorkspaceContext ([backend/app/core/workspace_context.py](https://github.com/securo-finance/securo/blob/main/backend/app/core/workspace_context.py)) to enforce multi-tenant isolation—every rule operation is scoped to the authenticated user's workspace.
Complete API Endpoint Reference
| Endpoint | Method | Purpose |
|---|---|---|
/api/rules |
GET | List all workspace rules |
/api/rules |
POST | Create new rule with optional immediate application |
/api/rules/{rule_id} |
PATCH | Update existing rule |
/api/rules/{rule_id} |
DELETE | Remove a rule |
/api/rules/preview |
POST | Test rule logic without saving |
/api/rules/export |
GET | Download rules as JSON |
/api/rules/import |
POST | Upload and install rules from JSON |
/api/rules/packs |
GET | List available rule packs |
/api/rules/packs/{pack_code}/install |
POST | Install a rule pack |
/api/rules/apply-all |
POST | Re-run all active rules on all transactions |
Summary
Securo's rules engine API provides a complete infrastructure for automated transaction categorization:
- Rule CRUD with workspace isolation and immediate application to historic data
- Safe experimentation through the preview endpoint
- Data portability via JSON export/import
- Accelerated setup through installable rule packs
- Maintenance operations including bulk re-application
The API design separates HTTP concerns in backend/app/api/rules.py from business logic in backend/app/services/rule_service.py, enabling testable, maintainable code that scales with user demand.
Frequently Asked Questions
What is the difference between creating a rule and previewing a rule?
Creating a rule persists the rule definition to the database and optionally applies it to existing transactions. Previewing a rule executes the rule logic against actual transaction data but makes no changes—it's a read-only simulation for validation. Use preview to test conditions and actions before committing.
How do rule packs differ from individual rules?
Rule packs are pre-built collections of rules distributed with Securo for specific countries or use cases. Installing a pack creates multiple individual rules in your workspace. Packs provide sensible defaults for new users, while individual rules allow fine-grained customization.
What happens when I call apply-all?
The apply-all endpoint re-executes every active rule against every transaction in your workspace, in priority order. This is useful for maintaining consistency after bulk imports or rule changes. The operation is idempotent—running it multiple times produces the same result.
Can I undo a rule import or apply-all operation?
Securo does not provide automatic undo functionality. To revert changes, you must re-import a previous export or manually delete undesired rules. The export feature at backend/app/api/rules.py#L38-L49 enables you to create restore points before major operations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →