Qonto + n8n: automate bank reconciliation without losing control

·10 min read
Updated on September 3, 2026

Exporting Qonto transactions to a spreadsheet is not bank reconciliation. You still need to fetch every transaction, prevent duplicates, match payments to expected invoices or entries, and send ambiguous cases to someone who can decide.

n8n can orchestrate this flow with the HTTP Request node. The difficult parts are the authentication method, change tracking and the boundary between an automated suggestion and an accounting decision. The setup below follows Qonto's published mechanisms as of August 13, 2026 and does not assume that n8n provides a native Qonto node.

What the workflow must do

A useful reconciliation flow has six stages:

  1. fetch new or modified Qonto transactions;
  2. normalise amounts, dates, counterparties and references;
  3. store each transaction under a stable key;
  4. find a matching invoice, payment or deterministic rule;
  5. propose a category when the evidence supports one;
  6. require review for ambiguous cases before writing to the accounting system.

A bank transaction does not always contain enough information to determine a ledger account, VAT treatment or the exact nature of an expense. The workflow prepares reconciliation. It does not replace the supporting document or the rules agreed with the accountant.

Authenticate to Qonto correctly

The Qonto Business API supports two authentication methods. The correct one depends on the integration.

API key for your own Qonto account

For an internal automation connected to your own Qonto organisation, the documentation accepts this header:

Authorization: sign-in:secret-key

Send sign-in:secret-key as the literal value. Do not add a Basic prefix and do not Base64-encode it.

Create a generic Header Auth credential in n8n:

Field Value
Name Authorization
Value your-sign-in:your-secret-key

Keep the secret in n8n's credential store. Do not place it in a Code node, a visible expression or an exported workflow.

OAuth 2.0 for integrations serving multiple customers

An application that connects Qonto accounts for several businesses should use OAuth 2.0. API calls then carry an access token:

Authorization: Bearer access-token

Some endpoints are available only through OAuth. Qonto publishes an endpoint matrix by authentication method. Create an application in the Developer Portal and implement the documented authorisation flow. An internal API key should not be repurposed as a multi-customer integration.

The X-Qonto-Staging-Token header serves a different purpose. Qonto documents it for Sandbox requests. It does not replace the production Authorization header.

Configure the n8n HTTP Request node

The canonical path uses n8n's built-in HTTP Request node, with no community package.

Field Value
Method GET
URL https://thirdparty.qonto.com/v2/transactions
Authentication the Header Auth or OAuth 2.0 credential chosen above
Response format JSON

The request must identify the account with bank_account_id or iban. Add the relevant query parameters:

Parameter Example Purpose
bank_account_id 018f... Account to query
status[] completed Process booked transactions
updated_at_from 2026-08-12T00:00:00.000Z Fetch transactions modified since the checkpoint
per_page 100 Documented maximum items per page
page 1 Requested page
includes[] attachments Include linked documents when needed

The response includes a meta object with current_page, next_page, total_pages and per_page. In n8n, continue while meta.next_page is not null. Do not infer the number of pages from the business's usual transaction volume.

Qonto states that omitting the status filter returns completed transactions by default. I keep status[]=completed explicit so the rule remains visible in the workflow.

Read the response without inventing data

This is a synthetic example. It follows the fields in Qonto's API reference but does not represent a customer transaction:

{
  "transaction_id": "super-transaction-7468",
  "amount": 19.99,
  "amount_cents": 1999,
  "side": "debit",
  "currency": "EUR",
  "label": "FREE MOBILE",
  "settled_at": "2026-08-12T08:32:00.000Z",
  "updated_at": "2026-08-12T08:32:05.000Z",
  "status": "completed",
  "reference": null,
  "attachment_required": true
}

The fields have separate roles:

  • transaction_id identifies the transaction;
  • amount_cents avoids floating-point comparisons;
  • side shows whether money entered or left the account;
  • status distinguishes values including pending, declined, completed and reversed;
  • updated_at makes it possible to pick up a changed transaction;
  • reference, label and attachments support matching but may not be sufficient.

Do not assume that a known counterparty always implies the same category. One supplier may sell several services, and a bank label does not establish the VAT treatment.

Prevent missing records and duplicates

Keeping only a list of IDs in workflow static data is fragile for a business-critical flow. Use durable storage with a unique constraint on transaction_id, then perform an upsert.

A minimal record can contain:

transaction_id
updated_at
status
amount_cents
side
label
reference
matched_document_id
proposed_category
review_status

The transformation remains simple:

const transaction = $json;

return [{
  json: {
    transactionId: transaction.transaction_id,
    updatedAt: transaction.updated_at,
    status: transaction.status,
    amountCents: transaction.amount_cents,
    side: transaction.side,
    label: transaction.label ?? null,
    reference: transaction.reference ?? null,
  },
}];

The next node upserts into PostgreSQL, Airtable or another store that enforces uniqueness. A later updated_at value updates the existing row instead of creating a duplicate.

To reduce the chance of missing a transaction at the boundary between runs, query a short overlap window and let the upsert deduplicate. Save the new checkpoint only after the complete run succeeds.

Match before asking an AI model

Start with deterministic rules:

  • exact invoice reference;
  • matching amount and currency;
  • consistent payment direction;
  • date inside a defined window;
  • previously approved IBAN or counterparty;
  • recurring rule approved by the accounting team.

AI can help when labels are irregular or several categories remain plausible. It should return a structured proposal and be able to request review.

Classify this transaction into one approved category.
Do not infer information that is absent from the label or reference.
Use review_required when the evidence is insufficient.

Approved categories:
- telecom
- software
- travel
- bank_fees
- taxes
- client_revenue
- internal_transfers
- review_required

Return JSON only:
{"category":"review_required","reason":"insufficient label"}

A model's self-reported "confidence score" is not a calibrated probability. Do not send entries straight to accounting on the basis of an arbitrary threshold. First measure errors against a reviewed transaction set, category by category, then define automation rules with the person responsible for the accounts.

Put human approval in the workflow

A practical flow can have three outputs:

  1. deterministic match: the reference and amount match an expected document;
  2. proposal for review: one category is plausible, but a person confirms it;
  3. exception: missing document, amount mismatch, reversed transaction or insufficient label.

Log the rule or model used, input fields, proposal and human decision. Avoid copying complete banking data into AI services that your internal policy has not approved.

The guide to human approval in production AI agents develops the same control pattern.

Test before activating the workflow

Prepare a representative test set without using customer data unless you have authorisation:

  • completed, pending and reversed transactions;
  • two or more response pages;
  • the same transaction_id with a newer updated_at;
  • identical amounts for two different invoices;
  • missing reference;
  • missing supporting document;
  • Qonto 401, 429 and 5xx responses;
  • a failed write to the destination store.

Confirm that an interrupted run can resume without a duplicate and that no automatic decision occurs when source data is incomplete. Alert on failures, late runs and a growing exception queue.

Official sources

What I would put in production

I would keep Qonto as the banking source, durable storage for idempotency, deterministic rules first and a review queue for everything else. AI would propose a category without deciding an accounting entry or tax treatment on its own.

This setup requires more discipline than a CSV export, but it stays readable and reversible. If the process also includes supplier invoices, the workflow for automating Pennylane invoicing with n8n complements this design. Kirako can also build an n8n automation around your accounting system.

Also available: Read in French