Connecting Xero

Connecting Xero turns an approved invoice into a bill in your Xero organization, coded to the supplier, account and property you chose. This page is for the admin who holds the Xero credentials: connector settings, mapping and disconnection are all admin-only, and the API refuses them regardless of what the screen offers.

Xero and QuickBooks Online are separate connectors and you can have both. When both are connected and both are switched on, an approved invoice posts to each of them — one bill in each — under a single export run. See the exports reference for what happens when one ledger accepts a bill and the other refuses it.

Two things to be clear about before you start. inletAP is not a Xero certified app and is not listed on the Xero App Store, so you will not find it by searching there; you connect it from inside inletAP. And this is not a sync. Bills go one way, from inletAP into Xero.

Connecting

Start the connection from Settings → Connectors. The same connection cards also sit on Exports → Ledger setup, and either one works — after you authorize, Xero sends you back to the Connectors tab. You sign in at Xero and choose what to authorize there. Xero's consent is granted per person rather than per organization, so one sign-in can return more than one set of books. inletAP never sees your Xero password.

inletAP asks for exactly five scopes and no more:

ScopeWhy
offline_accessTo keep posting without sending you back to Xero every thirty minutes.
accounting.invoicesTo create the bill.
accounting.contactsTo find the supplier's contact record.
accounting.settingsTo read the chart of accounts, the tax rates and the tracking categories.
accounting.attachmentsTo attach the source PDF to the bill.

What happens next depends on what that sign-in returned.

  • One organization, and it is your first Xero connection. It is switched on for you. A workspace whose only Xero connection posted nothing would read as broken rather than as careful.
  • Several organizations, or a Xero connection you already had. Each new one arrives switched off and you land on "Which Xero organizations should receive bills?" — tick the ones approved invoices should post into. Turning none on is a valid answer, and the screen says so.

You can change that answer whenever you like, with the Post approved bills here switch on each connection card. Authorizing is not the same act as agreeing to write into somebody's books.

With two or more Xero organizations switched on, mark one of them Unrouted bills go here. An invoice that names no ownership entity has to land in one set of books, and with no default marked inletAP does not guess: it parks the invoice with no_default_ledger rather than record the same expense twice. Routing an ownership entity to a particular organization is on Settings → Split coding — see posting to several companies.

Your Xero plan decides how bills may be posted

Xero's own Early plan caps how many bills an organization can approve in a month — five — and answers the sixth with an error rather than a warning. That is Xero's limit, not ours, and it is exactly the plan a small landlord is on.

inletAP reads the organization's plan when it connects and says so on the connection card before your first export rather than after the sixth bill fails. The way around it is to post bills as drafts instead of approving them: a draft does not count against the approval cap, and somebody in Xero approves them there. Post status is a setting on each connection.

Mapping what a bill refers to

A bill cannot post without a contact and an account, so an unmatched supplier is a blocked invoice rather than an untidy list.

Mapping lives on Exports → Ledger setup, one panel per connected organization. Choose Sync from Xero there to pull the organization's contacts, accounts, tax rates and tracking categories. Some rows match automatically by name; ties are left for a person. The panel counts the unmatched rows at the top and links straight to them, and only an admin can change a mapping.

What is mappedTo what in XeroWhy
VendorA Xero contactThe bill posts against it. Only the contact's ID is ever sent, so posting a bill can never rename your supplier or change its details.
GL codeAn account codeBecomes AccountCode on the bill line. Xero keys accounts by code, not by an internal ID, so that is what is sent.
Tax codeA Xero tax rateBecomes TaxType on the line, and it is what carries the tax money.
PropertyA tracking optionBecomes the tracking on the line, so the cost lands on the building.

One default sits above the list:

  • Default expense account — what a bill line uses when the invoice carries no GL code. Without it, an uncoded invoice cannot post at all, so it counts as a blocking gap.

