FlowKit

Connecting n8n to Xero: automating invoices, contacts and bank reconciliation

Published 17 August 2026 · 5 min read

Xero is one of the most widely used accounting platforms outside France — UK, Australia, New Zealand, Canada — and its API is public and well documented. n8n ships a native node, but it only covers two resources: contacts and invoices. For everything else, especially the bank transactions needed for real automated reconciliation, you need the HTTP Request node calling the API directly. This guide covers OAuth2 authentication, the tenant ID quirk unique to Xero, what the native node can do, and how to extend automation beyond it with HTTP Request — the same principle covered in our Qonto bank reconciliation guide, on the banking side rather than the accounting side.

Creating the app in the Xero developer portal

Unlike Qonto or other financial APIs that accept a static key, Xero only authenticates via OAuth2 — there is no personal-token alternative. App creation happens at developer.xero.com, under My Apps:

  1. Create a new app of type Web app (not Mobile or Desktop).
  2. Enter your n8n instance URL (or your reverse proxy, see our guide on n8n behind Traefik or Caddy) as the "Company or Application URL".
  3. Grab the generated Client ID, then create a Client Secret (shown only once — copy it immediately).

In n8n, create a Xero OAuth2 API credential and paste the Client ID and Client Secret. n8n then generates a Redirect URI to add back into the Xero app configuration — skip that round trip and authorization fails with an invalid redirect.

Picking the right scopes

When creating the credential, two scopes cover the native node's operations:

  • accounting.contacts — read/write contacts (customers, suppliers).
  • accounting.transactions — read/write invoices and, via HTTP Request, bank transactions.

A missed scope doesn't break the existing credential: authorization stays valid for what it does cover, but any operation outside that scope returns a 403. If you add a use case later (credit notes, detailed invoice line items), you need to reconnect the credential with the extended scopes rather than debug the error elsewhere.

Access tokens expire after 30 minutes, but n8n handles renewal automatically through the refresh token as long as the credential stays connected — no Wait node or renewal logic to add on the workflow side.

The tenant ID: the quirk that trips up most people

Xero is natively multi-tenant: a single OAuth2 token can grant access to several Xero organisations (think of an accounting firm managing several clients, similar to what we describe in our guide on hosting n8n for a multi-client agency). The direct consequence: every call to the Xero API must specify the target organisation through the Xero-tenant-id header, or the request fails even with a perfectly valid token.

For the native node, n8n handles this step automatically behind the scenes. For a manual HTTP Request call, you need to do it yourself:

  1. A GET https://api.xero.com/connections call with the OAuth2 token in the Authorization: Bearer {token} header returns the list of authorized organisations, each with its tenantId.
  2. That tenantId is then injected into the Xero-tenant-id header of every subsequent call.

On a single-tenant instance, that tenantId can be fetched once and stored in an n8n environment variable (see our guide to n8n environment variables) instead of being fetched on every run.

What the native node covers: contacts and invoices

n8n's Xero node exposes two resources, each with Create, Update, Get and Get Many operations:

Resource Operations Typical use case
Contact Create, Update, Get, Get Many Sync your customers/prospects (CRM, order form) into Xero without re-entering data
Invoice Create, Update, Get, Get Many Automatically generate a Xero invoice when an order or subscription closes

A concrete use case: a Stripe webhook or an e-commerce order triggers an n8n workflow that checks (Get Many on Contact) whether the customer already exists in Xero, creates it if not, then generates the matching invoice with the right line items. It's the same idempotent-upsert principle detailed in our Attio + n8n connection guide — check before creating, so a contact is never duplicated on every run.

Going further: bank transactions via HTTP Request

The native node doesn't cover bank transactions (BankTransactions), yet they're essential for real automated reconciliation — comparing bank movements imported into Xero against issued invoices and flagging gaps before the close. You need an HTTP Request node, reusing the existing OAuth2 credential rather than duplicating authentication:

  • URL: https://api.xero.com/api.xro/2.0/BankTransactions
  • Authentication: Generic Credential Type → OAuth2, pointing to the Xero credential already created.
  • Required headers: Xero-tenant-id (fetched as described above) and Accept: application/json.
  • Useful filter: the where parameter lets you restrict by date (Date >= DateTime(2026, 08, 01)) to avoid re-downloading the full history on every run — the same incremental-window principle described in our guide on keeping an index up to date without reprocessing everything.

The reconciliation itself follows the logic detailed in our Compare Datasets node guide: bank transactions from Xero on one side, issued invoices on the other, a reconciliation field (amount and date within a few days), and an "unmatched" output that triggers a Slack alert instead of waiting for the monthly close.

Pacing calls without hitting the limit

Xero enforces 60 calls per minute per organisation, plus a daily cap on top. On a batch job (syncing 200 contacts, importing a month of transactions), a one-to-two-second Wait node between each HTTP Request call avoids a 429 mid-execution — easier to plan for upfront than to fix after the fact, as our guide on handling API rate limits in n8n points out.

Why automating is worth the effort

A review of robotic process automation (RPA) in accounting firms, published by Perdana, Lee and Chu in the International Journal of Accounting Information Systems in 2023 ("Prototyping and implementing Robotic Process Automation in accounting firms", see on Google Scholar), documents measurable reliability gains on repetitive reconciliation and data-entry tasks once automated, in both accounting firms and in-house finance teams. That finding echoes an older, well-documented problem: manual re-entry of financial data remains a source of errors that human vigilance alone struggles to eliminate, as shown by Raymond Panko's research on spreadsheet data-entry errors ("What We Know About Spreadsheet Errors", Journal of Organizational and End User Computing, 1998, see on Google Scholar) — one more reason to route data from order to invoice, or from bank to books, through an API rather than manual re-entry at every step.

Going further

Connecting Xero to n8n removes double entry between your CRM, your order tool and your accounting, and lets you build a bank reconciliation that alerts continuously instead of only at the close. If your stack already needs an audit trail or compliance evidence to document (ISO 27001, SOC 2, GDPR), our Compliance & Audit Pack (€149) builds on the same logging-and-alert-on-gap principles. For an inbox that itself generates quotes and invoices to feed into Xero, the Inbox AI Pack (€79) sorts and prioritizes upstream; the Complete FlowKit Bundle (€269) bundles all three packs for end-to-end automation.

FAQ

Frequently asked questions

Is n8n's native Xero node enough to automate everything?

No. The native node only covers two resources: Contact and Invoice (create, update, get one or several records). For everything else — bank transactions, credit notes, detailed invoice line items, manual journals — you need the HTTP Request node calling the Xero API directly, reusing the same OAuth2 credential.

Why do my Xero API calls fail with a 400 error even though the token is valid?

The most common cause is a missing Xero-tenant-id header. The Xero API is multi-tenant: a single OAuth2 token can grant access to several Xero organisations, so every request (except the call to /connections itself) must explicitly specify the target organisation through this header, fetched once via GET https://api.xero.com/connections.

Do I need to manually renew the Xero token in n8n?

No. Xero OAuth2 tokens expire after 30 minutes, but n8n handles renewal automatically via the refresh token as long as the credential stays connected. The real point of attention is scopes: accounting.contacts and accounting.transactions cover the essentials, but a scope missed when creating the credential means reconnecting the account to add it.

What is the Xero API's rate limit?

Xero enforces a limit of 60 calls per minute per organisation (tenant), with a daily cap on top. On a workflow processing a batch of transactions or invoices, a one-to-two-second Wait node between calls avoids triggering a 429 mid-execution.

Bundle FlowKit Complet

€269