Moving from Xero to Odoo in Australia follows nine steps. Done properly, a small-business migration takes four to eight weeks. Done in a rush over a long weekend, it takes six months to unwind.

  1. Export your Xero data.
  2. Pick a cutover date aligned to your BAS cycle.
  3. Configure Odoo’s Australian localisation — GST, BAS, Peppol.
  4. Import contacts before anything else.
  5. Import open invoices and bills.
  6. Post opening balances from the trial balance.
  7. Switch bank feeds and ABA payments.
  8. Handle Xero-specific gotchas — payment allocations, rounding, payroll.
  9. Parallel-check for three to five days, then go live.

This is the playbook we actually use. It assumes you’ve already decided Odoo is the right next step — if you’re still weighing that up, the short test is whether Xero is now the bottleneck (inventory, manufacturing, field service, multi-entity) rather than the accounts engine.

When not to migrate off Xero

Not every business should move. We’ve talked several prospects out of it in the last twelve months, and the pattern is consistent. You probably shouldn’t migrate if:

  • You have fewer than ten users and your only pain point is that Xero “feels limited.” It isn’t — you haven’t hit its real ceiling yet. Rebuild your chart of accounts and add tracking categories before spending $30,000 on a migration.
  • Your bolt-ons are working. If Xero plus Employment Hero plus a single inventory tool covers 90% of operations and reconciles cleanly, the case for consolidation is weak. Odoo earns its fee by retiring three or four tools and the integration tax between them; with one clean integration the sum doesn’t work.
  • You don’t have internal capacity for the cutover. A Xero-to-Odoo migration requires four to eight weeks of engaged attention from someone in finance, plus two to three hours a week from the business owner. If that time isn’t available, delay the project until it is. A rushed migration is worse than a slow one.
  • You’re within six months of a sale, merger, or raise. Swapping ERPs inside a transaction window is a self-inflicted due diligence headache. Wait until the dust settles, then migrate in a clean quarter.
  • Your data is a mess. Migrations surface every reconciliation shortcut and dangling balance your team has papered over for years. Clean the books in Xero first. Migrate second. Do both at once and neither goes well.

If none of those describe you and Xero genuinely is the ceiling, read on.

Why businesses outgrow Xero

Xero is an excellent accounting product. It’s not an ERP, and at around 20 to 50 staff most Australian businesses hit the same wall: three or four bolt-ons patched around it — Cin7 or DEAR for inventory, ServiceM8 or Tradify for jobs, Employment Hero for payroll, a spreadsheet for everything in between. Each integration charges its own per-user fee, breaks on its own schedule, and reconciles against a single source of truth that doesn’t exist.

We worked with a Perth wholesale importer running Xero plus Cin7 plus a custom Zapier mesh; by the time they called us, they were paying roughly $1,100 a month in SaaS fees across six tools and spending two days a month reconciling stock-on-hand against the GL. Moving the whole stack into Odoo took their monthly software bill to around $540 for 12 users and collapsed the reconciliation work to about an hour. That’s the typical shape. The migration isn’t about leaving Xero; it’s about retiring the four tools you attached to it.

The second trigger is control. Once you’re running manufacturing, field service, or multi-warehouse logistics, you need to model business rules — reorder points, routing, job costing, award interpretation — that a pure accounting product can’t see. Odoo puts those rules into one database the accounts team and the operations team read from.

Fig. 01   The nine-step Xero to Odoo migration loop
Xero to Odoo migration timeline — nine steps grouped into three phases Nine-step migration flow grouped into three phases: Prepare covers export, cutover date, and AU configuration. Load covers contacts, open invoices, and opening balances. Cutover covers bank feeds, gotchas, and go live. PREPARE LOAD CUTOVER 01Export datafrom Xero 02Cutover datealigned to BAS 03AU configGST · BAS · Peppol 04Contactscustomers · suppliers 05Open invoices+ open bills 06Opening balancesfrom trial balance 07Bank feeds+ ABA payments 08Gotchasallocations · payroll 09Go live+ hypercare fortnight

