> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Getting started with Tracer

> Set up Tracer with Docker Compose, learn its core validation contexts, and run your first ALLOW, DENY, or REVIEW transaction validation call.

export const GMetadata = ({children}) => <Tooltip headline="Metadata" tip="Additional key-value information attached to entities like accounts or transactions — such as external IDs, reference numbers, or department codes." cta="See glossary" href="/en/glossary">
    {children}
  </Tooltip>;

export const GAuditTrail = ({children}) => <Tooltip headline="Audit trail" tip="A chronological, immutable record of every action and transaction in the system — essential for regulatory compliance and dispute resolution." cta="See glossary" href="/en/glossary">
    {children}
  </Tooltip>;

Tracer is the layer your authorization or onboarding system calls before a transaction goes through. It runs your fraud, risk, and limit policies in milliseconds and returns ALLOW, DENY, or REVIEW — so the decision lives in one place instead of being scattered across product code.

**What changes in your operation:** decision logic stops living in scattered `if` statements across services. Rule changes ship through an API the same day, not in the next release. Audit goes from "let me piece together logs from N systems" to "here is the immutable record of why this transaction got this decision."

**Trade-off to be honest about:** you add one HTTP call to the critical path of every transaction (target p99 under 80ms). In return, you get a single point for policy, audit, and analytics — and you remove duplicated logic from product code.

<Tip>
  **Who is this guide for?** Developers (junior or senior) integrating Tracer for the first time. If you're evaluating Tracer at a product or strategy level, start with [What is Tracer](./what-is-tracer.mdx). If you already have it running and need API mechanics, jump to the [Tracer API quick start](/en/reference/tracer/tracer-api-quick-start).
</Tip>

This guide walks you through setting up **Tracer** and running your first validation. In a few steps, you'll have a working environment ready to validate transactions in real time.

For step-by-step API instructions with request and response examples, see the [Tracer API quick start](/en/reference/tracer/tracer-api-quick-start).

## Why use Tracer

***

* **Real-time validation**: Make ALLOW/DENY/REVIEW decisions in under 80ms (p99)
* **Flexible rules**: Expression-based rule engine for custom business logic
* **Spending control**: Configure limits by account, portfolio, segment, and period
* **Complete <GAuditTrail>audit trail</GAuditTrail>**: Immutable validation records for SOX/GLBA compliance
* **Product-agnostic**: Supports any transaction type (Card, Wire, Pix, Crypto)

By the end of this guide, you will:

* Understand Tracer architecture and core concepts
* Have a working development environment
* Run your first transaction validation
* Configure a spending limit

***

## What is Tracer

***

Tracer is a transaction validation platform that evaluates rules and limits and returns instant decisions. Your system calls Tracer before executing transactions and acts on the decision (ALLOW, DENY, or REVIEW) according to your business logic.

### How it works

<Frame caption="Figure 1. How Tracer works">
  <img src="https://mintcdn.com/lerian-49cb71fc/SEOef3JqTInYAAau/images/en/d2/how-tracer-works.svg?fit=max&auto=format&n=SEOef3JqTInYAAau&q=85&s=27f03ce51f24a3a9e5b85cd6d6f40882" alt="How Tracer processes a validation request across its Validation, Rules, and Limits contexts and returns an ALLOW, DENY, or REVIEW decision; the Audit Context is intentionally not shown" width="1125" height="284" data-path="images/en/d2/how-tracer-works.svg" />
</Frame>

In this flow:

* **Rules** evaluate expressions against the transaction context
* **Limits** check spending thresholds for applicable scopes
* **Decision** returns ALLOW, DENY, or REVIEW based on evaluation results

### Core contexts

Tracer is built around four bounded contexts:

1. **Validation Context** - Orchestrates requests, coordinates evaluation, records audit trail
2. **Rules Context** - Manages rule definitions and expression evaluation
3. **Limits Context** - Manages spending limits and usage tracking
4. **Audit Context** - Keeps the immutable event log and verifies its hash chain

***

## Prerequisites

***

Before you start, make sure you have:

