# What Is the Purpose of the Rules Engine API in Securo?

> Discover how Securo's rules engine API automates financial transaction categorization with CRUD, preview, and bulk operations. Define and manage rules effortlessly.

- Repository: [securo-finance/securo](https://github.com/securo-finance/securo)
- Tags: api-reference
- Published: 2026-08-28

---

**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`](https://github.com/securo-finance/securo/blob/main/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.

```python

# 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:

```python

# 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`](https://github.com/securo-finance/securo/blob/main/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.

```python

# 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`](https://github.com/securo-finance/securo/blob/main/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:

```python

# 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`](https://github.com/securo-finance/securo/blob/main/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:

```python
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`](https://github.com/securo-finance/securo/blob/main/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`](https://github.com/securo-finance/securo/blob/main/backend/app/api/rules.py#L48-L70)) optionally creates missing default categories referenced by the pack's rules:

```python

# 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

```python

# 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`](https://github.com/securo-finance/securo/blob/main/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`](https://github.com/securo-finance/securo/blob/main/backend/app/api/rules.py) is a thin wrapper around [`backend/app/services/rule_service.py`](https://github.com/securo-finance/securo/blob/main/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/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)](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`](https://github.com/securo-finance/securo/blob/main/backend/app/api/rules.py) from business logic in [`backend/app/services/rule_service.py`](https://github.com/securo-finance/securo/blob/main/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`](https://github.com/securo-finance/securo/blob/main/backend/app/api/rules.py#L38-L49) enables you to create restore points before major operations.