# Bank statements tools

> MCP tools for Bank statements: bank_statements_imports_create, bank_statements_imports_get, bank_statements_imports_list, bank_statements_lines_ignore, bank_statements_lines_list, bank_statements_lines_match.

- `bank_statements_imports_create`: Import a bank statement
- `bank_statements_imports_get`: Get a bank statement import
- `bank_statements_imports_list`: List bank statement imports
- `bank_statements_lines_ignore`: Ignore a bank statement line
- `bank_statements_lines_list`: List bank statement lines
- `bank_statements_lines_match`: Match a bank statement line to an invoice

## `bank_statements_imports_create`

**Import a bank statement.** Operation [`bank_statements.imports.create`](https://ownrecord.io/docs/reference/bank-statements-imports-create.md) · Legal entity level · permission `invoices:write` · risk tier `financial` · since M5

Imports a bank statement of the legal entity's account as CSV and matches its incoming transfers to open
invoices of every brand of the entity (send_invoice invoices carry their number as the payment reference).

- The file needs a header row and, per booked transaction, a booking date, a signed amount (incoming money is
  positive), the reference and optionally the counterparty and a currency. Columns are recognised by common
  header names (English, German, Croatian) or named in `columns`; dates as `YYYY-MM-DD`, `DD.MM.YYYY` or with
  slashes (`dateFormat` required); `decimalSeparator` `.` or `,`. A file with an unreadable row is refused
  whole (`bank_statement_invalid`, rows in `details.errors`); at most 2,000 transactions per file.
- The same file twice is refused; lines an earlier import has (overlapping statements) are skipped and
  counted as `duplicates`.
- A line whose reference names exactly one open invoice and whose amount is that invoice's amount due pays
  it at once, as `invoices.mark_paid` would on the booking date (`invoice.paid`; a past-due subscription
  recovers). Every other line waits in the review queue (`bank_statements.lines.list` with
  `matchStatus=partial,unmatched`) with the reason and the invoices it may pay.

Financial tier: it records payments. Dry-run it first to see the matches without saving anything. CAMT.053
files arrive in a later version.

Annotations: `readOnlyHint: false` · `destructiveHint: false` · `idempotentHint: false` · `openWorldHint: false`

### Arguments

| Argument           | Type                                                          | Required | Description                                                                                                                                                                                              |
| ------------------ | ------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `csv`              | string                                                        | yes      | The statement as CSV text: a header row, then one booked transaction per row (booking date, signed amount, reference, optionally counterparty and currency). (1–2000000 characters)                      |
| `currency`         | string                                                        | yes      | The bank account's currency (rows without a currency column).                                                                                                                                            |
| `filename`         | string                                                        | no       | (1–200 characters)                                                                                                                                                                                       |
| `delimiter`        | one of `,`, `;`, `	`                                          | no       | `,`, `;` or a tab. Default: detected from the header.                                                                                                                                                    |
| `dateFormat`       | one of `YYYY-MM-DD`, `DD.MM.YYYY`, `DD/MM/YYYY`, `MM/DD/YYYY` | no       | Default: `YYYY-MM-DD`, or `DD.MM.YYYY` when the dates have dots. Dates with slashes need it.                                                                                                             |
| `decimalSeparator` | one of `.`, `,`                                               | no       | Default: `,` in `;`-separated files, else `.`.                                                                                                                                                           |
| `columns`          | object                                                        | no       | Header names to use when the recognised ones don't fit (e.g. `{ reference: "Remittance" }`).                                                                                                             |
| `entity_id`        | ID (`ent_…`)                                                  | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity.                                                        |
| `idempotency_key`  | string                                                        | no       | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's `idempotency_key`. (1–255 characters) |
| `dry_run`          | boolean                                                       | no       | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default `false`)                                                                                 |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Idempotency:** the result returns the `idempotency_key` used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
- **Dry run:** supported. `dry_run: true` checks permissions and rules and computes the result, then rolls everything back.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A field is malformed or out of range.
- [`bank_statement_invalid`](https://ownrecord.io/docs/reference/errors.md#bank_statement_invalid): The CSV can't be read: a missing column, a bad date or amount (`details.errors` lists the rows).
- [`bank_statement_already_imported`](https://ownrecord.io/docs/reference/errors.md#bank_statement_already_imported): This exact file was imported before (`details.import_id`).
- [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict): An invoice or line changed at the same time (another import or payment); retry.
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): The credentials can't record invoice payments for this entity (`invoices:write`, finance).

### Example

**Import a statement: one transfer pays its invoice, two wait for review**

Arguments:

```json
{
  "csv": "Booking date,Amount,Reference,Counterparty\n2026-11-04,1200.00,GEN-2026-000131,Alpen Apps GmbH\n2026-11-04,450.00,Invoice 2026-000132,Berg Software AG\n2026-11-04,-12.50,Account fee,Bank",
  "currency": "EUR",
  "filename": "statement-2026-11-04.csv",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "id": "bsi_01m4tx5nj8emwbyf7y9vcf48ba",
  "object": "bank_statement_import",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47zm",
  "livemode": false,
  "format": "csv",
  "filename": "statement-2026-11-04.csv",
  "currency": "EUR",
  "lineCount": 3,
  "counts": {
    "imported": 3,
    "duplicates": 0,
    "matched": 1,
    "partial": 0,
    "unmatched": 2,
    "ignored": 0
  },
  "from": "2026-11-04",
  "to": "2026-11-04",
  "options": {
    "delimiter": ",",
    "dateFormat": null,
    "decimalSeparator": null,
    "columns": {
      "bookingDate": "Booking date",
      "amount": "Amount",
      "reference": "Reference",
      "counterparty": "Counterparty",
      "currency": null
    }
  },
  "importedBy": {
    "type": "user",
    "id": "usr_01m4tx5nj8emwbyf7y9vcf47zk"
  },
  "version": 2,
  "createdAt": "2026-11-05T09:00:00.000Z",
  "updatedAt": "2026-11-05T09:00:00.000Z",
  "paidInvoiceIds": ["inv_01m4tx5nj8emwbyf7y9vcf47zn"]
}
```

## `bank_statements_imports_get`

**Get a bank statement import.** Operation [`bank_statements.imports.get`](https://ownrecord.io/docs/reference/bank-statements-imports-get.md) · Legal entity level · permission `invoices:read` · risk tier `read` · since M5

Returns one imported bank statement: the file's name, how it was read (delimiter, date
format, decimal separator, the columns used), the booking-date range and its lines counted by match status.
List its lines with `bank_statements.lines.list` and `importId`.

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument    | Type         | Required | Description                                                                                                                                       |
| ----------- | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`        | ID (`bsi_…`) | yes      | –                                                                                                                                                 |
| `entity_id` | ID (`ent_…`) | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity. |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A field is malformed or out of range.
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): No bank statement import or line with this ID is visible to the request.
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): The credentials can't read this entity's invoices (`invoices:read`).

### Example

**An import**

Arguments:

```json
{
  "id": "bsi_01m4tx5nj8emwbyf7y9vcf48ba",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy"
}
```

Result `output`:

```json
{
  "id": "bsi_01m4tx5nj8emwbyf7y9vcf48ba",
  "object": "bank_statement_import",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47zm",
  "livemode": false,
  "format": "csv",
  "filename": "statement-2026-11-04.csv",
  "currency": "EUR",
  "lineCount": 3,
  "counts": {
    "imported": 3,
    "duplicates": 0,
    "matched": 1,
    "partial": 0,
    "unmatched": 2,
    "ignored": 0
  },
  "from": "2026-11-04",
  "to": "2026-11-04",
  "options": {
    "delimiter": ",",
    "dateFormat": null,
    "decimalSeparator": null,
    "columns": {
      "bookingDate": "Booking date",
      "amount": "Amount",
      "reference": "Reference",
      "counterparty": "Counterparty",
      "currency": null
    }
  },
  "importedBy": {
    "type": "user",
    "id": "usr_01m4tx5nj8emwbyf7y9vcf47zk"
  },
  "version": 2,
  "createdAt": "2026-11-05T09:00:00.000Z",
  "updatedAt": "2026-11-05T09:00:00.000Z"
}
```

## `bank_statements_imports_list`

**List bank statement imports.** Operation [`bank_statements.imports.list`](https://ownrecord.io/docs/reference/bank-statements-imports-list.md) · Legal entity level · permission `invoices:read` · risk tier `read` · since M5

Lists the legal entity's imported bank statements in the mode of the request, newest first, with their lines
counted by match status (`matched`, `partial` and `unmatched` waiting for review, `ignored`) and the
duplicates skipped.

Paginate with `limit` (1–100, default 10) and `starting_after` (the `next_cursor` of the previous page).

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument         | Type         | Required | Description                                                                                                                                       |
| ---------------- | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `limit`          | integer      | no       | (1–100)                                                                                                                                           |
| `starting_after` | ID (`bsi_…`) | no       | –                                                                                                                                                 |
| `entity_id`      | ID (`ent_…`) | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity. |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A field is malformed or out of range.
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): No bank statement import or line with this ID is visible to the request.
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): The credentials can't read this entity's invoices (`invoices:read`).

### Example

**The latest imports**

Arguments:

```json
{
  "limit": 10,
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy"
}
```

Result `output`:

```json
{
  "object": "list",
  "data": [
    {
      "id": "bsi_01m4tx5nj8emwbyf7y9vcf48ba",
      "object": "bank_statement_import",
      "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47zm",
      "livemode": false,
      "format": "csv",
      "filename": "statement-2026-11-04.csv",
      "currency": "EUR",
      "lineCount": 3,
      "counts": {
        "imported": 3,
        "duplicates": 0,
        "matched": 1,
        "partial": 0,
        "unmatched": 2,
        "ignored": 0
      },
      "from": "2026-11-04",
      "to": "2026-11-04",
      "options": {
        "delimiter": ",",
        "dateFormat": null,
        "decimalSeparator": null,
        "columns": {
          "bookingDate": "Booking date",
          "amount": "Amount",
          "reference": "Reference",
          "counterparty": "Counterparty",
          "currency": null
        }
      },
      "importedBy": {
        "type": "user",
        "id": "usr_01m4tx5nj8emwbyf7y9vcf47zk"
      },
      "version": 2,
      "createdAt": "2026-11-05T09:00:00.000Z",
      "updatedAt": "2026-11-05T09:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

## `bank_statements_lines_ignore`

**Ignore a bank statement line.** Operation [`bank_statements.lines.ignore`](https://ownrecord.io/docs/reference/bank-statements-lines-ignore.md) · Legal entity level · permission `invoices:write` · risk tier `write` · since M5

Takes a line out of the review queue without paying an invoice, with the reason: a bank fee, a processor
payout, a refund, or a partial payment settled with the customer another way. The line stays in the
statement as `ignored`; nothing is posted.

Annotations: `readOnlyHint: false` · `destructiveHint: false` · `idempotentHint: false` · `openWorldHint: false`

### Arguments

| Argument          | Type         | Required | Description                                                                                                                                                                                              |
| ----------------- | ------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`              | ID (`bsl_…`) | yes      | –                                                                                                                                                                                                        |
| `reason`          | string       | yes      | Why the line pays no invoice (a fee, a payout, a refund, a partial payment settled otherwise). (1–500 characters)                                                                                        |
| `expectedVersion` | integer      | no       | (1–9007199254740991)                                                                                                                                                                                     |
| `entity_id`       | ID (`ent_…`) | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity.                                                        |
| `idempotency_key` | string       | no       | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's `idempotency_key`. (1–255 characters) |
| `dry_run`         | boolean      | no       | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default `false`)                                                                                 |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Idempotency:** the result returns the `idempotency_key` used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
- **Dry run:** supported. `dry_run: true` checks permissions and rules and computes the result, then rolls everything back.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A field is malformed or out of range.
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): No bank statement import or line with this ID is visible to the request.
- [`bank_statement_line_resolved`](https://ownrecord.io/docs/reference/errors.md#bank_statement_line_resolved): The line was matched or ignored already.
- [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict): The line changed since you read it (`expectedVersion`); retry.
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): The credentials can't record invoice payments for this entity (`invoices:write`, finance).

### Example

**A bank fee**

Arguments:

```json
{
  "id": "bsl_01m4tx5nj8emwbyf7y9vcf48bc",
  "reason": "Bank fee",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "id": "bsl_01m4tx5nj8emwbyf7y9vcf48bc",
  "object": "bank_statement_line",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47zm",
  "livemode": false,
  "importId": "bsi_01m4tx5nj8emwbyf7y9vcf48ba",
  "row": 3,
  "bookingDate": "2026-11-04",
  "amount": {
    "amount": "450000000",
    "currency": "EUR"
  },
  "reference": "Invoice 2026-000132",
  "counterparty": "Berg Software AG",
  "matchStatus": "ignored",
  "review": {
    "reason": "amount_only",
    "candidateInvoiceIds": ["inv_01m4tx5nj8emwbyf7y9vcf48bd"],
    "candidates": [
      {
        "invoiceId": "inv_01m4tx5nj8emwbyf7y9vcf48bd",
        "number": "GEN-2026-000132",
        "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47z0"
      }
    ]
  },
  "invoiceId": null,
  "brandId": null,
  "ledgerTransactionId": null,
  "payoutItemId": null,
  "matchedBy": null,
  "matchedAt": null,
  "ignoredReason": "Bank fee",
  "version": 2,
  "createdAt": "2026-11-05T09:00:00.000Z",
  "updatedAt": "2026-11-05T10:00:00.000Z"
}
```

## `bank_statements_lines_list`

**List bank statement lines.** Operation [`bank_statements.lines.list`](https://ownrecord.io/docs/reference/bank-statements-lines-list.md) · Legal entity level · permission `invoices:read` · risk tier `read` · since M5

Lists the legal entity's bank statement lines in the mode of the request, newest first. Filter by
`importId`, by `matchStatus` (one or several: the review queue is `partial` and `unmatched`) and by
`invoiceId` (the lines that paid or point to an invoice).

A line in review says why in `review.reason`: `amount_mismatch` or `currency_mismatch` (its reference names
an invoice, the amount differs), `ambiguous_reference` (it names several), `already_matched` (another line of
the import paid that invoice), `amount_only` (no reference, but open invoices with exactly this amount due),
`no_match` or `not_incoming` (money going out). `review.candidateInvoiceIds` are the invoices it may pay.
Resolve a line with `bank_statements.lines.match` or `.ignore`.

Paginate with `limit` (1–100, default 10) and `starting_after` (the `next_cursor` of the previous page).

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument         | Type                                                                                                                | Required | Description                                                                                                                                       |
| ---------------- | ------------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `importId`       | ID (`bsi_…`)                                                                                                        | no       | Only this import's lines.                                                                                                                         |
| `matchStatus`    | one of `unmatched`, `matched`, `partial`, `ignored` or array of one of `unmatched`, `matched`, `partial`, `ignored` | no       | One status or several; the review queue is `partial` and `unmatched`.                                                                             |
| `invoiceId`      | ID (`inv_…`)                                                                                                        | no       | Only the lines that paid or point to this invoice.                                                                                                |
| `limit`          | integer                                                                                                             | no       | (1–100)                                                                                                                                           |
| `starting_after` | ID (`bsl_…`)                                                                                                        | no       | –                                                                                                                                                 |
| `entity_id`      | ID (`ent_…`)                                                                                                        | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity. |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A field is malformed or out of range.
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): No bank statement import or line with this ID is visible to the request.
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): The credentials can't read this entity's invoices (`invoices:read`).

### Example

**The review queue**

Arguments:

```json
{
  "matchStatus": ["partial", "unmatched"],
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy"
}
```

Result `output`:

```json
{
  "object": "list",
  "data": [
    {
      "id": "bsl_01m4tx5nj8emwbyf7y9vcf48bc",
      "object": "bank_statement_line",
      "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47zm",
      "livemode": false,
      "importId": "bsi_01m4tx5nj8emwbyf7y9vcf48ba",
      "row": 3,
      "bookingDate": "2026-11-04",
      "amount": {
        "amount": "450000000",
        "currency": "EUR"
      },
      "reference": "Invoice 2026-000132",
      "counterparty": "Berg Software AG",
      "matchStatus": "unmatched",
      "review": {
        "reason": "amount_only",
        "candidateInvoiceIds": ["inv_01m4tx5nj8emwbyf7y9vcf48bd"],
        "candidates": [
          {
            "invoiceId": "inv_01m4tx5nj8emwbyf7y9vcf48bd",
            "number": "GEN-2026-000132",
            "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47z0"
          }
        ]
      },
      "invoiceId": null,
      "brandId": null,
      "ledgerTransactionId": null,
      "payoutItemId": null,
      "matchedBy": null,
      "matchedAt": null,
      "ignoredReason": null,
      "version": 1,
      "createdAt": "2026-11-05T09:00:00.000Z",
      "updatedAt": "2026-11-05T09:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

## `bank_statements_lines_match`

**Match a bank statement line to an invoice.** Operation [`bank_statements.lines.match`](https://ownrecord.io/docs/reference/bank-statements-lines-match.md) · Legal entity level · permission `invoices:write` · risk tier `financial` · since M5

Pays an open (or uncollectible) invoice of the entity with a line from the review queue: the transfer's
booking date becomes the payment date and its reference the payment reference, as `invoices.mark_paid`
records them (`Dr bank / Cr receivable`, `invoice.paid`; a past-due or unpaid subscription recovers). The
line's amount must be the invoice's amount due in the same currency: invoices are paid in full only.

Financial tier: an approval policy may require a second person. Dry-run it first.

Annotations: `readOnlyHint: false` · `destructiveHint: false` · `idempotentHint: false` · `openWorldHint: false`

### Arguments

| Argument          | Type         | Required | Description                                                                                                                                                                                              |
| ----------------- | ------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`              | ID (`bsl_…`) | yes      | –                                                                                                                                                                                                        |
| `invoiceId`       | ID (`inv_…`) | yes      | The invoice the line pays: its amount due must equal the line's amount.                                                                                                                                  |
| `expectedVersion` | integer      | no       | (1–9007199254740991)                                                                                                                                                                                     |
| `entity_id`       | ID (`ent_…`) | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity.                                                        |
| `idempotency_key` | string       | no       | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's `idempotency_key`. (1–255 characters) |
| `dry_run`         | boolean      | no       | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default `false`)                                                                                 |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Idempotency:** the result returns the `idempotency_key` used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
- **Dry run:** supported. `dry_run: true` checks permissions and rules and computes the result, then rolls everything back.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A field is malformed or out of range.
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): No line, or no issued invoice of this entity, has this ID.
- [`bank_statement_line_resolved`](https://ownrecord.io/docs/reference/errors.md#bank_statement_line_resolved): The line was matched or ignored already.
- [`bank_statement_amount_mismatch`](https://ownrecord.io/docs/reference/errors.md#bank_statement_amount_mismatch): The line's amount isn't the invoice's amount due (full payments only).
- [`invoice_status_invalid`](https://ownrecord.io/docs/reference/errors.md#invoice_status_invalid): The invoice can't be paid: it is paid, voided or a checkout receipt.
- [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict): The line (`expectedVersion`) or the invoice changed meanwhile; retry.
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): The credentials can't record invoice payments for this entity (`invoices:write`, finance).

### Example

**The transfer pays the invoice its amount points to**

Arguments:

```json
{
  "id": "bsl_01m4tx5nj8emwbyf7y9vcf48bc",
  "invoiceId": "inv_01m4tx5nj8emwbyf7y9vcf48bd",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "object": "bank_statement_match",
  "line": {
    "id": "bsl_01m4tx5nj8emwbyf7y9vcf48bc",
    "object": "bank_statement_line",
    "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47zm",
    "livemode": false,
    "importId": "bsi_01m4tx5nj8emwbyf7y9vcf48ba",
    "row": 3,
    "bookingDate": "2026-11-04",
    "amount": {
      "amount": "450000000",
      "currency": "EUR"
    },
    "reference": "Invoice 2026-000132",
    "counterparty": "Berg Software AG",
    "matchStatus": "matched",
    "review": {
      "reason": "amount_only",
      "candidateInvoiceIds": ["inv_01m4tx5nj8emwbyf7y9vcf48bd"],
      "candidates": [
        {
          "invoiceId": "inv_01m4tx5nj8emwbyf7y9vcf48bd",
          "number": "GEN-2026-000132",
          "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47z0"
        }
      ]
    },
    "invoiceId": "inv_01m4tx5nj8emwbyf7y9vcf48bd",
    "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47z0",
    "ledgerTransactionId": "txn_01m4tx5nj8emwbyf7y9vcf48be",
    "payoutItemId": null,
    "matchedBy": "manual",
    "matchedAt": "2026-11-05T10:00:00.000Z",
    "ignoredReason": null,
    "version": 2,
    "createdAt": "2026-11-05T09:00:00.000Z",
    "updatedAt": "2026-11-05T10:00:00.000Z"
  },
  "invoice": {
    "id": "inv_01m4tx5nj8emwbyf7y9vcf48bd",
    "number": "GEN-2026-000132",
    "status": "paid",
    "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47z0"
  }
}
```