Step 1: Export your Xero data

Xero’s export is cleaner than most. You’ll pull the following in CSV or PDF from the Accounting → Reports and Contacts screens:

  • Chart of accounts (Settings → Chart of Accounts → Export)
  • Contacts (customers and suppliers, separately)
  • Open invoices (Sales → Awaiting Payment)
  • Open bills (Purchases → Awaiting Payment)
  • Bank statements — full history if you want historical bank feeds, twelve months at minimum
  • Trial balance at cutover date
  • Inventory items if you use Xero’s lightweight inventory (unlikely — usually this lives in Cin7 or DEAR)
  • General Ledger detail report (one per financial year)

The gap Xero’s exporter leaves is tracking categories, repeating invoices, and attached files. Tracking categories don’t map one-for-one to Odoo’s analytic accounts — you’ll need to decide whether they become analytic tags, warehouses, cost centres, or departments. Repeating invoice templates have to be rebuilt in Odoo’s subscription or recurring-invoice engine; there’s no export path. Attached files can be pulled via the Xero API or Hubdoc but not through the UI, which catches most DIY migrations by surprise.

Step 2: Choose a cutover date aligned to your BAS cycle

The right cutover date is the first day of a new BAS period. For most small businesses that’s 1 October, 1 January, 1 April, or 1 July. For monthly lodgers it’s the first of any month. Mid-period cutovers are possible but they double your reconciliation work — you’ll finish the period in Xero, start the next in Odoo, and run one consolidated BAS by hand.

End-of-financial-year (1 July) is the cleanest cutover because your opening balances come straight from the audited trial balance, your depreciation schedule restarts, and the payroll year rolls over — so you can hand payroll to Employment Hero integrated with Odoo without splitting STP reports across two platforms. The trade-off: every other Australian business with a bookkeeper is trying to do the same thing in June, so partner capacity is tight. Book early or go with a 1 January cutover.

Step 3: Set up Odoo’s Australian accounting

This is where most generic migration guides lose the plot. Odoo ships an Australian localisation pack that installs the AU chart of accounts, GST tax codes, and BAS report generator — but installing the pack is the first ten per cent. The real work happens in five sub-areas, each of which has a specific failure mode if rushed.

Mapping the chart of accounts

Xero’s chart and Odoo’s AU chart are similar but not identical. Xero’s 4xx revenue codes, 3xx equity codes, and default GST-free adjustments don’t line up one-for-one. Build a mapping table that assigns every Xero code to an Odoo account (or a merged Odoo account) before you import a single transaction. Accounts that exist in Xero but have no activity in the last three years can be retired rather than migrated.

BAS tax groups

Configure tax groups for GST on sales, GST on purchases, PAYG withheld, PAYG instalment, and any WET (wine equalisation tax) or LCT (luxury car tax) exposure. Odoo groups taxes into BAS boxes (G1, 1A, 1B, W1, W2, T1, etc.) via tag assignments on each tax code — miss a tag and the amount won’t appear on the correct BAS line, which is the quiet kind of compliance error that doesn’t show up until the ATO flags a variance.

GST clearing account

Set up a dedicated GST clearing account so that when you pay the ATO, the payment debits the clearing balance cleanly against BAS obligations. Without this, GST collected and GST paid sit in separate balance-sheet accounts and your BAS reconciliation becomes a manual exercise every quarter.

Peppol e-invoicing

If you’re sending invoices to government buyers or large customers already on the Peppol network, enable Odoo’s Peppol BIS 3.0 output and register for an access point. The ATO mandates Peppol for federal government suppliers, and state governments are following. Setup is a half-day job but the timing matters — do it before the first invoice batch to a Peppol-connected customer.

ABA batch payments

Enable batch payments and ABA file generation for your bank. ANZ, NAB, CBA, and Westpac all produce slightly different ABA formats; Odoo handles the variations but each needs the correct bank user-ID and APCA identifier set. Get these from your bank’s corporate internet banking portal, not from Xero’s stored version, which may be stale.