* [ ] **Docker** and **Docker Compose** installed
* [ ] **Go 1.26+** (for local development — the exact toolchain version is declared in the repository's `go.mod`)
* [ ] **PostgreSQL 17** (the shared Midaz primary, started by the platform infrastructure compose — not by Tracer's own)
* [ ] **API Key** for authentication

### Infrastructure dependencies

Tracer requires the following components:

| Component  | Version | Purpose                                                                                                                                                |
| ---------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| PostgreSQL | 17      | Data persistence and audit trail. Tracer uses its own `tracer` database on the shared Midaz PostgreSQL primary; it does not ship a dedicated instance. |

### Ports

Default ports used by Tracer services:

| Service    | Port | Description                                                                                   |
| ---------- | ---- | --------------------------------------------------------------------------------------------- |
| Tracer API | 4020 | Main REST API                                                                                 |
| PostgreSQL | 5701 | Shared Midaz PostgreSQL primary, as exposed by the shipped infrastructure example (`DB_PORT`) |

***

## Step 1: Set up the environment

***

You can run Tracer with Docker Compose or locally for development.

### Option A: Docker Compose (recommended)

<Note>
  Tracer's own Compose file declares only two services: the application and a one-shot migration runner. **PostgreSQL is not one of them** — it comes from the shared platform infrastructure Compose and must be healthy first. The application container starts only after the migration runner has applied the schema and exited successfully, so the service always boots against an already-migrated database.
</Note>

<Note>
  Tracer is available to licensed customers; its repository is maintained internally. The steps below assume you already have access to the required Tracer project files.
</Note>

Navigate to the Tracer project directory and start the services:

```bash theme={null}
cd components/tracer

# Setup environment
cp .env.example .env

# Start all services (brings up the shared infrastructure first,
# then the migration runner, then Tracer)
make up
```

### Option B: Local run

For development, you can run Tracer locally:

```bash theme={null}
# Set environment variables
export DB_HOST="localhost"
export DB_NAME="tracer"
export API_KEY="your-secure-api-key"
export API_KEY_ENABLED="true"
export SERVER_PORT="4020"
export LOG_LEVEL="INFO"

# Start the service
go run cmd/app/main.go
```

### Essential environment variables

| Variable          | Description                   | Example                  |
| ----------------- | ----------------------------- | ------------------------ |
| `DB_HOST`         | PostgreSQL host               | `localhost`              |
| `DB_NAME`         | PostgreSQL database name      | `tracer`                 |
| `API_KEY`         | API Key for authentication    | `your-secure-api-key`    |
| `API_KEY_ENABLED` | Enable API Key authentication | `true`, `false`          |
| `SERVER_PORT`     | API port                      | `4020`                   |
| `LOG_LEVEL`       | Log level                     | `INFO`, `DEBUG`, `ERROR` |

***

## Step 2: Authenticate to the API

***

Tracer supports two authentication modes. Which one you use depends on the deployment topology:

| Deployment                                  | Auth header                   | When to use                                                                                                                                                          |
| ------------------------------------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Single-tenant**                           | `X-API-Key: <api-key>`        | Local development, single-customer BYOC, or any deployment with `MULTI_TENANT_ENABLED=false` (the default).                                                          |
| **Multi-tenant (SaaS / BYOC Multi-Tenant)** | `Authorization: Bearer <jwt>` | Any deployment with `MULTI_TENANT_ENABLED=true`. The JWT is issued by [Access Manager](/en/platform/access-manager/access-manager) and carries the `tenantId` claim. |

The remaining steps in this guide use the single-tenant API Key form because most local-development setups run that way. If your environment is multi-tenant, replace `X-API-Key: your-secure-api-key` with `Authorization: Bearer $JWT` in every example.

### API Key (single-tenant)

Include the API Key in the `X-API-Key` header:

```http theme={null}
GET /v1/rules
X-API-Key: your-secure-api-key
```

### Bearer JWT (multi-tenant)

Include the JWT issued by Access Manager in the `Authorization` header:

```http theme={null}
GET /v1/rules
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

Tracer extracts the `tenantId` claim from the JWT and routes the request to the correct tenant database. **You never pass the tenant identifier in a header, path, body, or rule scope** — the token is the only source of truth.

### cURL example

```bash theme={null}
# Single-tenant: List rules
curl -H "X-API-Key: your-secure-api-key" \
  http://localhost:4020/v1/rules
```

```bash theme={null}
# Multi-tenant: List rules
curl -H "Authorization: Bearer $JWT" \
  https://tracer.sandbox.lerian.net/v1/rules
```

<Warning>
  API Keys and JWTs should be kept secure. Never expose them in client-side code or public repositories.
</Warning>

<Warning>
  API key authentication is **disabled by default** (`API_KEY_ENABLED=false`). The provided `.env.example` keeps it off so local development works without setup, but a production deployment **must** set `API_KEY_ENABLED=true` (single-tenant) or `MULTI_TENANT_ENABLED=true` and `PLUGIN_AUTH_ENABLED=true` (multi-tenant) before exposing the service.
</Warning>

***

## Step 3: Configure a spending limit

***

Spending limits control transaction amounts by scope and period. Create a limit using `POST /v1/limits`.

### Limit types

| Type              | Description                            | Period counting                                         |
| ----------------- | -------------------------------------- | ------------------------------------------------------- |
| `DAILY`           | Maximum amount per day                 | A new count starts each calendar day at 00:00 UTC       |
| `WEEKLY`          | Maximum amount per week                | A new count starts each ISO week, Monday at 00:00 UTC   |
| `MONTHLY`         | Maximum amount per month               | A new count starts on the 1st of the month at 00:00 UTC |
| `CUSTOM`          | Maximum amount for a custom date range | One count for the whole range                           |
| `PER_TRANSACTION` | Maximum per single transaction         | No count is kept                                        |

For detailed configuration of all limit types including time windows and custom periods, see the [Spending limits guide](./spending-limits.mdx).

### Scopes

Apply limits to specific contexts:

* **Segment**: Apply to all accounts in a segment (e.g., corporate customers)
* **Portfolio**: Apply to accounts in a portfolio
* **Account**: Apply to a specific account
* **Transaction type**: Apply only to CARD, WIRE, PIX, or CRYPTO

### Create a limit

```bash theme={null}
curl -X POST http://localhost:4020/v1/limits \
  -H "X-API-Key: your-secure-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Daily Corporate Card Limit",
    "description": "Daily spending limit for corporate card transactions",
    "limitType": "DAILY",
    "maxAmount": "50000.00",
    "currency": "BRL",
    "scopes": [
      {
        "segmentId": "550e8400-e29b-41d4-a716-446655440000",
        "transactionType": "CARD"
      }
    ]
  }'
```

### Activate a limit

```bash theme={null}
curl -X POST http://localhost:4020/v1/limits/{id}/activate \
  -H "X-API-Key: your-secure-api-key"
```

### Limit lifecycle

Limits are created in `DRAFT` status and follow the lifecycle `DRAFT` → `ACTIVE` → `INACTIVE`. Inactive limits can return to `DRAFT` for editing or be permanently deleted. Activate a limit to start enforcement. For the full lifecycle and transition rules, see the [Spending limits guide](./spending-limits.mdx).

### Monitor usage

Every `POST /v1/validations` response carries `limitUsageDetails`, with one entry per limit Tracer checked: the cap, the amount attempted, and the projected consumption of that cap's current period if the transaction is allowed. `GET /v1/limits/{id}/usage` reports a cumulative total across the limit's counters, for reviewing overall consumption.

For detailed configuration options, see the [Spending limits guide](./spending-limits.mdx).

***

## Step 4: Validate your first transaction

***

With limits configured, you're ready to validate a transaction using `POST /v1/validations`.

### Submit a transaction for validation

Send a validation request with the transaction context including:

* Transaction details (type, amount, currency, timestamp)
* Account information
* Optional: segment, portfolio, merchant, and custom <GMetadata>metadata</GMetadata>

```bash theme={null}
TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)