There is no accounts-payable mapping and no sales-tax-expense mapping here, and their absence is not an oversight. A Xero bill does not name an A/P account — Xero derives it from the ACCPAY type — and Xero has a real purchase-tax engine in every region, including the United States, so tax is carried by a rate on the line rather than written as an extra expense line. Both of those rows exist for QuickBooks and neither has a Xero question behind it.

Tracking, and what does not port from QuickBooks

Xero puts tracking on each line, so one Xero bill can carry a different property on every line. There is no header-level dimension to get trapped by, which is the QuickBooks Locations problem and it does not exist here.

The ceiling is Xero's: an organization defines at most two tracking categories in total, so your properties have to be one of the two you already use.

Two QuickBooks concepts have no Xero equivalent and are not emulated:

  • Coding a line to a unit as a sub-customer. QuickBooks-only. Xero has nothing that means the same thing and we are not going to invent one.
  • A header department or location. QuickBooks-only, for the same reason.

What a posted bill looks like

The bill is created as an ACCPAY invoice against the mapped contact, with one line per invoice line item — or a single line when the invoice has none. A multi-line invoice maps line by line, not as a single lump.

On the billWhere it comes from
ContactThe mapped Xero contact, by ID only
Date and due dateThe invoice date and due date read off the document
ReferenceThe supplier's own invoice number
Line account codeThe GL code mapped to an account code, or your default expense account
Line taxThe stated tax, carried by the mapped tax rate and split across the lines so the parts add up to the invoice's tax exactly
Line trackingThe property, as a tracking option, where you use tracking
StatusApproved, or draft, depending on the connection's post status
CurrencyThe invoice currency, when the organization can hold one
The invoice itselfThe source PDF, uploaded to Xero and attached to the bill, where the invoice arrived with one

Attaching the PDF is best-effort and deliberately cannot cost you the bill. A document that arrived without a PDF posts without an attachment. A file over Xero's 10 MB request ceiling is refused before the upload rather than failing the whole push, and an upload that fails for any other reason is logged and left — the bill is already in your ledger by then, and nothing about it is undone.

The arithmetic is checked before anything is sent. Line items are pre-tax and the invoice amount is the grand total, so the lines must add up to the total less tax, within a penny; and the bill Xero would settle at must equal the invoice total. If either fails, the item is held back with both figures named rather than posting a bill that settles at the wrong number.

Stated tax with no Xero tax rate mapped also waits, and it waits in every country. A Xero line expresses tax through its tax rate and nothing else, so the alternatives would be to drop the tax and underpay the supplier, or to let Xero apply the account's own default rate — a number nobody asserted. Both are worse than waiting for a person.

The identifier that comes back

When a bill is created, inletAP records the Xero invoice ID against the document, along with the idempotency key used to post it.

That key is minted before the first attempt and reused on every retry of the same post, so a dropped connection replays rather than creating a second bill. If Xero declines to say what happened to the first request, inletAP looks the bill up in Xero before trying again, and adopts the one that is already there rather than creating a second.

inletAP never issues a partial update to a Xero bill. A partial update in Xero deletes the lines you left out, so any update sends the complete invoice or it is not sent.

The nightly check

On the Starter plan and above, inletAP reads back the bills it posted to every connected ledger once a night — Xero and QuickBooks Online alike — and records what each one actually holds. A bill changed or removed in Xero afterwards becomes a difference you can see rather than a silent disagreement. The check reads; it never writes.

The free plan does not include it. A free workspace posts bills to Xero exactly as described above and reads nothing back.

When a bill will not post

The batch records the reason in the words Xero used, and offers a retry. A refusal never leaves half a bill: the bill exists in Xero in full, or it does not exist.

What you seeWhat to do
No contact mapped for the supplierMap the vendor to a Xero contact and retry.
The account code could not be resolvedMap the GL code, or set a default expense account.
Stated tax with no tax rate mappedMap the tax code to a Xero tax rate.
The lines do not add up to the invoiceOpen the invoice; extraction read a line wrongly, or a split was re-cut after the batch was planned.
The organization cannot hold a foreign-currency billPost it in the organization's own currency, or export that one as CSV.

Where to go next