Do this entire step in a test database, not production. You’ll discover tax-code edge cases — export sales, GST-free food lines, imports with deferred GST — that need rules before you load a single invoice. This is the biggest source of rework we see from businesses trying to implement Odoo themselves.

Step 4: Import contacts

Load customers and suppliers before anything else — invoices and bills reference them, so the order matters. Clean the Xero export first: dedupe by ABN where you can, standardise state codes (WA not Western Australia), strip trailing whitespace, and split combined name/company fields into Odoo’s separate name and parent_id structure. For B2B customers, map to Odoo’s company record with contact children underneath; for retail customers, use individual records.

Keep the Xero contact ID as a custom reference field. You’ll thank yourself the first time a historical invoice query needs tracing back to source.

Step 5: Import open invoices and bills

Only open (unpaid) invoices and bills need to come across as transactional documents. Everything historical can live as summary journal entries against opening balance accounts — or stay read-only in Xero for audit. Most businesses don’t need seven years of line-item detail rehydrated into Odoo; the ATO accepts the Xero archive as source records.

For each open invoice, import: invoice number, customer, date, due date, line items with tax codes, payment status (partially paid matters), and any attached PDF. Watch out for Xero’s rounding: it rounds line-item tax to two decimals and then sums, while Odoo sums line-item amounts and taxes the total. On invoices with many small lines you’ll see one or two cents drift. Match Odoo’s computation to Xero’s per-line method before import, or reconcile the small differences in a rounding account after.

Step 6: Post opening balances

Opening balances come from the trial balance at your cutover date. Post one journal entry debiting every asset balance, crediting every liability and equity balance, with the offset going to an Opening Balance Equity account. If your books are in order, that journal balances to zero. If it doesn’t, you have a Xero reconciliation problem — don’t migrate it, fix it first.

Bank account opening balances deserve special attention: the balance on the Odoo side must match the closing balance in Xero at 23:59 on cutover day, accounting for in-flight transactions that cleared the bank but hadn’t posted to Xero. Pull the bank feed right up to cutover in Xero, reconcile, then take the balance.

Step 7: Bank feeds and ABA payments

Set up Odoo’s bank feed with your bank from day one — not after go-live. ANZ, NAB, CBA, and Westpac all connect via Odoo’s bank statement import or via third-party aggregators; the exact method depends on whether your bank supports CDR (Consumer Data Right) open banking yet. For most SMEs, daily CSV or MT940 import works reliably.

ABA file generation — the standard Australian batch payment format — needs configuring before your first payment run. Each bank expects a slightly different user ID and APCA identifier in the ABA header. Get the codes from your bank’s corporate internet banking portal, not from Xero’s stored version, which is often stale.

Step 8: Xero-specific gotchas

A handful of Xero quirks will bite if you don’t plan for them. Each one has caught an in-flight migration we’ve inherited from another partner.

Payment allocations

Xero allows a single payment to part-allocate across multiple invoices in ways that don’t always round-trip through its own export. Reconcile the open-AR ageing between Xero and Odoo before go-live; any gap is almost always an allocation issue. Fix the allocations in Xero first, re-export, and re-import — never patch the mismatch in Odoo after the fact.

Prepayments and overpayments

These sit in Xero as a special transaction type. In Odoo they become either credit notes or unreconciled bank journal lines — decide which convention fits your business and migrate consistently. Mixing the two across a customer’s history makes AR statements confusing and refund processing error-prone.

Manual journals with tracking categories

Tracking categories don’t export cleanly in Xero’s standard journal export. Run the Journal Report filtered by each tracking category to capture the full picture, then decide whether those tracking values become Odoo analytic tags, warehouses, cost centres, or departments — the choice shapes reporting for years afterwards.

Recurring invoices