curl -X POST http://localhost:4020/v1/validations \
  -H "X-API-Key: your-secure-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "requestId": "550e8400-e29b-41d4-a716-446655440104",
    "transactionType": "CARD",
    "subType": "credit",
    "amount": "1500.00",
    "currency": "BRL",
    "transactionTimestamp": "'"$TS"'",
    "account": {
      "accountId": "550e8400-e29b-41d4-a716-446655440100"
    },
    "merchant": {
      "merchantId": "550e8400-e29b-41d4-a716-446655440103",
      "category": "5411",
      "name": "Test Merchant"
    },
    "metadata": {
      "channel": "mobile"
    }
  }'
```

<Note>
  The `transactionTimestamp` must be recent, which is why the example generates it: future timestamps are rejected with error code `0419` (1-minute clock skew tolerance), and timestamps older than 24 hours are rejected with error code `0421`.
</Note>

<Note>
  `requestId` is the idempotency key. Send a new UUID for each attempt — repeat one and Tracer returns the decision it already recorded for that key, so a rule you activated in between will not appear to take effect.
</Note>

Tracer evaluates the rules and limits that apply to the transaction, then returns one of three decisions:

| Decision | Meaning                                             | Your system should           |
| -------- | --------------------------------------------------- | ---------------------------- |
| `ALLOW`  | Transaction approved                                | Proceed with the transaction |
| `DENY`   | Transaction denied (rule matched or limit exceeded) | Block the transaction        |
| `REVIEW` | Requires manual review                              | Queue for human review       |

The response includes details about which rules were evaluated, which matched, and the current limit usage — useful for debugging and customer support.

<Info>
  **Why Tracer returns a decision instead of blocking directly.** Tracer is a decisioning layer, not an authorization gateway. The calling system is the one that holds the customer relationship, knows the channel, and decides what to do with a DENY — for example, your card-issuing system may decide to honor a `DENY` for a stand-in pre-auth but still want to capture the request for analytics. By returning a decision, Tracer fits into any authorization flow without owning the customer-facing UX.
</Info>

For complete payload structure and field details, see the [API reference](/en/reference/tracer/validate-transaction).

***

## Step 5: Create a validation rule

***

Rules let you define custom business logic that evaluates during validation. Create a rule using the `POST /v1/rules` endpoint with an expression, action, and optional scopes.

For example, to block high-value transactions:

```bash theme={null}
curl -X POST http://localhost:4020/v1/rules \
  -H "X-API-Key: your-secure-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Block high-value card transactions",
    "description": "Deny card transactions above R$ 10,000",
    "expression": "amount > 10000",
    "action": "DENY",
    "scopes": [
      {
        "transactionType": "CARD"
      }
    ]
  }'
