Connect Xero: pull orders, customers, invoices and products, check inventory
Complete the OAuth2 flow for your app on developer.xero.com with the three read scopes, copy the Tenant ID from the connections list, paste both values into Integration, test, map, activate.
The Xero connector pulls orders, customers, invoices and products from your Xero organisation into this system, can push customers, products and invoices back to Xero, and can check inventory quantities through Xero Items. It does not push inventory changes back to Xero: inventory is read-only in this connection. One connection is for one Xero organisation, identified by its Tenant ID.
Prerequisites#
- A Xero organisation you can sign in to, and an app registered for it on developer.xero.com.
- You can complete the OAuth2 flow for that app on developer.xero.com and grant all three read scopes: accounting.transactions.read, accounting.contacts.read and accounting.settings.read. A token missing any one of them will fail the test or the pulls.
- You know which organisation the connection is for. The Tenant ID is the organisation ID, not the app ID — the two are different values and are not interchangeable.
Get your credentials#
- Go to developer.xero.com, open your app, and complete the OAuth2 flow. When Xero asks for scopes, include at least accounting.transactions.read, accounting.contacts.read and accounting.settings.read.
- Copy the access token that the OAuth2 flow returns. This token is what you paste into Integration — there is no separate API key to create for this connection.
- Get the Tenant ID for your organisation in one of two ways: call GET https://api.xero.com/connections with the access token and copy the tenantId of your organisation from the response; or open developer.xero.com → your app → connections and read the tenantId shown there.
Fill it into Integration#
- Open Integration → Connector Marketplace → Xero → New connection.
- tenant_id — required, Tenant ID (Organisation): paste the tenantId of your organisation, in the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. It is the organisation ID from the connections list, not the app ID.
- access_token — required, Access token: paste the access token returned by the OAuth2 flow, in full. It is a password-type field and is stored as a secret. Make sure the token was granted with accounting.transactions.read, accounting.contacts.read and accounting.settings.read.
Test the connection#
Click Test connection. The test sends a real request to GET https://api.xero.com/api.xro/2.0/Organisation with two headers: Authorization: Bearer followed by your access token, and xero-tenant-id with your tenant_id. A 200 response counts as a pass, and the result shows the organisation name Xero returned, so you can confirm it is the organisation you meant. A 401 means the token is invalid or expired; a 403 means the token does not carry enough scope. If tenant_id or access_token is missing, the test stops before sending anything, because both values are needed for this probe. The probe times out after 12 seconds.
Mapping / pick a template#
Pick the Xero standard mapping. Orders, customers and invoices follow the standard Xero Accounting records, products and inventory checks follow Xero Items. After the test passes, run one pull and check a real order side by side — order number, customer, lines and amounts — check one invoice and one product the same way, and compare one item quantity with what Xero shows, before activating.
Activate#
After activation, the connection pulls orders, customers, invoices and products from the Xero organisation named by your tenant_id on the schedule you set, pushes customers, products and invoices to Xero when those flows run, and reads inventory quantities from Xero Items when inventory is checked. Watch the first runs in Runs / Logs and compare them with Xero before leaving the connection unattended.
What this connection does not do: it does not push inventory changes back to Xero. Quantities in Xero Items are read for checks only, so stock adjustments still need to be made in Xero itself or in the system where the adjustment actually happens.
FAQ#
Test fails with 401 — token invalid or expired
Xero refused the access token itself: it is wrong, incomplete, or no longer valid. The organisation probe never gets past authentication in this case, so the tenant_id is not the first thing to check.
Go back to developer.xero.com → your app, complete the OAuth2 flow again, copy the fresh access token in full into the access_token field, and test again.
Test fails with 403 — scope is not enough
The token was accepted, but it was not granted the read scopes this connection needs. The required three are accounting.transactions.read, accounting.contacts.read and accounting.settings.read — missing any one of them can produce this result.
Redo the OAuth2 flow on developer.xero.com for your app and grant all three scopes this time, paste the new access token into Integration, and test again. Do not just re-paste the old token — its scopes do not change.
The token is right, but the test still fails — wrong organisation
The tenant_id does not belong to the organisation the token was authorised for. The probe sends your tenant_id in the xero-tenant-id header, and Xero answers for that organisation only — a valid token paired with another organisation ID fails here, and the organisation name in a successful result is the check that you picked the right one.
Re-copy the tenantId for the intended organisation: call GET https://api.xero.com/connections with the access token and pick that organisation tenantId from the response, or read it under developer.xero.com → your app → connections. Replace tenant_id, save, and test again — then confirm the organisation name shown matches.
Test stops before sending — a required value is missing
tenant_id or access_token is empty. The organisation probe needs both: the token for the Authorization header and the tenant_id for the xero-tenant-id header, so the test stops instead of sending a request that cannot succeed.
Fill in both fields from the fill-in step — tenant_id from the connections list and access_token pasted in full — save, and test again.
Connected, but inventory quantities never change in Xero
That is the boundary of this connection, not a failure: inventory is read from Xero Items for checks, and inventory changes are not pushed back to Xero. Orders, customers, invoices and products flow as described above; stock levels in Xero stay under Xero control.
Make stock adjustments in Xero itself, or in the system where the adjustment actually happens, and use this connection inventory check to verify the quantities afterwards.
Test times out after 12 seconds
The organisation probe did not get an answer from Xero in time. This is a reachability or response problem on the way to api.xero.com, not a verdict on your token or tenant_id — neither value was actually judged.
Wait a moment and run Test connection again with the same two values. If timeouts repeat while other connections test fine, note the time and the exact message from Runs / Logs before changing any value.