Xero’s repeating invoice templates have no export path. You’ll need to list every template before cutover and rebuild it manually in Odoo’s recurring-invoice or subscription module. The common miss is discovering a dormant quarterly template on the first day of the new quarter after go-live.

Payroll and STP Phase 2

If you’re using Xero Payroll, you’re moving payroll too. Most Australian Odoo implementations pair with Employment Hero for STP Phase 2 reporting and award interpretation, syncing back to Odoo for GL postings. Cut over payroll on the first day of a pay period, never mid-pay — splitting a single pay run across two systems creates STP reconciliation headaches the ATO doesn’t forgive.

Super fund IDs

SuperStream USI and SPIN values in Xero don’t always carry across cleanly. Validate every super fund against the ATO’s Fund Validation Service before the first super batch in Odoo. A single wrong USI fails the whole batch, and catching it after the first fortnight costs you the re-lodgement effort plus the embarrassment with staff.

Step 9: Test, parallel-check, go live

The week before go-live, run parallel entries for three to five days — enter the same transactions in both systems, reconcile daily. You’re not looking for Odoo to match Xero to the cent; you’re looking for every variance to have a known cause. Common causes at this stage are rounding (fine), timing on bank feeds (fine), and tax-code mapping errors (fix immediately).

Hypercare for the first fortnight after go-live: a named consultant on call, daily check-ins, and a freeze on non-essential configuration changes. The golden rule — don’t start customising Odoo until your finance team has closed one clean month in it.

Migration timeline and cost

A straightforward Xero-to-Odoo migration for a 10-to-25-user business runs four to eight weeks from discovery to go-live and costs $20,000 to $45,000 in partner fees, plus Odoo licence fees from about $34 AUD per user per month for all apps. Businesses with heavy inventory, manufacturing, or field-service operations sit in the $45,000 to $90,000 range and take two to three months because the real work is modelling the operational side, not the accounts. The accounting migration itself is rarely the bottleneck — it’s the parts of your business Xero couldn’t see.

You can see our implementation method for how we phase the work, or the migration paths we support if you’re moving from something other than Xero.


If you’re weighing up a Xero-to-Odoo move, we run free discovery calls for Australian businesses — we’ll map your current stack, the triggers that are pushing you off Xero, and what a realistic cutover looks like against your BAS cycle. Arrange a discovery call and we’ll give you an honest assessment before you commit a dollar.

Frequently asked.

How long does a Xero to Odoo migration take?

Four to eight weeks for most small-to-medium businesses with standard accounting plus CRM, sales, and light inventory. Add two to four weeks for manufacturing, field service, or multi-warehouse configurations. Full mid-market migrations with custom workflows run three to six months end to end.

Can I run Xero and Odoo in parallel during migration?

For a short parallel window of three to five days before go-live, yes — it's the standard acceptance test. Running both permanently is a different question and usually a mistake: you end up reconciling two ledgers, paying two licence fees, and confusing your staff. If you need a reason to keep Xero read-only post-cutover, archive it for historical audit rather than running it live.

What does a Xero to Odoo migration cost in Australia?

Partner fees typically run $20,000 to $45,000 for small-to-medium businesses and $45,000 to $90,000 for mid-market with manufacturing or field service. Odoo licensing starts at approximately $34 AUD per user per month for all apps, billed annually. Most businesses recover the partner fee in year one through retired SaaS tools and reduced reconciliation time.

Do I need to migrate all my historical data from Xero?

No. The ATO accepts the Xero archive as source records for audit purposes, and most businesses only bring across open transactions plus opening balances at cutover. Historical GL detail can come across as summary journal entries if you want it queryable in Odoo, but it's rarely worth the cost of loading.

What happens to BAS lodgement during the migration?

Finish your current BAS period in Xero and lodge it from there; start the next period in Odoo. Cutover on the first day of a new BAS period to avoid splitting one quarter across two systems. Odoo's BAS report (Types A, C, D) generates directly for ATO lodgement once the Australian localisation is configured properly.