```

<Note>
  Tracer keeps the rule name in a normalized form, so the `name` in the response can differ from the string you sent. Take the `ruleId` from the response and use it in the activate call below.
</Note>

### Activate a rule

```bash theme={null}
curl -X POST http://localhost:4020/v1/rules/{id}/activate \
  -H "X-API-Key: your-secure-api-key"
```

<Note>
  Activation takes effect right away on the instance that served the activate call, so a single-instance setup starts evaluating the rule on your next validation. When you run several instances behind a load balancer, the others pick the change up on their next rule sync (`RULE_SYNC_POLL_INTERVAL_SECONDS`, default `10`); deactivation propagates the same way.
</Note>

### Rule lifecycle

Rules follow the same lifecycle as limits: `DRAFT` → `ACTIVE` → `INACTIVE`. To start evaluation, activate the rule using `POST /v1/rules/{id}/activate`. Active rules can be deactivated and reactivated as needed.

For detailed information about rule expressions and lifecycle management, see the [Rules engine guide](./rule-engine.mdx).

***

## Observability

***

Tracer exposes endpoints for monitoring and observability.

### Key metrics

Tracer exposes OpenTelemetry-compatible metrics via the OTLP exporter, plus custom application metrics:

* `tracer_auth_failures_total{reason}` - Authentication failures by reason (missing\_api\_key, invalid\_api\_key)
* `tracer_audit_persist_failures_total` - Audit record persistence failures (compliance risk)
* `tracer_validation_rollback_failures_total` - Usage rollback failures during REVIEW decisions (eventual consistency gaps that self-correct at period boundaries)

Standard HTTP request metrics are provided automatically by Tracer's built-in OpenTelemetry HTTP middleware.

***

## Verification

***

Confirm that everything is working correctly.

### Checklist

* [ ] Docker services started and healthy
* [ ] API Key authentication working
* [ ] Spending limit configured
* [ ] Test transaction validated successfully
* [ ] Rule created and activated

***

## Next steps

***

You've successfully set up Tracer and validated your first transaction. From here, you can explore more advanced features:

* **[Integration guide](./integration-guide.mdx)** - Learn how to integrate your authorization system with Tracer
* **[Rules engine](./rule-engine.mdx)** - Write validation rules in CEL and manage their lifecycle
* **[Spending limits](./spending-limits.mdx)** - Configure and manage spending limits by scope and period
* **[Audit and compliance](./audit-compliance.mdx)** - Query validation history and understand the audit trail

***

## Quick reference

***

The three flows you'll use most:

* **Validate a transaction**: `POST /v1/validations` — see the [Tracer API quick start](/en/reference/tracer/tracer-api-quick-start) for the request shape.
* **Manage rules**: `/v1/rules` (CRUD + lifecycle endpoints `/activate`, `/deactivate`, `/draft`) — see the [Rules engine guide](./rule-engine.mdx).
* **Manage limits**: `/v1/limits` (CRUD + lifecycle + `/usage`) — see the [Spending limits guide](./spending-limits.mdx).

For the full endpoint catalog, request/response schemas, and error codes, see the [API reference](/en/openapi/v3-current/tracer.yaml).

### What your system should do with each decision

| Decision | Tracer recommends | Your system should                        |
| -------- | ----------------- | ----------------------------------------- |
| `ALLOW`  | Approval          | Proceed with the transaction              |
| `DENY`   | Denial            | Block the transaction and inform the user |
| `REVIEW` | Review            | Queue for manual review in your system    |

<Note>
  Tracer returns decisions as recommendations. Your system is responsible for implementing the appropriate action based on each decision.
</Note>
