Connecting Xero

Xero is a finished connector. An approved invoice becomes a bill in your Xero organization, coded to the contact, the account and the property you chose, and inletAP records the Xero invoice ID against the document — so "where did this end up" has an answer rather than a search.

Two things to be clear about before you spend the time. 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 bills travel one way, from inletAP into your books. Nothing is written back onto your invoices except the identifier of the bill that was created.

Xero and QuickBooks Online are separate connectors and you can hold both. With both connected and both switched on, an approved invoice posts to each of them — one bill in each. The exports reference covers what happens when one ledger accepts a bill and the other refuses it.

Before you start

  • Be an Admin. Connecting, the destination switches, mapping and disconnecting are all admin-only, and the API refuses them whatever the screen offers. A Controller Approver or an AP Specialist sees the control greyed out with the reason on it. Running the export afterwards is an Admin or a Controller Approver.
  • Have a Xero sign-in for the organization the bills belong in. inletAP never sees your Xero password.
  • Know which plan that organization is on. Xero's own Early plan caps how many bills an organization may approve in a month, and answers the next one with an error rather than a warning. That is Xero's limit, not ours. Step 4 is where it is handled.
  • Have your vendors and GL codes in inletAP already. Step 5 matches what you hold against what Xero holds; it does not invent either side. Importing your data loads them from a spreadsheet.

Connecting takes a few minutes. The matching takes as long as your vendor list.

1. Start the connection

Open Settings → Connectors. The Xero card reads "Not connected yet" and says what pressing the button does before you press it. Press Connect Xero.

The same button sits on Exports → Ledger setup while no ledger is connected. Either one works, and you come back to whichever screen you started from.

2. Authorize at Xero

inletAP sends you to Xero. You sign in there and choose what to authorize. Xero grants consent per person rather than per organization, so one sign-in can return more than one set of books.

inletAP asks for five scopes and no more: offline_access, so it can keep posting without sending you back to Xero every half hour; accounting.invoices, to create the bill; accounting.contacts, to find the supplier's contact record; accounting.settings, to read the chart of accounts, the tax rates and the tracking categories; and accounting.attachments, to attach the source document. They are listed back to you on the connection card, so you can check what was granted rather than remember it.

Where you land. Back on the screen you started from. If the sign-in returned one set of books, a Xero connected message appears and the card names the organization, its country and its plan. If it returned several, there is deliberately no success message: nothing posts anywhere yet, and you land on the chooser in the next step.

3. Say which books receive bills

A connection is not a destination. Authorizing lets inletAP write into a set of books; a separate switch decides whether it does.

  • 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.
  • Anything else — several sets of books from one sign-in, or a Xero connection you already had — arrives switched off, under the heading "Which Xero organizations should receive bills?". Tick the ones approved invoices should post into and press Save. Decide later is a real answer and the screen says so: it leaves the workspace exactly as it is.

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 more than one set of books 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.

4. Choose how bills arrive

How bills arrive, on the connection card, takes one of three answers: post as a draft, post as awaiting approval, or post as approved.

inletAP answers it for you when the connection is made, by reading the organization's own plan: a plan that caps monthly approvals is set to draft, and anything else to approved. That value is written once, while the setting is still empty, and is never overwritten afterwards — a reconnect or a nightly capability read cannot silently revert a choice you made.

Change it if your accountant wants the final say inside Xero. A draft and an awaiting-approval bill both leave the monthly approval allowance alone; an approved bill uses one of them up. Where the organization caps approvals, the card says so before your first export rather than after a refused bill, and it names the setting that avoids it.

5. Match contacts, accounts and tax rates

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

Open Exports → Ledger setup. If you hold more than one connection, pick this one in the Editing bar at the top: everything below it belongs to the ledger named there. Press Read lists from Xero to pull the organization's contacts, accounts, tax rates and tracking categories. Rows that match by name are matched for you; ties are left for a person, because guessing between two similar accounts is the sort of help nobody wants. Show gaps only narrows the tables to what is still outstanding.

In inletAPIn XeroWhat it becomes on the bill
VendorA contactWho the bill is posted against. Only the contact's ID is sent, so posting a bill can never rename your supplier.
GL codeAn account codeAccountCode on the line. Xero keys accounts by code rather than by an internal ID.
Tax codeA tax rateTaxType on the line, which is what carries the tax money.
PropertyA tracking optionThe tracking on the line, so the cost lands on the building.

Set the Default expense account as well. It is what a line uses when the invoice carries no GL code, and without it an uncoded invoice cannot post at all, so it is counted as a blocking gap rather than a preference.

There is no accounts-payable row here and no sales-tax-expense row, and neither absence is 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 instead of being written as an extra expense line. Both of those rows exist for QuickBooks, and neither has a Xero question behind it.

6. Prove it worked

Three checks, in the order they cost you time.

The checklist. Exports → Ledger setup carries five steps read off the connection itself: app authorized, with the scopes that were granted; organization selected, by name; chart of accounts read, with the account count and the time of the last read; contact mapping reviewed; and a test bill posted. That last step closes only when a batch has really succeeded — posting a test bill from that button arrives in a later release, so the way to close it is a real export.

The mapping panel. With nothing outstanding it reads "Everything in use is matched. Approved invoices can post to your ledger." Anything else is counted at the top of the panel and linked to the row that fixes it.

The audit trail. Audit Log carries a Connector Connected entry naming the organization, recorded against System rather than a person. That is deliberate: the return leg is a browser redirect carrying no session, and naming somebody we cannot identify would be worse than admitting we cannot.

Then post something real. Approve one invoice, open Exports, and press Post approved invoices. A succeeded batch names the ledger and the bill; a failed one names the cause per invoice and offers the fix beside it.

Export history with a failed batch expanded, each held invoice naming its reason and the control that fixes it.
The first run is the real test. A batch that failed names the cause invoice by invoice — an unmatched vendor here — and nothing about it posted twice.

What a posted bill carries

The bill is created as an ACCPAY invoice against the matched 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 rather than as one lump.

The invoice date and the due date read off the document become the bill's dates, and the supplier's own invoice number becomes the reference. Each line carries the account code its GL code is matched to — or your default expense account — plus the property as a tracking option where you use tracking. The stated tax is carried by the matched tax rate and split across the lines so the parts add back to the invoice's tax exactly. The status is whatever you chose in step 4, and the currency is the invoice's own, where the organization can hold one.

The source document goes up too, where the invoice arrived with one, and that upload is best-effort by design. A document that arrived without a file posts without an attachment. A file over Xero's 10 MB request ceiling is refused before the upload rather than failing the whole push. Any other upload failure is logged and left alone: the bill is 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 check 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 matched tax rate 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.

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 equivalent here and are not emulated: coding a line to a unit as a sub-customer, and a header department or location. Both are QuickBooks-only, and inventing a stand-in for either would quietly spend the other tracking slot.

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. Where Xero declines to say what happened to the first request, inletAP looks the bill up in Xero and adopts the one that is already there, and only mints a new attempt once it knows there is none.

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

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 now holds. A bill changed or removed 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 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 full, or it does not exist.

What you seeWhat to do
No contact matched for the supplierMatch the vendor to a Xero contact and retry.
The account code could not be resolvedMatch the GL code, or set a default expense account.
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 rest, including stated tax with no matched rate and an organization that cannot hold a foreign-currency bill, are in export failures.

Where to go next

View this page as markdown

Last updated