# Transactions & Journal Entries

Transactions are the way money moves in EntryTarget. Every transaction contains one or more journal entries, each representing a debit-credit pair.

## What is a Transaction?

A transaction is a logical group of journal entries that execute atomically — either all journal entries succeed or none do. Transactions are identified by a `transaction_id` (UUID v7).

A transaction can contain multiple journal entries, potentially in different currencies. For example, a single transaction could move BRL between two accounts and USD between two other accounts.

## What is a Journal Entry?

A journal entry is a single debit-credit pair within a transaction. Each journal entry:

* Moves a specific `amount` from a **debit account** to a **credit account**
* Declares the `asset` (currency) of the movement
* Has a `sequence` number within the transaction (starting at 1)
* Has a `type` label describing the movement (e.g., `PIX_IN`, `PIX_OUT`, `FEE`)
* Applies a `balance_policy` to each side (debit and credit)

### Journal Entry Fields

| Field               | Type      | Description                                   |
| ------------------- | --------- | --------------------------------------------- |
| `id`                | UUID      | Unique identifier for the journal entry       |
| `transaction_id`    | UUID      | The transaction this journal entry belongs to |
| `entry_type`        | String    | Free-form label (e.g., `PIX_OUT`)             |
| `entry_sequence`    | Integer   | Sequence within the transaction (1, 2, 3...)  |
| `asset`             | String    | Currency code (e.g., `BRL`)                   |
| `amount`            | Integer   | Amount moved (must be > 0)                    |
| `debit_account_id`  | UUID      | The account being debited                     |
| `credit_account_id` | UUID      | The account being credited                    |
| `idempotency_key`   | String    | The idempotency key from the request header   |
| `created_at`        | Timestamp | When the journal entry was created            |

## Creating a Transaction

Every transaction request requires an `Idempotency-Key` header.

```bash
curl -X POST http://<host>:8080/transaction \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: ak_..." \
  -H "X-Api-Secret: sk_..." \
  -H "Idempotency-Key: my-unique-key-123" \
  -d '{
    "journal_entries": [
      {
        "sequence": 1,
        "type": "PIX_OUT",
        "asset": "BRL",
        "amount": 1000,
        "debit": {
          "account_id": "019702a0-...-debit",
          "balance_policy": "ALWAYS_POSITIVE"
        },
        "credit": {
          "account_id": "019702a0-...-credit",
          "balance_policy": "ALWAYS_NEGATIVE"
        }
      }
    ]
  }'
```

**Response:**

```json
{
  "transaction_id": "019702a0-...-txid",
  "journal_entries": [
    {
      "id": "019702a0-...-entry1",
      "sequence": 1,
      "type": "PIX_OUT",
      "asset": "BRL",
      "amount": 1000,
      "debit": {
        "account_id": "019702a0-...-debit",
        "category": "PAYMENT_ACCOUNT",
        "post_balance": 4000,
        "version": 5,
        "balance_policy": "ALWAYS_POSITIVE"
      },
      "credit": {
        "account_id": "019702a0-...-credit",
        "category": "PIX_ASSET",
        "post_balance": -6000,
        "version": 3,
        "balance_policy": "ALWAYS_NEGATIVE"
      }
    }
  ]
}
```

{% hint style="info" %}
POST responses do not include `created_at`. Use `GET /transaction/:id` or `GET /journal/entry/:id` to retrieve timestamps.
{% endhint %}

## Multi-Entry Transactions

A single transaction can contain multiple journal entries:

```json
{
  "journal_entries": [
    {
      "sequence": 1,
      "type": "PIX_OUT",
      "asset": "BRL",
      "amount": 1000,
      "debit": { "account_id": "uuid-customer", "balance_policy": "ALWAYS_POSITIVE" },
      "credit": { "account_id": "uuid-pix-asset", "balance_policy": "ALWAYS_NEGATIVE" }
    },
    {
      "sequence": 2,
      "type": "FEE",
      "asset": "BRL",
      "amount": 50,
      "debit": { "account_id": "uuid-customer", "balance_policy": "ALWAYS_POSITIVE" },
      "credit": { "account_id": "uuid-fee-revenue", "balance_policy": "NONE" }
    }
  ]
}
```

This atomically moves R$10.00 from the customer to the PIX asset account and R$0.50 as a fee — all or nothing.

## Multi-Currency Transactions

Journal entries within a single transaction can use different currencies:

```json
{
  "journal_entries": [
    {
      "sequence": 1,
      "type": "EXCHANGE_BRL",
      "asset": "BRL",
      "amount": 50000,
      "debit": { "account_id": "uuid-brl-account", "balance_policy": "ALWAYS_POSITIVE" },
      "credit": { "account_id": "uuid-brl-exchange", "balance_policy": "NONE" }
    },
    {
      "sequence": 2,
      "type": "EXCHANGE_USD",
      "asset": "USD",
      "amount": 10000,
      "debit": { "account_id": "uuid-usd-exchange", "balance_policy": "NONE" },
      "credit": { "account_id": "uuid-usd-account", "balance_policy": "NONE" }
    }
  ]
}
```

**Rule:** Each journal entry's debit and credit accounts must share the same asset as the journal entry's declared asset. Different journal entries within the same transaction can have different assets.

## Atomicity

If any journal entry in a transaction fails (e.g., insufficient funds on one journal entry), the **entire transaction** is rejected. No partial execution occurs.

## Querying Transactions

### Get all journal entries of a transaction

```bash
curl http://<host>:8080/transaction/<transaction_id> \
  -H "X-Api-Key: ak_..." \
  -H "X-Api-Secret: sk_..."
```

### Get a specific journal entry

```bash
curl http://<host>:8080/journal/entry/<journal_entry_id> \
  -H "X-Api-Key: ak_..." \
  -H "X-Api-Secret: sk_..."
```

## Validation Rules

| Field             | Rule                                                    |
| ----------------- | ------------------------------------------------------- |
| `sequence`        | Must start at 1 and increment without gaps (1, 2, 3...) |
| `type`            | Only `A-Z`, `0-9`, `_` — auto-converted to uppercase    |
| `asset`           | Only `A-Z`, `0-9`, `_` — auto-converted to uppercase    |
| `amount`          | Must be greater than zero                               |
| `balance_policy`  | Must be `ALWAYS_POSITIVE`, `ALWAYS_NEGATIVE`, or `NONE` |
| `Idempotency-Key` | Required header, max 100 characters                     |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://entrytarget.gitbook.io/docs/concepts/transactions-and-journal-entries.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
