---
title: "Match a bank transaction to an invoice or expense"
method: POST
path: "/v1/banking/transactions/{transactionId}/match"
tags: ["Banking"]
---

# Match a bank transaction to an invoice or expense

`POST /v1/banking/transactions/{transactionId}/match`

## Request

- Base URL: `https://api.frihet.io`
- URL: `https://api.frihet.io/v1/banking/transactions/{transactionId}/match`
- Auth: API key in header `X-API-Key`

Link a bank transaction to an invoice or expense in your workspace
(status becomes 'matched'). This records the match WITHOUT posting ledger
(GL) entries — full GL reconciliation is performed in the supervised app
flow. Fails with 409 if the transaction is already matched/reconciled.

## Path parameters

- `transactionId` string, required

## Request body

- BankMatch
  - `documentId` string, required: ID of the invoice or expense to match. Must belong to your workspace.
  - `documentType` 'invoice' | 'expense', required
  - `notes` string

## Response `200`

Transaction matched

- object
  - `data` BankTransaction: A bank transaction. Positive amount = income, negative = expense.
    - `id` string
    - `connectionId` string: ID of the owning bank account (accountId).
    - `transactionId` string: Provider transaction ID (manual-* for API-created entries).
    - `date` string, date
    - `amount` number: Positive for income, negative for expenses.
    - `currency` string
    - `description` string
    - `reference` string, nullable
    - `category` string, nullable
    - `counterparty` object, nullable
      - `name` string
      - `accountNumber` string
      - `iban` string
    - `reconciled` boolean
    - `reconciledWith` 'invoice' | 'expense', nullable
    - `reconciledId` string, nullable
    - `reconciledAt` string, date-time, nullable
    - `status` 'raw' | 'recognized' | 'matched' | 'categorized' | 'excluded'
    - `source` string, nullable
    - `createdAt` string, date-time, nullable
    - `updatedAt` string, date-time, nullable

## Other responses

- `400`: Bad request - invalid parameters or request body
- `401`: Authentication required or invalid API key
- `404`: Resource not found
- `409`: Transaction already matched/reconciled
- `429`: Rate limit exceeded (100 requests per minute)

---

[API](https://skmtc.dev/frihet/apis/frihet-api.md) · [All operations](https://skmtc.dev/frihet/apis/frihet-api/llms.txt) · [OpenAPI document](https://skmtc.dev/frihet/apis/frihet-api/revisions/3dd37f6a72d1?raw)
