---
title: "Match a bank statement against unpaid invoices"
method: POST
path: "/invoices/scan-statement"
tags: ["Invoices"]
---

# Match a bank statement against unpaid invoices

`POST /invoices/scan-statement`

Parses one or more uploaded bank-statement files (CSV or Excel) into transactions, keeps incoming credits, and matches them against the user's unpaid (non-quote) invoices. Matching is reference-first: an invoice reference (`hash`, e.g. `NA001`) or an exact-total amount with a strong client-name match is auto-applied (invoice marked paid + a payment recorded); a credit below the total that strongly identifies an invoice records a partial payment without marking it paid. Lower-confidence amount-only matches are returned as `suggestions` and never applied. Re-importing the same statement is idempotent (payments are de-duplicated by amount + date). When a non-CHF invoice is marked paid, its CHF exchange rate is stored.

## Response `200`

Statement processed; returns a summary plus the applied matches, suggestions and unmatched transactions.

## Other responses

- `400` — Missing file field
- `401` — Unauthorized
- `422` — No bank transactions could be parsed from the uploaded file(s)
- `500` — Internal Server Error

---

[API](https://skmtc.dev/vocal/apis/magic-heidi-invoicing-software-api.md) · [All operations](https://skmtc.dev/vocal/apis/magic-heidi-invoicing-software-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/vocal/magic-heidi-invoicing-software-api/revisions/591ae048f0a0/schema)
