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

# Invoice Transaction

> InvoiceTransaction is the reconciliation pivot record that links one Invoice to one Transaction, recording the exact amount (and optional accounting-currency eq

InvoiceTransaction is the reconciliation pivot record that links one Invoice to one Transaction, recording the exact amount (and optional accounting-currency equivalent) that the bank movement satisfies on the invoice. It is written exclusively by the reconciliation pipeline and by connector sync mapping targets; it is not mutated directly by the user-facing API. Key associations are Workspace (tenant scope), Invoice, Transaction, and optionally Subscription (for subscription-driven payments) and ExchangeRate (for multi-currency accounting conversion).

| Naming                          | Value                      |
| ------------------------------- | -------------------------- |
| Object                          | Invoice Transaction        |
| Resource type (JSON:API `type`) | `invoice_transaction`      |
| Collection / records root       | `invoice_transactions`     |
| REST base                       | `/v1/invoice-transactions` |
| Entity class                    | `InvoiceTransaction`       |

## API operations

| Operation | Method & path                          | Status        |
| --------- | -------------------------------------- | ------------- |
| List      | `GET /v1/invoice-transactions`         | ✅ Implemented |
| Retrieve  | `GET /v1/invoice-transactions/{id}`    | ✅ Implemented |
| Create    | `POST /v1/invoice-transactions`        | 🟡 Planned    |
| Update    | `PATCH /v1/invoice-transactions/{id}`  | 🟡 Planned    |
| Delete    | `DELETE /v1/invoice-transactions/{id}` | 🟡 Planned    |

## Data model

### Attributes

| Field                    | Type                              | Required | Constraints                                                                        | Allowed values                                                                                                     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ------------------------ | --------------------------------- | -------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| invoice\_transaction\_id | string, UUID                      | ✅ Yes    | unique; generated by gen\_random\_uuid() on insert                                 | —                                                                                                                  | Public immutable identifier for this reconciliation link. Exposed on all API responses; the internal pk is never surfaced.                                                                                                                                                                                                                                                                                                                                     |
| amount                   | string (decimal 12,2)             | ✅ Yes    | CHECK amount > 0; max 12 digits total, 2 decimal places                            | —                                                                                                                  | The portion of the invoice satisfied by this transaction link, expressed in the transaction's original currency. Always positive — direction is implied by the invoice/transaction relationship.                                                                                                                                                                                                                                                               |
| currency                 | string, enum (CurrencyCodeEnum)   | ✅ Yes    | Must be a valid ISO 4217 code present in currency\_code\_enum Postgres native enum | USD, EUR, GBP, JPY, CHF, CAD, AUD, NZD, SEK, NOK, DKK, PLN, CZK, … (full ISO 4217 set defined in CurrencyCodeEnum) | ISO 4217 currency code for the amount field. Matches the transaction's instructed currency at reconciliation time.                                                                                                                                                                                                                                                                                                                                             |
| accounting\_amount       | string (decimal 12,2)             | ⚪ No     | nullable; max 12 digits total, 2 decimal places                                    | —                                                                                                                  | Amount converted to the workspace accounting currency using the linked exchange\_rate. Null when no FX conversion was required (amount currency already equals accounting currency) or when the exchange rate was not available at reconciliation time.                                                                                                                                                                                                        |
| accounting\_currency     | string, enum (CurrencyCodeEnum)   | ⚪ No     | nullable; same Postgres native enum currency\_code\_enum                           | USD, EUR, GBP, JPY, CHF, CAD, AUD, NZD, SEK, NOK, DKK, PLN, CZK, … (full ISO 4217 set)                             | Currency code for accounting\_amount. Populated only when a multi-currency FX conversion was performed. Null when accounting\_amount is null.                                                                                                                                                                                                                                                                                                                  |
| is\_partial              | boolean                           | ✅ Yes    | default false                                                                      | true, false                                                                                                        | Legacy flag indicating the transaction only partially covers the invoice. Superseded by allocation\_type; kept for one release cycle for backward compatibility with the reconciliation persister. Will be dropped once allocation\_type (W19-P13) is fully rolled out.                                                                                                                                                                                        |
| allocation\_type         | string, enum (AllocationTypeEnum) | ⚪ No     | nullable; default 'full'; Postgres native enum allocation\_type\_enum              | full, partial, overpayment, fee\_deduction                                                                         | Structured classification of how the transaction satisfies the invoice. 'full' means complete payment; 'partial' means the transaction covers only part of the outstanding amount; 'overpayment' means the payment exceeds the invoice total; 'fee\_deduction' means a service fee was deducted from the gross payment before crediting the invoice. Replaces is\_partial. Null and 'full' are treated identically by the reconciliation P5 recompute service. |
| created\_at              | string, datetime, 🔒 system       | ✅ Yes    | set on insert via onCreate lifecycle hook; never updated                           | —                                                                                                                  | ISO 8601 timestamp of when this reconciliation link was created by the pipeline or connector sync.                                                                                                                                                                                                                                                                                                                                                             |
| updated\_at              | string, datetime, 🔒 system       | ⚪ No     | set on insert and on every update via onCreate/onUpdate lifecycle hooks            | —                                                                                                                  | ISO 8601 timestamp of the last modification to this record. Updated automatically by MikroORM on every flush.                                                                                                                                                                                                                                                                                                                                                  |
| deleted\_at              | string, datetime                  | ⚪ No     | nullable; null means active record; non-null means soft-deleted                    | —                                                                                                                  | Soft-delete timestamp. All active-record queries must filter deleted\_at IS NULL. A partial index idx\_invoice\_transactions\_invoice\_active on (invoice\_pk) WHERE deleted\_at IS NULL exists specifically to support the invoice-merge UPDATE path that rewrites links without a workspace bound.                                                                                                                                                           |

### Relationships

| Name           | Type                    | Required | Description                                                                                                                                                                                                                                                                          |
| -------------- | ----------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| workspace      | to-one (workspace)      | ✅ Yes    | Tenant boundary. Every InvoiceTransaction belongs to exactly one Workspace. Two composite indexes (workspace + invoice, workspace + transaction) are declared at the entity level for tenant-scoped lookup performance.                                                              |
| invoice        | to-one (invoice)        | ✅ Yes    | The invoice this bank transaction is reconciled against. FK invoice\_pk. A partial index idx\_invoice\_transactions\_invoice\_active covers invoice\_pk WHERE deleted\_at IS NULL to support invoice-merge rewrites that filter solely on invoice\_pk without a workspace predicate. |
| transaction    | to-one (transaction)    | ✅ Yes    | The bank Transaction (debit or credit movement) that satisfies part or all of the linked invoice. FK transaction\_pk.                                                                                                                                                                |
| subscription   | to-one (subscription)   | ⚪ No     | Optional link to a Subscription when the payment originates from a recurring subscription contract. Null for one-off invoice payments. FK subscription\_pk nullable.                                                                                                                 |
| exchange\_rate | to-one (exchange\_rate) | ⚪ No     | The ExchangeRate snapshot used to compute accounting\_amount / accounting\_currency during multi-currency reconciliation. Null when no FX conversion was needed. FK exchange\_rate\_pk nullable.                                                                                     |

### System-computed

* invoice\_transaction\_id is generated via gen\_random\_uuid() as the Postgres column default and mirrored by randomUUID() in the TypeScript initializer — both guarantee a unique UUID on every insert without application-level collision risk.
* created\_at is set to new Date() by an onCreate MikroORM lifecycle hook on the entity property initializer; it is never updated after insert.
* updated\_at is set by both onCreate and onUpdate hooks, so it reflects the timestamp of the most recent flush for any property change.
* deleted\_at is null on creation and is set to a non-null Date by soft-delete callers (reconciliation pipeline / connector sync unlink). All active-record queries must include deleted\_at: null in their filter predicates.
* is\_partial defaults to false at the TypeScript level; this maps to DEFAULT false in Postgres. It is a deprecated surrogate for allocation\_type and will be dropped in a future migration once W19-P13 is complete.
* allocation\_type defaults to AllocationTypeEnum.FULL ('full') at both the TypeScript level and the Postgres column default (DEFAULT 'full'). The reconciliation P5 recompute service treats NULL and 'full' as semantically identical.
* accounting\_amount and accounting\_currency are pipeline-computed from the linked ExchangeRate at reconciliation time; they are null when the transaction currency already matches the workspace accounting currency or when FX data was unavailable.
* This entity is one of the 12 target models in the MCP connector sync mapping pipeline (ConnectorMapping target model: invoice\_transaction). Records may be created or soft-deleted by the connector sync persister as well as the Well reconciliation agent.
* Three indexes are declared at the entity class level: composite (workspace\_pk, invoice\_pk), composite (workspace\_pk, transaction\_pk), and a partial expression index idx\_invoice\_transactions\_invoice\_active on (invoice\_pk) WHERE deleted\_at IS NULL — the last index is required specifically for the invoice-merge UPDATE path that rewrites foreign keys without a workspace bound.

## Example

```json theme={null}
{
  "data": {
    "type": "invoice_transaction",
    "id": "a3f7c291-84e2-4b10-9d2e-1f5b0c3e8a47",
    "attributes": {
      "invoice_transaction_id": "a3f7c291-84e2-4b10-9d2e-1f5b0c3e8a47",
      "amount": "2500.00",
      "currency": "EUR",
      "accounting_amount": "2712.50",
      "accounting_currency": "USD",
      "is_partial": false,
      "allocation_type": "full",
      "created_at": "2026-04-14T09:23:11.000Z",
      "updated_at": "2026-04-14T09:23:11.000Z",
      "deleted_at": null
    },
    "relationships": {
      "workspace": {
        "data": { "type": "workspace", "id": "b1c2d3e4-f5a6-7890-abcd-ef1234567890" }
      },
      "invoice": {
        "data": { "type": "invoice", "id": "c9d8e7f6-a5b4-3c2d-1e0f-9a8b7c6d5e4f" }
      },
      "transaction": {
        "data": { "type": "transaction", "id": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90" }
      },
      "subscription": {
        "data": null
      },
      "exchange_rate": {
        "data": { "type": "exchange_rate", "id": "e1f2a3b4-c5d6-7890-abcd-123456789abc" }
      }
    }
  }
}
```

<sub>Source: `apps/api/src/database/entities/InvoiceTransaction.ts` · domain: financial-graph · tier: Supporting</sub>
