The Xero Accounting API is how anything outside the platform – a CRM, an EPOS, a custom dashboard, a scheduled script – reads and writes the data inside a Xero organisation. It’s a REST interface with OAuth 2.0 auth, JSON payloads, sane endpoints and good docs. Use the API to create new records, query existing ones, or pull data created or modified since a given UTC timestamp into your own systems. If you build software that touches ledger data in the UK, you’ll meet Xero’s developer programme sooner or later. Most teams ship as a Xero app on the marketplace, or as a private custom integration. The Xero developer platform also has a getting started guide that walks new builders through the basics.
What the APIs offer
The headline product is the Accounting API: invoices, contacts, bills, bank transactions, items, accounts, journals, reports, the lot. Around it sit several other APIs – Payroll, Files, Assets, Bank Feeds, Projects and the Practice Manager interface for firm tooling. Most third-party integrations are built primarily on the main one, with a Files or Bank Feeds call where it’s needed. Each tier of the developer programme – public, private, partner – gets the same API surface, but with different rate-limit ceilings.
Key facts to anchor any integration design:
- OAuth 2.0 with PKCE for confidential and public apps. Refresh tokens last 60 days from issue and expire if unused for 60 days.
- REST, JSON over HTTPS, multi-tenant by design. Every call is scoped to a tenant (one Xero organisation) you’ve been given access to.
- Rate limits per tenant: 60 requests per minute, 5,000 per day, plus a 10,000 concurrency cap. Hit them and you get a
429with aRetry-Afterheader. - Idempotency keys are supported on POST and PUT – send a UUID in the
Idempotency-Keyheader so a network retry doesn’t create duplicate invoices. - Webhooks for invoices, contacts and bills, signed with HMAC. You’ll still want a polling fallback for events that aren’t webhooked.
What people actually build with it
Useful integrations almost always fall into one of these buckets:
- CRM and quote-to-cash – HubSpot, Pipedrive or a custom CRM that pushes invoices in when a deal closes, then pulls payment status back so sales can see what’s been paid.
- EPOS and ecommerce – Shopify, WooCommerce, Lightspeed, Square: daily sales summaries written in as a single journal or invoice per day, with payment processor fees split out.
- Inventory and stock – DEAR, Unleashed, Cin7 syncing items, stock movements and bills so the trial balance reflects real stock value.
- Custom reporting – dashboards in Power BI, Looker Studio or Metabase that pull P&L, balance sheet and aged reports straight from the Reports endpoints.
- Workflow automation – Make, n8n or Zapier flows that approve bills, file expense receipts, or chase debtors from a Slack message.
- Industry-specific apps – construction job costing, hospitality tronc, agency time-tracking – anywhere domain logic sits outside the ledger but the books still need to balance.
OAuth 2.0 authentication flow
The flow is standard OAuth 2.0 authorization code with PKCE for public apps:
- Register an app in the Xero developer portal. Pick public, web app or custom connection depending on who connects.
- Redirect the user to
https://login.xero.com/identity/connect/authorizewith yourclient_id, the requested scopes (e.g.accounting.transactions accounting.contacts offline_access) and a state parameter. - The user authorises and picks which organisation to connect. They’re redirected back to your callback URL with an authorisation code.
- Exchange the code at
/identity/connect/tokenfor an access token (30-minute lifetime) and a refresh token (60-day lifetime). - Call
GET /connectionsto retrieve thetenantIdfor each organisation the user authorised. You’ll need to passXero-Tenant-Idon every subsequent call.
Refresh tokens rotate – every refresh gives you a new refresh token and the old one is invalidated. Store the new one immediately, or you’ll lose access on the next refresh.
Key endpoints worth knowing
The surface is wide, but eight or nine endpoints cover most integration work:
- Invoices – create new invoices, update, void, email and attach. The same endpoint handles individual invoices and bulk reads. Supports both ACCREC (sales) and ACCPAY (bills), including draft, submitted and authorised transaction states. You can pass
?where=Status=="DRAFT"as a querystring to filter results, or use the invoices endpoint to retrieve only those modified since this timestamp via theIf-Modified-Sincehttp header. Pass?summaryOnly=trueto retrieve a smaller version of each record, excluding line-item detail, when you only need headline data. Use the PUT method for inserts where you control the ID, and POST when the platform should generate it. Multicurrency is supported on Premium plans, where each line carries its own currency and the platform handles CurrencyRate validation against the day’s rate. - Credit Notes – the credit notes endpoint mirrors the invoices model and is essential when you’re handling refunds or partial reversals. Invoices and credit notes share the same identifier scheme, so look-ups are consistent across both.
- Contacts – your customer and supplier master. Note that contacts can be merged, so always look up by ContactID, not name.
- BankTransactions and BankTransfers – for spend money, receive money and inter-account transfers that aren’t tied to an invoice or bill. Each one has a type, status and line items, much like an invoice.
- Items – product / service catalogue, including tracked inventory items if the organisation has Tracked Inventory turned on. Each item carries a Code, Name and a Boolean flag for IsTrackedAsInventory.
- Reports – P&L, Balance Sheet, Trial Balance, Bank Summary, Budget Summary. Returns row-by-row JSON, not a flat data set, so plan your parsing.
- Journals – a read-only feed of every ledger journal posted, ideal for incremental data warehouse loads.
- Attachments – PDFs and images on invoices, bills and bank transactions; upload via multipart, retrieve by ID.
- TrackingCategories – departments, locations or projects used for segmental reporting.
Where AI agents fit in
A growing slice of integrations are no longer “CRM A talks to ledger B” pipes – they’re AI agents that read transaction data, classify and code it, surface anomalies, or draft month-end commentary. The data model is well suited to this: every transaction has a stable ID, the schema is clean, and idempotency keys mean an AI agent can retry safely without doubling up entries. If you’re building an AI agent that needs to read or write into a UK Xero org, the same OAuth, rate-limit and webhook rules apply – and the same advice about testing in the demo company before touching live data.
Webhooks and idempotency
Webhooks fire on create and update for Invoices, Contacts and Bills. You register a webhook URL in the developer portal, the platform signs every payload with HMAC-SHA256, and you verify the signature before trusting the body. The payload is intentionally lean – just the resource identifier and event type – so you make a follow-up http GET to fetch the latest state. That avoids stale data from out-of-order delivery. The SentToContact Boolean on the resulting record tells you whether the customer has already been emailed, useful for contact-state machines.
For writes, always set Idempotency-Key to a UUID per logical operation. If the network drops between the request being processed and you receiving the response, retrying with the same key returns the original result instead of creating a duplicate. It’s the difference between a clean integration and a Friday afternoon spent reversing 200 duplicate invoices.
Rate limits, pagination and large datasets
The 60/min and 5,000/day limits on api calls are per tenant, not per app. A retail client doing a daily ten-year backfill can blow through a daily allocation of api calls in the first hour – so design for efficient data retrieval from day one. Tips to optimise:
- Use
If-Modified-Sinceon every read, then walk paginated responses with thepageparameter (100 records per page on most endpoints). Useorderfor primary ordering and a comma-separated list for secondary ordering across pages. - For Invoices and BankTransactions, the
whereclause lets you filter byUpdatedDateUTC, which is essential for incremental syncs. - Use a single api call with
summaryOnly=trueon list endpoints when you don’t need full line-item detail. This dramatically reduces payload size by excluding computation-heavy fields. - Respect the
Retry-Afterhttp header on 429s. Exponential backoff plus jitter beats fixed-interval retry every time. A persistent 400 response usually means a malformed querystring or invalid IDs. - Never hammer Reports endpoints in a tight loop – they’re more expensive on the server side and will rate-limit faster.
- Field max length matters: most string fields cap at 255 chars, descriptions at 4,000.
- Attachments are capped at 25mb in size each. If you need bigger files, upload an external URL reference in the line description instead.
Sandbox and the demo company
Every Xero developer gets a free demo company to test against, refreshable from the portal. Combined with a free trial of a real org, that’s enough to build and test end-to-end before you ever connect to a paying client’s data. Always run integration tests against the demo, not a real organisation – it’s the cheapest insurance you can get.
Multi-tenancy gotchas
The same access token can have access to many organisations (tenants). Three things to remember:
- Always pass
Xero-Tenant-Idon every call. Forget it and the platform guesses, which is exactly what you don’t want. - The
/connectionsendpoint is your source of truth for which tenants a token can see – call it after every refresh, because users can disconnect or re-connect tenants without telling you. - Store tokens against the user, not the tenant. One user can authorise five organisations on the same token.
- Each organisation’s data is isolated – never assume cross-tenant queries will work, they won’t.
Official Xero API SDKs
An official SDK is maintained for Node.js, .NET, Java, PHP, Python and Ruby. They handle OAuth, token refresh, request signing and the bulk of the data models for you – effectively a thin wrapper that hides the rougher edges of the raw HTTP layer. For anything serious in production, use one of these libraries rather than rolling your own HTTP client – the auth flow alone has enough sharp edges to justify it. Records created in Xero through these libraries look identical to those created in the UI; downstream consumers can’t tell the difference.
Build vs marketplace app: which way to go?
Before you write a line of code, check the App Store. If a connector already exists for what you need (Stripe, Shopify, Dext, GoCardless, Hubdoc, Float), it’s almost always cheaper, faster and more reliable than building your own. Build with code when:
- The data model is industry-specific and no off-the-shelf app fits.
- You need fine-grained control over how transactions are coded.
- You’re embedding ledger data inside another product (a vertical SaaS, an internal portal).
- Volume or rules push you past the limits of a no-code / low-code automation tool.
For everything else, a marketplace app plus a Make or Zapier flow will get you 80% of the way for a tenth of the build cost.
Does Xero accounting have an API?
Yes – the main developer endpoints plus Payroll, Files, Assets, Projects, Bank Feeds and Practice Manager. Documentation lives at developer.xero.com, and a free demo company is available to every registered developer.
Archiving, voiding and tidying up
Use the Status=ARCHIVED update on Contacts to archive without deleting – history stays intact for audit. For Invoices, void is the canonical “soft delete” once approved. Boolean flags like IsArchived and EmailSent show up across multiple endpoints and are worth handling consistently across your data model.
Need help making the integration behave?
If you’re a developer scoping an integration, or a finance team or accountant trying to work out whether to build, buy or stitch together with no-code, we can help you pick the right route. We’ve worked with developers on dozens of integration projects from quick syncs to full custom apps. Drop us a line or have a look at our integration services page for context.