Overview
This guide describes how Xero — the cloud accounting product from Xero Limited — connects to TrustBill, a UAE FTA-accredited service provider (ASP), so Xero users in the UAE can issue PINT-AE compliant e-invoices without switching accounting systems.
Xero is a global SaaS product with regional editions for the UK, Australia, New Zealand, the US, Canada, Singapore, Hong Kong and South Africa — plus a "Global" edition used everywhere else, including the UAE. Xero has no dedicated UAE edition, so UAE customers run the Global edition with manually configured 5% VAT and TRN handling. Xero does not natively generate PINT-AE XML or transmit through a UAE-accredited ASP.
TrustBill closes that gap through a certified Xero App Store connector authenticated with Xero's OAuth 2.0 + PKCE flow. Approved (posted) invoices are pulled from Xero via webhook + REST fetch, translated into PINT-AE XML, validated in real time, delivered over Peppol via a certified ASP (Tron-Stride or Storecove), and the FTA acknowledgement reference is written back onto the invoice's Reference field or a tracking category.
What this integration delivers
- Certified Xero App Store app — installed with two clicks, OAuth 2.0 with PKCE, no code
- Works across all Xero plan tiers (Ignite / Grow / Comprehensive / Ultimate — the new global names, or the older Starter / Standard / Premium / Ultimate depending on region)
- Read on
Invoices(AUTHORISED status),CreditNotes,Contacts,Items,TaxRates,Organisation - UAE VAT rates (5% Standard, Zero-Rated, Exempt, Reverse Charge, Out of Scope) mapped to FTA tax categories
- Live FTA status written back onto the Xero invoice's Reference field or a dedicated TrustBill Status tracking category
- Multi-currency Xero invoices converted to AED using Xero's own
CurrencyRate - Bulk migration path for historical Xero invoices via CSV export
- Multi-organisation Xero logins handled — a single OAuth session can serve many client orgs
What is Xero?
Xero is a cloud-based accounting SaaS product, popular with SMEs and accountant-managed businesses worldwide. It is browser-based, evergreen (no client versioning — everyone runs the same current release), with a well-documented public REST API and OAuth 2.0 authentication.
- Cloud-only — accessed via
go.xero.com; no on-premise install - Regional editions determine the default chart of accounts and pre-baked tax rates, but the underlying data model is identical across regions
- Bank-feed heavy workflow — most Xero SMEs run their books off automatic bank reconciliation
- Companion products: Xero Practice Manager, Xero Projects, Xero Expenses, Xero Payroll, Xero Inventory Plus, Xero Analytics
- Public API at
api.xero.comwith REST endpoints for Invoices, Contacts, Items, TaxRates, CreditNotes, Reports, etc. - Webhooks for Invoice / Contact events (subscription per Xero App)
Why UAE customers still choose Xero: its bank-feed-driven reconciliation is world-class, and UAE accountants trained in Xero-Practice-Manager workflows keep using it even after migrating. TrustBill lets them keep Xero and add compliance — no ERP migration.
Regional Editions & the UAE Gap
Xero picks a regional edition at organisation creation time. The edition determines: default chart of accounts, default tax rates, currency, financial-year offset, and tax-report layout. There is no dedicated UAE (Middle East) edition — UAE customers run one of the flexible editions with manually configured 5% VAT.
| Xero region | Tax engine | UAE recommendation |
|---|---|---|
| Xero Global | Fully customisable VAT/GST/Sales-Tax rates | Recommended — add your own UAE 5% VAT + Zero/Exempt rates |
| Xero UK | VAT + Making Tax Digital | Supported — set your VAT rates to UAE values manually |
| Xero Singapore | GST | Supported — customise rates to UAE VAT |
| Xero Hong Kong | No sales tax by default | Supported — add UAE VAT rates manually |
| Xero Australia | GST + BAS | Not ideal — GST tax report differs from UAE VAT 201 layout |
| Xero New Zealand | GST | Not ideal — same as AU |
| Xero US | Sales Tax + 1099s | Not compatible — no VAT model |
| Xero Canada / South Africa | GST/HST/PST / VAT (SA) | Supported — customise rates to UAE values |
Xero region cannot be changed after creation. If you are on the US edition, you'll need to set up a fresh Global-edition organisation and migrate customers/items/opening-balances via Xero's own Migration tool before installing TrustBill. Xero's Migration team runs the migration for free within a 30-day window.
Supported Xero Plans & Modules
Xero rebranded its subscription tiers globally in 2025. Both the new and the legacy plan names are supported by the connector.
| Xero plan (new name — 2025+) | Legacy name | API access | Support level |
|---|---|---|---|
| Xero Ignite | Starter | Yes — limited invoice count | Full — invoice-count limits still apply on Xero side |
| Xero Grow | Standard | Yes | Full — recommended baseline |
| Xero Comprehensive | Premium | Yes + multi-currency | Full — recommended if you invoice in multiple currencies |
| Xero Ultimate | Ultimate | Yes + all modules | Full |
| Xero Non-Profit / Partner-Managed | Various | Yes | Full — same API surface |
Modules the connector reads from
| Module | Role in the flow |
|---|---|
| Invoices (Sales) | Primary source of out_invoice — connector reads on AUTHORISED status |
| Credit Notes (Sales) | Source of credit_note |
| Bills (Purchases) — optional | Source of purchase when reverse-charge is required |
| Contacts | Buyer TRN (via TaxNumber), address, country, name |
| Items | SKU / Code, description, default tax type |
| Tax Rates | Custom UAE VAT rates → TrustBill taxCategory |
| Tracking Categories | Used for write-back (TrustBill Status, TrustBill Ack Ref) |
Prerequisites
On the Xero side
- Any active Xero plan (Ignite or higher) on a VAT-capable edition (Global, UK, SG, HK, CA, ZA)
- Organisation base currency =
AED, or multi-currency (Comprehensive+) with AED enabled - Organisation VAT/Tax settings: Business Settings → Financial Settings → Organisation's Tax Basis matches your VAT registration
- Company TRN saved in Business Settings → Organisation Details → Tax Number
- Contacts populated with the buyer's TRN in the Tax Number field for B2B customers
- Custom UAE VAT tax rates configured under Accounting → Advanced → Tax Rates (Standard 5%, Zero-Rated, Exempt, Reverse Charge, Out of Scope)
- Xero user with the Adviser or Standard role (only Adviser can install app-store apps that need OAuth write scope for write-back)
On the TrustBill side
- A TrustBill SME account (one account = one TRN = one Xero organisation)
- Completed KYB (business verification) — trade licence + TRN certificate uploaded
- Submission mode set to
testorsandboxduring onboarding,livefor production - OAuth credentials are provisioned automatically at App Store install; no manual API key
Integration Architecture
Push-first: Xero fires a webhook when an invoice transitions to AUTHORISED; TrustBill fetches the full record via REST and drives the pipeline.
Outbound flow (Xero → TrustBill → FTA)
- A user approves an invoice in Xero (invoice status becomes
AUTHORISED). Draft and Submitted (needs-approval) invoices are ignored. - Xero fires the
INVOICE / UPDATEwebhook to the URL registered by the TrustBill App at install. - TrustBill's Xero webhook receiver verifies the HMAC-SHA256 signature (
x-xero-signatureheader) and acknowledges immediately. - Asynchronously, TrustBill fetches the full Invoice + Contact + LineItems via
GET /api.xro/2.0/Invoices/{invoiceID}. - The payload is translated into TrustBill's
InvoiceCreateInputshape. - TrustBill's internal
POST /v1/invoicesstores the invoice asdraft. - If auto-submit is enabled,
POST /v1/invoices/submitfires immediately. - Pipeline:
queued → transformed → validated → delivered. ASP forwards to FTA over Peppol.
Inbound flow (FTA → TrustBill → Xero)
- ASP posts an inbound webhook to TrustBill on FTA acknowledgement.
- TrustBill's Xero worker calls
POST /api.xro/2.0/Invoices(upsert semantics keyed onInvoiceID) to update the Reference field or a Tracking Category with the FTA acknowledgement ref. - Users see the status column in the Xero Sales list within seconds.
Connection Methods
Five paths — the App Store app covers 95% of customers; the others exist for specific corner cases.
1. Xero App Store App (recommended)
Install TrustBill E-Invoicing for Xero from apps.xero.com. OAuth 2.0 with PKCE handshake, webhooks auto-registered, custom fields / tracking categories auto-provisioned.
- Certified by Xero Developer Program
- No code, no server, no manual keys
- Handles multi-organisation logins (accountants managing many client orgs)
- Auto refreshes tokens (Xero access tokens live 30 min; refresh tokens rotate on use)
2. Direct API + Webhooks (custom middleware)
Register your own Xero Developer app and subscribe to the INVOICE webhook. Your middleware receives the callback, fetches the invoice, and calls the TrustBill REST API.
- Best when you need custom transformation logic or already run middleware
- You manage the OAuth tokens (PKCE, refresh rotation, HMAC verification)
- Follow the ERP Partner API guide
3. Xero SDK polling
Use the official xero-node, xero-python or xero-net SDK to poll for AUTHORISED invoices on a schedule. Best when webhooks are blocked by your firewall.
- Query with
GET /Invoices?where=Status=="AUTHORISED" AND UpdatedDateUTC>=DateTime(...) - Respect the 60-req/min tenant + 5000-req/day realm rate limit
- Requires periodic OAuth refresh — SDKs handle rotation
4. Zapier / Make (no-code)
TrustBill publishes a Zapier and Make connector — build a "New Xero AUTHORISED invoice → Create TrustBill invoice → Submit" flow in minutes.
5. CSV Export (one-off migrations)
Export from Business → Invoices → Export, run the TrustBill xero-csv-normaliser, upload via POST /v1/invoices/bulk.
Which method should I use?
For 95% of Xero UAE customers, install the App Store app. Use Zapier / Make if your team already standardises on one. Use SDK polling only when webhooks are firewalled. Use direct API only for custom transformation logic. Use CSV only for historical migrations.
Authentication (OAuth 2.0 + PKCE)
Xero requires OAuth 2.0 with PKCE for all new integrations. The App Store app requests the following scopes at install:
openid (identity)
profile (user profile)
email (user email)
accounting.transactions (read + write invoices, credit notes, bills)
accounting.contacts (read + write contacts)
accounting.settings (read tax rates, org, tracking categories)
accounting.attachments (optional — attach PINT-AE XML back to Xero invoice)
offline_access (issue refresh token)Token lifetimes
| Token | Lifetime | Notes |
|---|---|---|
| Access token | 30 minutes | Used as Authorization: Bearer |
| Refresh token | 60 days idle | Rotates on every use — old refresh token is invalidated. TrustBill handles rotation atomically. |
| Tenant connection | Until explicitly disconnected | Multiple tenantIds can be attached to one refresh token |
Tenant selection
Xero's OAuth callback returns a list of authorised tenants (organisations). A single Xero login (typical for accountants) can carry access to many client orgs — TrustBill stores the mapping tenantId → trustbill_tenant_id so you can serve every client from one Xero session.
Idempotency-Key derivation for Xero
Every TrustBill write endpoint requires an Idempotency-Key. Derive it from the Xero invoice's stable InvoiceID (GUID):
Idempotency-Key: xero::{tenantId}::Invoice::{InvoiceID}Xero webhook retries and refresh-token rotations reuse the same key — TrustBill returns the cached response, so retries never create duplicate FTA submissions.
Xero API Rate Limits
Xero's rate limits are per-tenant, not per-app — so a single client org gets the full budget even if it's connected to multiple apps.
| Limit | Value | Header returned |
|---|---|---|
| Concurrent requests | 5 per tenant | HTTP 429 x-rate-limit-problem: concurrent |
| Requests per minute | 60 per tenant | x-minlimit-remaining |
| Requests per day | 5,000 per tenant | x-daylimit-remaining |
| App-wide | 10,000 requests / minute across all tenants | — |
The TrustBill connector implements exponential backoff on 429 and prefers webhooks over polling so the daily limit stays under 200 requests / tenant / day even at high invoice volumes.
Xero → PINT-AE Field Mapping
Xero exposes invoice data via GET /api.xro/2.0/Invoices/{InvoiceID}. The connector reads the returned JSON and maps into TrustBill's InvoiceCreateInput.
Header-level mapping
| Xero field | TrustBill field | Notes |
|---|---|---|
InvoiceNumber | number | Xero's human-readable number ("INV-0042"); 1–64 chars |
InvoiceID | Idempotency-Key + sellerInvoiceReference | GUID; stable across Xero renumbering |
Date | issueDate | Xero returns /Date(1725753600000)/ — connector normalises to ISO YYYY-MM-DD |
DueDate | dueDate | Optional |
Type | invoiceType | ACCREC → sale, ACCPAY → purchase |
Status | gate — only AUTHORISED and PAID are pulled | DRAFT / SUBMITTED / VOIDED / DELETED ignored |
CurrencyCode | currency | Must be AED; multi-currency invoices converted at CurrencyRate |
Organisation.TaxNumber | seller.trn | 15-digit UAE TRN (from GET /Organisation) |
Organisation.LegalName | seller.name | — |
Contact.Name | buyer.name | Fetched from GET /Contacts/{ContactID} |
Contact.TaxNumber | buyer.trn | 15-digit TRN; leave empty for B2C |
Contact.Addresses[type=POBOX or STREET] | buyer.address | Prefer STREET; fall back to POBOX |
Contact.Addresses[*].Country | buyer.country | Normalised to ISO 3166-1 alpha-2 |
Reference | buyerReference | Customer PO — also the write-back target for FTA ack ref |
LineAmountTypes | controls inclusive/exclusive handling | Exclusive / Inclusive / NoTax |
UpdatedDateUTC | delta cursor for polling | Used by the SDK polling path |
Line-level mapping (LineItems[])
| Xero field | TrustBill field | Notes |
|---|---|---|
Description | lines[].description | Non-empty; supports Unicode / Arabic |
Quantity | lines[].quantity | Must be > 0 |
UnitAmount | lines[].unitPrice | VAT-exclusive; connector strips VAT when LineAmountTypes=Inclusive |
DiscountRate / DiscountAmount | lines[].discountAmount | Per-line, applied before VAT |
ItemCode | lines[].sellerItemId | From Xero Items catalogue |
TaxType | lines[].vatRate + lines[].taxCategory | Xero tax type code — mapped via the Xero Tax Rate Mapping table |
Tracking[] | Not sent to FTA | Preserved on the Xero side; used for TrustBill status write-back |
Totals are computed server-side
Do not send Xero's SubTotal / TotalTax / Total. TrustBill re-computes totals from lines[] and returns them. If Xero's Total differs from TrustBill's by more than ±0.01 AED (Xero rounds per-line inclusive-tax invoices differently), the connector logs a variance and blocks submission until you toggle the invoice to Exclusive or re-save it.
Create Invoice (draft)
Endpoint: POST /v1/invoices
A real Xero invoice mapped to the TrustBill payload. Xero invoice: INV-0042 — Sale of digital marketing services to a Dubai buyer at 5% VAT.
Request body
{
"number": "INV-0042",
"issueDate": "2026-09-08",
"dueDate": "2026-10-08",
"currency": "AED",
"invoiceType": "sale",
"buyer": {
"name": "Nexus Media Group LLC",
"trn": "100447889200013",
"country": "AE",
"email": "ap@nexusmedia.example",
"address": {
"line1": "Business Bay, Bay Square 8",
"city": "Dubai",
"country": "AE"
}
},
"seller": {
"name": "Xero Studio LLC",
"trn": "100100100100019",
"country": "AE"
},
"lines": [
{
"description": "Q4 2026 Search Marketing Retainer",
"sellerItemId": "SVC-SEO-RETAINER",
"quantity": 1,
"unit": "MON",
"unitPrice": 8500.00,
"vatRate": 0.05,
"taxCategory": "standard_5"
}
],
"sellerInvoiceReference": "Xero InvoiceID 3b7f4c...",
"notes": "Payment: 30 days net"
}Response (201 Created) — abbreviated:
{
"id": "4a2d8c6b-....-uuid",
"number": "INV-0042",
"status": "draft",
"invoiceType": "sale",
"totals": { "subtotal": 8500, "tax": 425, "total": 8925, "currency": "AED" },
"pipeline": [],
"errors": [],
"submissionMode": "sandbox",
"source": "xero-appstore-app"
}Credit Notes
Xero represents credit notes as separate CreditNote records at /api.xro/2.0/CreditNotes. Xero also links a credit note to one or more invoices via the CreditNoteNumber and Allocations arrays.
| Xero record | invoiceType | Required extra fields |
|---|---|---|
CreditNote type ACCRECCREDIT with Allocations[] | credit_note | referencedInvoiceNumber = allocated invoice's InvoiceNumber, reasonCode |
CreditNote type ACCRECCREDIT standalone (no allocations) | credit_note | reasonCode = OtherAdjustment |
CreditNote type ACCPAYCREDIT (purchase-side) | debit_note | referencedInvoiceNumber = original Bill's InvoiceNumber, reasonCode |
Sign convention: Xero credit notes carry positive quantities and positive rates — send them the same way to TrustBill. The invoiceType tells the FTA that the document reverses the reference invoice; PINT-AE handles the sign in the XML.
Repeating Invoices
Xero's Repeating Invoices generate concrete invoices on a schedule. The connector treats each generated invoice as a fresh event:
- Each cycle creates a new
Invoicewith its ownInvoiceID— fresh Idempotency-Key, fresh TrustBill draft, fresh FTA submission - Xero fires the
INVOICE / CREATEwebhook as soon as the child is created (usually inDRAFT— connector waits until it becomesAUTHORISED) - The Repeating template itself is not pushed to TrustBill — only the concrete invoices it produces
- If the Repeating template is set to Approve for sending, invoices land straight in AUTHORISED and flow through immediately
Auto-submit tip: for Repeating Invoices, enable TrustBill's auto-submit on ingest. Otherwise every child sits as a draft in TrustBill waiting for a human to click Submit.
Submit Invoice(s) for Delivery
Creating a draft in TrustBill does not deliver the invoice to the FTA. Submission is an explicit second call.
Endpoint: POST /v1/invoices/submit
{ "ids": ["4a2d8c6b-....-uuid"] }Xero UX: the App Store app installs a Send to FTA action under the Xero invoice's 3-dot menu. Because Xero's AUTHORISED status is itself the "invoice is real" signal, most tenants prefer auto-submit-on-ingest and don't use the manual button.
Status Tracking & Write-back
Xero does not expose invoice-level custom fields via API (they're editable only through the UI). The connector uses two write-back paths:
| Path | What it writes | Visible in Xero |
|---|---|---|
| Reference field | Compact stamp: {user reference} · TrustBill: {status} · {FTA ref} | Yes — Reference column on the Sales / Invoices list |
| Tracking Category | A dedicated TrustBill Status tracking category with values Draft / Queued / Delivered / Acknowledged / Rejected | Yes — filter and pivot the Sales list by this category |
| Attachment | The final PINT-AE XML attached to the Xero invoice | Yes — Attachments tab on the invoice |
| TrustBill status | Xero side effect |
|---|---|
| draft / queued / validated | Tracking Category set; Reference field not yet updated |
| delivered | Tracking Category set to Delivered |
| acknowledged | Reference field stamped with FTA ack ref; Tracking Category = Acknowledged; PINT-AE XML attached |
| rejected | Tracking Category = Rejected; Reference field stamped with reject code |
Bulk Migration from Xero
To migrate historical Xero invoices (up to 12 months back) into TrustBill:
- In Xero: Business → Invoices → filter by date range and Status = AUTHORISED or PAID → Export
- Run the TrustBill xero-csv-normaliser script to remap column headers
- Upload in
testmode viaPOST /v1/invoices/bulk - Review the summary; repeat in
sandboxandlive
TrustBill CSV column headers
number,issueDate,dueDate,invoiceType,currency,sellerTrn,sellerName,buyerTrn,buyerName,buyerCountry,buyerAddressLine1,buyerCity,lineDescription,lineQty,lineUnit,lineUnitPrice,lineVatRate,lineTaxCategory,referencedInvoiceNumber,notes| Limit | Value |
|---|---|
| Max rows per file | 1,000 invoices |
| Max file size | 5 MB |
| Partial success | Yes — bad rows reported without rolling back the batch |
Xero Demo Company + TrustBill Modes
Xero provides a free Demo Company alongside every user account — a seeded sandbox tenant that can be reset any time. Use it during onboarding paired with TrustBill's sandbox mode.
Xero side
- Demo Company: switchable from the Xero organisation menu; free with any plan; can be reset to fresh seed data
- Production organisation: your real books
- Both share the same OAuth session — just pick the tenant when connecting
TrustBill side
| TrustBill mode | Purpose | Reaches FTA? |
|---|---|---|
test | Local integration testing — no ASP call | No |
sandbox | End-to-end dry run against the ASP sandbox | FTA sandbox only |
live | Real, legally binding e-invoicing | Yes — the FTA production network |
Recommended pairing during onboarding: Xero Demo Company + TrustBill sandbox mode. Switch both to production on go-live day.
Xero Tax Rate Mapping (UAE)
Because there's no UAE Xero edition, you configure UAE VAT rates yourself under Accounting → Advanced → Tax Rates. The connector reads Xero's TaxType string per line and maps it via the following table.
| Xero Tax Rate name (create in Xero) | Rate | TrustBill vatRate | TrustBill taxCategory |
|---|---|---|---|
| UAE VAT 5% on Sales | 5% | 0.05 | standard_5 |
| UAE Zero-Rated Sales (Export) | 0% | 0 | zero_rated_export |
| UAE Zero-Rated Sales (Healthcare) | 0% | 0 | zero_rated_healthcare |
| UAE Zero-Rated Sales (Education) | 0% | 0 | zero_rated_education |
| UAE Exempt Sales (Financial) | Exempt | 0 | exempt_financial |
| UAE Exempt Sales (Residential Rent) | Exempt | 0 | exempt_residential_rent |
| UAE Reverse Charge (Designated Zone) | 0% | 0 | reverse_charge_designated_zone |
| Out of Scope | No Tax | 0 | out_of_scope |
The TrustBill App Store app can auto-create these tax rates in your Xero organisation on install (Xero permits creation via the accounting.settings scope). If you already have tax rates with different names, map them once in TrustBill Sources → Xero → Tax Rate Mapping.
UAE-Specific Scenarios
Free Zone / Designated Zone sellers
Xero has no concept of a designated-zone flag. Set it on your TrustBill tenant (Settings → Company → Zone Type = Designated). It flows through as seller.designatedZone: true so PINT-AE emits the free-zone declaration.
Margin scheme
Use a Xero Tracking Category value Margin Scheme on the invoice line. The connector reads it and sends lines[].marginScheme: true, using the item's Purchase Price as the margin base.
Reverse charge on imports
Bills (Type=ACCPAY) from non-UAE suppliers using the UAE Reverse Charge tax rate are mapped to invoiceType: purchase + taxCategory: reverse_charge_designated_zone. PINT-AE emits the ReverseCharge markers.
B2C simplified tax invoices
Contacts with no TaxNumber are treated as B2C. Invoices under 10,000 AED become simplified tax invoices under FTA rules — TrustBill emits the correct PINT-AE profile automatically.
Multi-currency
On Xero Comprehensive+, invoices in USD / EUR / GBP etc. carry a CurrencyRate. The connector converts every line to AED and reports AED totals to the FTA, preserving the original invoiced currency in the PINT-AE Note for reconciliation.
Multi-Organisation Xero
A single Xero login (typical for accountants) can be authorised on many organisations. The OAuth callback returns a list of tenant IDs the user has access to.
- Each Xero organisation = one TRN = one TrustBill tenant
- The App Store app stores the mapping
xero_tenant_id → trustbill_tenant_id, so one Xero login can serve many clients - TrustBill's Accounting Firm account type surfaces every client tenant on a single dashboard
Rate limits are per tenant, so an accounting firm with 50 client orgs gets 50× the effective rate budget. No global throttling within your Xero App app.
Error Handling
TrustBill errors follow the shape { code, humanMessage, meta? }. The App Store app writes the code into the Xero Tracking Category (TrustBill Reject Reason) so it's discoverable from within Xero.
| HTTP | Typical code | Xero root cause | Action |
|---|---|---|---|
| 400 | invalid_body | Contact missing TaxNumber, or line missing TaxType | Fix the Contact / invoice in Xero; connector auto-retries on next AUTHORISED update |
| 400 | totals_mismatch | Xero per-line inclusive-tax rounding vs TrustBill per-invoice | Toggle the invoice's Amounts are to Tax Exclusive, re-save |
| 400 | unknown_tax_type | Custom-named Xero Tax Rate not in the connector's map | Add mapping in TrustBill Sources → Xero → Tax Rate Mapping |
| 400 | region_not_supported | Xero organisation is on US edition (no VAT engine) | Ask Xero Migration team to move you to Global edition |
| 401 | xero_oauth_expired | Refresh token expired (60 days idle), or user revoked | Reconnect the App Store app from Xero Settings → Connected Apps → TrustBill → Reconnect |
| 401 | xero_tenant_removed | User revoked the tenant connection | Re-authorise the tenant during a fresh App Store app OAuth flow |
| 403 | kyb_required | TrustBill tenant not yet approved by compliance | Contact TrustBill support |
| 403 | xero_scope_denied | User declined an OAuth scope (e.g. accounting.settings) | Re-run OAuth with all scopes granted; write-back and tax-rate creation need settings |
| 409 | invoice_mode_mismatch | Xero production connected but TrustBill still in sandbox | Switch mode in TrustBill dashboard |
| 409 | invoice_number_duplicate | Two Xero orgs pushed the same InvoiceNumber | Use per-org invoice-number prefixes (Xero Settings → Invoice Settings → Prefix) |
| 429 | xero_rate_limited | 60-req/min tenant cap hit | Automatic exponential backoff — respects x-rate-limit-problem header |
Setup Checklist
- Confirm Xero edition — Global (recommended), UK, SG, HK, CA or ZA. US edition needs migration first.
- Set organisation base currency to AED, or enable AED under multi-currency (Comprehensive+)
- Fill Company TRN in Organisation Details → Tax Number
- Add the 8 UAE VAT Tax Rates under Accounting → Advanced → Tax Rates (or let the App Store app auto-create them on install)
- Populate Contact TRNs for every B2B customer
- Create your TrustBill SME account and complete KYB
- Install the TrustBill App Store app from
apps.xero.comas a Xero Adviser user - Approve all requested OAuth scopes (including
accounting.settings) - Pick the tenant during the OAuth callback (or select multiple if you're an accountant)
- Confirm auto-created tracking category TrustBill Status exists on the organisation
- Enable
sandboxmode in TrustBill - Approve a test invoice in Xero and confirm the Tracking Category becomes Acknowledged within 3 minutes
- Reconcile Xero's Reports → Sales Tax Report against TrustBill's Delivered Invoices
- Switch to
livewhen FTA registration is complete
Suggested test cases before go-live
- B2B invoice at 5% VAT, AUTHORISED — expect
acknowledged - Draft invoice in Xero — expect no TrustBill submission (only AUTHORISED are pulled)
- B2C invoice under 10,000 AED (Contact with no TaxNumber) — expect PINT-AE "simplified" profile
- Credit Note allocated to an earlier invoice — expect matching pair
- Export sale (Contact country != AE, UAE Zero-Rated Export tax) — expect
zero_rated_export - Designated-zone customer — expect reverse-charge markers
- Multi-line invoice with mixed VAT (5% + 0%) — expect two
taxCategoryvalues - Repeating Invoice child fires — expect fresh FTA submission on AUTHORISED status
- Multi-currency invoice (USD, converted via Xero CurrencyRate) — expect AED-normalised totals
- Multi-tenant login (accountant with 3 client orgs) — expect routing to correct TrustBill tenant per org
- Refresh-token rotation — expect zero user impact
- Bulk upload of 500 historical invoices via CSV — expect partial success reported per row
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| App Store install fails with "Adviser role required" | User is on Standard or Read Only role | Ask the Xero org owner to grant Adviser role, or install as the owner |
| Invoice approved in Xero, nothing in TrustBill | Webhook signature mismatch — Xero rejects retries after 7 attempts | Check Xero Developer Portal → App → Webhook logs; re-authorise if the app secret was rotated |
| Tracking Category doesn't appear | OAuth scope accounting.settings denied | Reconnect the app and approve all scopes |
Invoice stuck in queued | Insufficient TrustBill credit or KYB pending | Check the TrustBill dashboard banner; top up credit |
Invoice reaches rejected with "buyer_trn_invalid" | Contact TaxNumber has spaces or is 14 digits | Fix in Xero: Contact → Edit → Tax Number. Connector auto-retries on next AUTHORISED update. |
totals_mismatch on inclusive-tax invoices | Xero per-line rounding on inclusive tax | Change Amounts are to Tax Exclusive on affected invoices |
| Refresh token stops working overnight | Refresh-token rotation collision — two workers used the same token concurrently | Reconnect the app; TrustBill's connector serialises refreshes atomically |
| 429s during first-time historical sync | Bootstrap sync hit the 5,000/day cap | Wait for the daily reset; TrustBill's connector paces bootstrap to avoid this |
| Duplicate FTA submissions after a network blip | Custom middleware missed the Idempotency-Key | Use xero::tenantId::Invoice::InvoiceID derivation |
| Status write-back Reference field wiped | User edited the Reference field manually after stamp | Connector re-stamps on the next status change; existing user reference is preserved as prefix |
Support & Contact
Technical Support
- WhatsApp: +971 52 260 9313
- Email: info@trustbill.ae
- Documentation hub: trustbill.ae/en/documentation
- Xero integration marketing page: trustbill.ae/en/integrations/xero
- QuickBooks Online integration: /documentation/quickbooks-online
- Zoho integration: /documentation/zoho
- Odoo integration: /documentation/odoo
- Tally integration: /documentation/tally
- ERP Partner API guide: /documentation/erp-partner-api
Escalation
For Xero go-live escalations, please include: your TrustBill tenant ID, the Xero tenantId, the failing invoice's InvoiceID and InvoiceNumber, and the timestamp of the failed pipeline run. TrustBill support responds to Xero-tagged tickets within one business hour during UAE working days.