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

# Overview

## Getting Started with FinWatch

This guide takes you from zero to a running FinWatch instance with your first fraud detection rule evaluated — in under 10 minutes.

## What is FinWatch?

FinWatch is an **embeddable, developer-first fraud detection engine** designed to run alongside your fintech application. Unlike traditional fraud detection platforms that operate as opaque, external services, FinWatch deploys directly into your infrastructure and gives you full transparency and control over the rules that govern your transaction monitoring.

At its core, FinWatch provides three things:

1. **The Watch Script DSL** — A purpose-built domain-specific language for writing fraud detection rules. Rules are stored as `.ws` files that can be versioned in Git, reviewed in pull requests, and deployed with the same rigour as your application code. The language is designed to express complex fraud patterns — velocity checks, time-based anomalies, sequential behaviour analysis — in a readable, declarative format.
2. **An Embedded Analytical Engine** — FinWatch uses [DuckDB](https://duckdb.org/), a high-performance embedded analytical database, to store and query transaction data locally. This means aggregate functions like **"count the number of transactions from this account in the last 24 hours"** execute in milliseconds without requiring a round-trip to an external database. DuckDB's columnar storage and vectorised execution engine are optimised for exactly this type of analytical workload.
3. **GitOps-Native Rule Management** — Rules can be synced from a Git repository, enabling a full CI/CD lifecycle for fraud logic; write a rule, open a PR, get it reviewed by your compliance team, merge, and FinWatch picks it up automatically. Every change is audited, every version is recoverable.

The result is a fraud detection system that is fast to deploy, transparent to audit, and powerful enough to catch sophisticated fraud patterns that simple regex-based systems miss entirely.

***

## Prerequisites

Before you begin, make sure you have the following:

* **Docker** (recommended) — [Install Docker](https://docs.docker.com/get-docker/)
* **curl** — For sending HTTP requests from the command line. Pre-installed on macOS and most Linux distributions.
* **A text editor** — For writing `.ws` rule files. Any editor works;` VS Code` is recommended.
* **Basic terminal knowledge** — You should be comfortable running commands in a terminal.

If you plan to build from source instead of using Docker:

* **Go 1.21+** — [Install Go](https://go.dev/doc/install)
* **Git** — For cloning the repository and (optionally) for GitOps rule management.

***

## Installation

### Docker

The fastest way to get FinWatch running:

```bash theme={null}
docker run -d \
  --name finwatch \
  -p 8081:8081 \
  -e WATCH_SCRIPT_DIR=/app/watch_scripts \
  -v $(pwd)/my_rules:/app/watch_scripts \
  finwatch/finwatch:latest
```

This command:

* Starts FinWatch in the background (`-d`).
* Maps port `8081` on your host to port `8081` in the container.
* Sets the watch script directory to `/app/watch_scripts` inside the container.
* Mounts a local directory (`my_rules/`) so you can add and edit rule files from your host machine.

Verify it's running:

```bash theme={null}
curl http://localhost:8081/instructions
```

You should see an empty JSON array `[]` — this means FinWatch is running and ready.

### Environment Variables

FinWatch's behaviour is configured through environment variables. Here is a complete reference:

<Columns cols={2}>
  <Card title="WATCH_SCRIPT_DIR" icon="folder">
    **Default:** `watch_scripts`

    Directory where `.ws` rule files are stored and watched for changes.
  </Card>

  <Card title="WATCH_SCRIPT_GIT_REPO" icon="git">
    **Default:** *(empty)*

    Git repository URL to sync rules from. If set, enables GitOps mode.
  </Card>

  <Card title="WATCH_SCRIPT_GIT_BRANCH" icon="git">
    **Default:** `main`

    The Git branch to track for rule updates.
  </Card>

  <Card title="CLIENT_DSN" icon="database">
    **Default:** *(empty)*

    PostgreSQL connection string for the  database. Enables the watermark sync feature.
  </Card>

  <Card title="FINWATCH_MEMORY_LIMIT" icon="zap">
    **Default:** `2GiB`

    Maximum memory DuckDB is allowed to use. Accepts values like `1GiB`, `4GiB`, `512MiB`.
  </Card>

  <Card title="FINWATCH_PORT" icon="server">
    **Default:** `8081`

    The HTTP port FinWatch listens on.
  </Card>
</Columns>

***

## Your First Transaction

With FinWatch running, let's inject a transaction. This simulates what your application would do in production: sending a transaction to FinWatch for real-time risk evaluation.

Run the following `curl` command:

```bash theme={null}
curl -X POST http://localhost:8081/inject \
  -H "Content-Type: application/json" \
  -d '{
    "transaction_id": "txn_001",
    "amount": 15000.00,
    "currency": "USD",
    "source": "acct_alice_123",
    "destination": "acct_bob_456",
    "reference": "invoice_2026_001",
    "description": "Consulting payment",
    "status": "pending",
    "created_at": "2026-04-18T14:30:00Z",
    "meta_data": {
      "ip_address": "192.168.1.100",
      "destination_country": "US",
      "device_type": "mobile"
    }
  }'
```

**Field-by-field explanation:**

| Field            | Type             | Required | Description                                                                                                                                     |
| ---------------- | ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `transaction_id` | string           | No       | A unique identifier. Auto-generated as a UUID if not provided.                                                                                  |
| `amount`         | float            | **Yes**  | The monetary value of the transaction.                                                                                                          |
| `currency`       | string           | **Yes**  | The ISO 4217 currency code (e.g., `"USD"`, `"EUR"`, `"NGN"`).                                                                                   |
| `source`         | string           | No       | The account or entity initiating the transaction.                                                                                               |
| `destination`    | string           | No       | The account or entity receiving the transaction.                                                                                                |
| `reference`      | string           | **Yes**  | A unique reference string for idempotency.                                                                                                      |
| `description`    | string           | No       | A human-readable description of the transaction.                                                                                                |
| `status`         | string           | No       | The current status of the transaction (e.g., `"pending"`, `"applied"`, `"failed"`).                                                             |
| `created_at`     | string (RFC3339) | No       | The timestamp of the transaction. Defaults to the current time if not provided.                                                                 |
| `meta_data`      | object           | No       | Arbitrary key-value metadata. This is where you put custom fields your rules can reference (e.g., IP address, country, device type, MCC codes). |

A successful response returns HTTP `200 OK` with an empty body. The transaction is now stored in DuckDB and has been evaluated against all active rules.

At this point, you have no rules — so nothing was flagged. Let's fix that.

***

## Your First Rule

Create a directory for your rules (if you haven't already) and add a new file:

```bash theme={null}
mkdir -p my_rules
```

Now create a file called `HighValueCheck.ws` inside `my_rules/`:

```go lines theme={null}
rule HighValueCheck {
    description "Flags any transaction over $10,000 for manual review."

    when amount > 10000

    then review
         score  0.7
         reason "Transaction amount exceeds $10,000 high-value threshold"
}
```

**What this rule does:**

* **Name:** `HighValueCheck` — A clear, descriptive identifier.
* **Description:** Explains the rule's purpose in plain English for auditors and analysts.
* **Condition (`when`):** Checks if the transaction's `amount` field is greater than `10000`.
* **Action (`then`):**
  * **Verdict:** `review` — Flag for human analyst review (don't hard-block).
  * **Score:** `0.7` — High confidence that this warrants attention.
  * **Reason:** A clear explanation that will appear in logs and dashboards.

FinWatch watches the `my_rules/` directory for changes. Within seconds of saving the file, you should see a log message indicating the rule was compiled:

```shellscript theme={null}
INF Compiled watch script: HighValueCheck
```

### Testing the Rule

Now inject the same transaction again:

```bash theme={null}
curl -X POST http://localhost:8081/inject \
  -H "Content-Type: application/json" \
  -d '{
    "transaction_id": "txn_002",
    "amount": 15000.00,
    "currency": "USD",
    "source": "acct_alice_123",
    "destination": "acct_bob_456",
    "reference": "invoice_2026_002",
    "description": "Consulting payment",
    "status": "pending",
    "meta_data": {
      "destination_country": "US"
    }
  }'
```

This time, the `$15,000` transaction exceeds the `$10,000` threshold in your rule. In the FinWatch logs, you'll see that the `HighValueCheck` rule fired and produced a `review` verdict with a `0.7` risk score.

Now inject a transaction that should **not** trigger the rule:

```bash theme={null}
curl -X POST http://localhost:8081/inject \
  -H "Content-Type: application/json" \
  -d '{
    "transaction_id": "txn_003",
    "amount": 500.00,
    "currency": "USD",
    "source": "acct_charlie_789",
    "destination": "acct_dave_012",
    "reference": "coffee_shop_001",
    "description": "Coffee purchase"
  }'
```

This `$500` transaction falls well below the `$10,000` threshold. The rule does not fire. No verdict is produced.

***

## What Just Happened?

Here's the complete flow of what happened when you injected that `$15,000` transaction:

```mermaid placement="top-left" actions={false} theme={null}
graph TD
    A["Your Application<br/>(curl POST /inject)"]
    B["FinWatch HTTP API<br/>(Port 8081)"]
    C["Transaction Storage<br/>(DuckDB)<br/><br/>← Transaction persisted locally"]
    D["Rule Engine<br/>HighValueCheck.ws<br/><br/>← amount 15000 &gt; 10000 → TRUE"]
    E["Risk Consolidator<br/><br/>← Aggregates verdicts from all rules<br/>Score: 0.7<br/>Verdict: review"]
    F["Anomaly Reporter<br/>(WebSocket Tunnel)<br/><br/>← Sends to FinWatch Cloud dashboard<br/>via WebSocket if connected"]

    A --> B
    B --> C
    C --> D
    D --> E
    E --> F
```

1. **Ingestion:** The HTTP handler receives the JSON payload and decodes it into a `Transaction` struct.
2. **Storage:** The transaction is inserted into the local DuckDB `transactions` table. This makes it available for aggregate queries by other rules.
3. **Rule Evaluation:** The engine loads all compiled rules and evaluates them against the transaction. Each rule's `when` clause is checked. If it evaluates to `true`, the `then` clause produces a `RiskVerdict`.
4. **Risk Consolidation:** All verdicts are aggregated. The final risk score, verdict, and reason are determined.
5. **Anomaly Reporting:** If the final verdict warrants it, an anomaly notification is sent to the FinWatch Cloud dashboard via the WebSocket tunnel for real-time alerting.

***

## Next Steps

You've successfully installed FinWatch, injected a transaction, and written your first rule. Here's where to go from here:

* [**Writing Your First Rule**](writing-your-first-rule.md) — A deeper tutorial on building rules step by step.
* [**Conditions Deep Dive**](conditions-deep-dive.md) — Learn every operator, logical combinator, and pattern matching technique available in the `when` clause.
* [**Aggregate Functions Guide**](aggregate-functions-guide.md) — The most powerful feature of the DSL: detecting fraud patterns over time using `count()`, `sum()`, `avg()`, and more.
* [**The Rule Cookbook**](rule-cookbook.md) — A library of production-ready rule patterns you can copy and customise.
* [**DSL Reference**](../DSL_REFERENCE.md) — The complete language reference for the Watch Script DSL.
* [**API Documentation**](../../watch/API_DOCUMENTATION.md) — Full REST API reference for all FinWatch endpoints.
