Systems
Xero integration with your online store: sales, payments and tracked stock
Xero allows 60 API calls a minute and 5,000 a day per organisation, and is designed for up to 5,000 sales invoices a month. We build the integration so a busy store stays inside those numbers, then host and run it.
What Xero is and who runs it
Xero is cloud accounting software for small and medium businesses and their accountants. It holds contacts, items, invoices, bills, payments, bank transactions and the general ledger, and on its tracked items it keeps a quantity on hand and a stock value. An item in Xero has one quantity and no stock location.
For a store that makes Xero a ledger with a basic item list. Xero's developer documentation is direct about scale: it is designed for up to 5,000 sales invoices, 5,000 bills and 5,000 bank transactions a month, recommends at most 4,000 tracked inventory items, and warns that contact lists over 10,000 can cause performance problems. An integration for a growing store has to be built with those numbers in mind from the first day.
What connects to Xero
| Flow | Direction | Xero endpoint |
|---|---|---|
| Sales | store to Xero | Invoices (type ACCREC), per order or per day |
| Payments and payouts | store and payment provider to Xero | Payments, BankTransactions |
| Customers | store to Xero | Contacts, store customer ID in ContactNumber |
| Refunds | store to Xero | CreditNotes |
| Items and prices | Xero to store | Items with Code, SalesDetails.UnitPrice |
| Stock | Xero to store | QuantityOnHand on tracked Items |
Per order or per day is the first decision. One invoice per order gives the accountant every sale with its customer, and it reaches Xero's 5,000 a month at about 166 orders a day. One invoice per day and payment method keeps Xero small, and the order detail stays in the integration's log. B2B orders on account always go in as their own invoice to the customer's contact, because they need a due date and a payment against them.
ContactNumber exists for exactly this job: it identifies a contact in an external system and shows as Contact Code in Xero, read-only in the Xero interface. The integration stores the store's customer ID there and matches on it before it creates anyone. Xero has said contact names may stop being unique and recommends ContactID as the reference, so the integration never matches on name. See duplicate customers and orders.
How Xero exposes data
OAuth 2.0 or a Custom Connection
The Accounting API is REST with JSON and OAuth 2.0. With the standard code flow an access token lasts 30 minutes and a refresh token 60 days; an integration that refreshes in time keeps running, one that is down for longer needs a person to authorize again.
A Custom Connection uses the client credentials grant for one Xero organisation. There is no refresh token to lose, and the organisation's own user authorizes it once by email. It is a premium option with its own monthly subscription, paid by the organisation, and only available for organisations in Australia, New Zealand, the UK and the US. From 29 April 2026 new Custom Connections use granular scopes and no longer get accounting.journals.read.
Rate limits per organisation
| Limit | Value |
|---|---|
| Calls in progress at once | 5 |
| Calls per minute | 60 |
| Calls per day | 5,000 (1,000 for apps on the starter tier) |
| Calls per minute for one app, all organisations | 10,000 |
| Request size | 10 MB; Xero advises batches of up to 50 |
| Items per create or update request | 100 recommended |
Every response carries X-DayLimit-Remaining, X-MinLimit-Remaining and X-AppMinLimit-Remaining. Over a limit Xero answers 429 with X-Rate-Limit-Problem and, for the minute and daily limits, Retry-After. The windows are fixed and reset at a different moment per organisation. Xero's limits page has the full list.
The arithmetic for 600 orders a day posted one by one: one contact lookup, one invoice and one payment per order is 1,800 calls a day, inside 5,000. The same 600 written in batches of 50 invoices and 50 payments is 12 invoice calls and 12 payment calls, plus the contact lookups. The difference shows on a sale day: 3,000 orders one by one is 9,000 calls, which the daily limit stops at 5,000; in batches the same day stays under 3,500 calls.
Idempotency and webhooks
POST, PUT and PATCH requests accept an Idempotency-Key header of up to 128 characters. Xero caches the response, and a repeat with the same key returns the cached result instead of creating a second invoice. That makes a retry after a timeout safe.
Webhooks cover contacts, invoices, credit notes, overpayments, prepayments and App Store subscriptions. The receiver must answer within 5 seconds with a 2xx. When it does not, Xero retries with decreasing frequency for 24 hours and then disables the webhook until someone re-enables it. There is no webhook for items, so stock changes are read with If-Modified-Since.
Where a Xero integration gets stuck
Short codes and names. An item Code holds 30 characters and a Name 50. Store SKUs and titles are often longer. The integration keeps a mapping from store SKU to Xero code and writes the full title to Description, which takes 4,000. See variant mapping.
Tracked stock is one number. A tracked item has QuantityOnHand, QuantityOnBackOrder and QuantityAvailable, which is on hand minus back order. There is no location. When the store has several stock locations, the per-location numbers come from the warehouse system and Xero only gets the value of stock. See which stock counts.
Tracked items only work with full accounts. An item becomes tracked when it has an InventoryAssetAccountCode of type INVENTORY and a COGSAccountCode. An item created without them is untracked, and Xero keeps no quantity for it. The integration checks the account codes before it creates an item, so the store never shows stock for an item Xero is not counting.
Tax as amounts or as codes. Each invoice line carries an account code and a tax type, and LineAmountTypes says whether the amounts include tax, exclude it or have none. A store that charges tax-inclusive prices and an integration that sends them as exclusive put the whole tax amount on top. The integration sets LineAmountTypes per store and compares the invoice total in Xero with the order total before it marks the order as done. See money, tax and rounding.
Platforms we integrate with Xero
The store side is described per platform on Shopify, WooCommerce and BigCommerce. The other small-business ledger we integrate is QuickBooks; for a larger finance setup see Sage Intacct. The order flow in general is on order integration.
We build the integration to your Xero organisation: your accounts, tax types, tracked items and the per-order or per-day choice your accountant makes. Then we host, run and monitor it for a monthly fee. Before go-live it runs as a dry run that writes nothing to Xero, so you see every invoice and payment it would post. All integrations come with a dashboard, logs and a per-run diff. Tell us how you use Xero.
Frequently asked questions
What happens when the store sells more than Xero is designed for?
Xero states it is designed for up to 5,000 sales invoices a month. A store with 600 orders a day produces about 18,000. The integration then posts one summary invoice per day and payment method, with the store orders listed in the integration's log and dashboard, and keeps customer-level invoices for B2B orders on account. Your accountant decides the split before go-live.
Do we need a Custom Connection?
It is the cleanest route for an integration built for one company. A Custom Connection uses the client credentials grant for a single Xero organisation, so no refresh token can expire. It is a paid add-on subscription that the organisation buys from Xero, and it is available in Australia, New Zealand, the UK and the US.
What happens when the integration hits a Xero rate limit?
Xero answers HTTP 429 with an X-Rate-Limit-Problem header that names the limit, and a Retry-After header for the minute and daily limits. The integration pauses that organisation for the time given and keeps the work in its queue. Because it writes invoices in batches of up to 50, a normal day uses a small part of the 5,000 calls.
Can Xero tell the store when stock changes?
Not directly. Xero webhooks cover contacts, invoices, credit notes, overpayments, prepayments and App Store subscriptions, not items. The integration reads items changed since its last run with the If-Modified-Since header. See why webhooks are not a guarantee for how we combine webhooks with polling.
Our SKUs are longer than 30 characters. Is that a problem?
Yes, for tracked items. An item Code in Xero holds 30 characters and a Name 50. The integration keeps a mapping table from each store SKU to a Xero code that fits, and writes the full store title to the item Description, which holds 4,000 characters.
Tell us what you need
Tell us which systems you use and what needs to work better. We reply personally within one working day. We help you define the work, then agree the price and timing before you commit.
- You know the price and the timeline before you commit to anything
- We work out the connection that takes the work off your hands
- We handle the build, hosting, monitoring and maintenance
- Your team has less information to retype and fewer discrepancies to chase