Skip to main content

Xero Setup for BillingOne

This runbook walks you through connecting Xero, preparing your catalog and clients, and pushing your first generated invoice. Follow the steps in order — each later step depends on the ones before it.

Primary path: Use the in-app setup wizard on the billing dashboard or Settings → Integrations. The wizard guides OAuth, contact sync, client mapping, and catalog import in one flow.

Navigation: BillingOne → Dashboard (setup checklist) or SettingsIntegrations


Before You Start

You will need:

  • A Xero organisation with customer contacts, items, and revenue accounts already configured
  • Admin or Finance access in BillingOne (integration connect requires appropriate permissions)
  • PanelOne clients that correspond to your billable customers

Tip: Keep using your existing Xero organisation. BillingOne generates new invoices and pushes them to Xero — historical invoices stay in Xero and are not duplicated.


Step 1: Connect Xero (in-app wizard)

  1. Open BillingOne → Dashboard and expand the Xero setup checklist, or go to Settings → Integrations.
  2. Find Xero under Billing Integrations and click Configure (or Connect in the setup wizard).
  3. Complete the OAuth authorization flow — you will be redirected to Xero to grant access.
  4. When you return to BillingOne, confirm Xero shows as Connected.

The wizard uses a platform-owned OAuth app by default — MSPs do not register their own Xero developer app unless they choose Bring your own app (BYO) in the setup wizard. OAuth tokens are stored per organisation after authorization.

BYO OAuth (optional)

MSPs with their own Xero or QuickBooks developer app can select Bring your own app on the welcome step of the setup wizard (or in Configure on an existing integration):

  1. Create a developer app at Xero Developer or the Intuit Developer Portal.
  2. Register the PanelOne redirect URI shown in the wizard ({SUPABASE_URL}/functions/v1/xero-oauth-callback or quickbooks-oauth-callback).
  3. Save Client ID and Client Secret in BYO mode, then complete OAuth.

Connection mode is stored in integrations.config.accounting_oauth_mode (platform or byo). BYO credentials are encrypted in integration_secrets (xero_client_id, xero_client_secret, or QuickBooks equivalents).

Once connected, BillingOne can sync invoice snapshots, import your Xero catalog, and push generated invoices back to Xero.


Step 2: Sync Xero Contacts

  1. On the Integrations tab, open Client Mappings (or click Map Xero contacts to clients on the Xero card).
  2. Click Sync contacts from Xero to pull customer contacts into BillingOne.
  3. Wait for the sync to finish — you should see a count of contacts imported.

Contacts are cached locally so you can map them without returning to Xero for every client.


Step 3: Map Clients to Xero Contacts

Every PanelOne client that receives a pushed invoice must be linked to a Xero contact.

  1. In the Map Xero contacts to clients dialog, review the suggested matches (exact name matches are applied automatically).
  2. For unmatched or fuzzy matches, select the correct PanelOne client from the dropdown.
  3. Click Save mappings.

You can also set xero_contact_id on individual clients from Clients → Edit client → Billing integration mappings, but the bulk mapping dialog is faster for initial onboarding.

Push failure hint — missing_xero_contact: If a push fails with this hint, the invoice's client has no Xero contact mapping. Return to Client Mappings and link that client before pushing again.


Step 4: Import the Catalog from Xero

  1. Open BillingOne → Catalog (sidebar).
  2. Click Import from Xero in the page header.
  3. Wait for the sync — BillingOne imports Xero items, accounts, and tax rates, then upserts catalog rows.

Import the catalog before building contract templates so line items resolve to the correct Xero item codes and GL accounts at invoice time.

For CSV or manual catalog rows (items not yet in Xero), see CSV Imports.


Step 5: Review Catalog GL Codes and Tax

After import, spot-check catalog rows before you attach them to contracts:

  1. On the Catalog page, open a row to edit (or review synced rows in the table).
  2. Confirm the default revenue account (GL code) is set — synced Xero items inherit account mappings where available.
  3. Confirm the Xero tax code (xero_tax_type) is correct for each sellable item.
  4. Fix any gaps on CSV or manual rows — they do not inherit Xero metadata until you assign account and tax codes.

Push failure hint — missing_account_code: If a push fails with this hint, BillingOne could not resolve a Xero sales/revenue account code for one or more lines. Re-import the Xero catalog (which syncs accounts), assign a default revenue account on affected catalog rows, or ensure your Xero organisation has at least one REVENUE/SALES account with a code.


Step 6: Add CSV or Manual Catalog Items (Optional)

Use this when you sell items in BillingOne that are not yet in Xero:

  1. On Catalog, click Import CSV or New catalog item.
  2. CSV rows become source: csv; manual rows become source: manual.
  3. Assign revenue account and tax codes on each row before using them on contracts.

See CSV Imports for column formats and headerless positional layout.


Step 7: Create Contract Templates

  1. Go to Contracts → Templates.
  2. Create a template that mirrors your standard agreement structure (e.g. per-device managed services, platform fee, labour block).
  3. Attach catalog items to template lines so generated invoices inherit correct codes and pricing.
  4. Save the template for reuse across clients.

Templates speed up onboarding when you rebuild agreements client-by-client or import from a PSA export.


Step 8: Configure Invoice Settings

  1. Open Settings → Integrations → Invoice Settings.
  2. Review and save:
SettingWhat it controls
Billing periodMonthly, quarterly, or annual generate cycle
Generate on dayDay of month for scheduled generation
Auto-generateWhether invoices are created on schedule
Include service contractsPull recurring contract lines into generated invoices
Include subscriptions / device countsPax8 and metered sources
Auto-push to XeroPush to Xero automatically after generation
Invoice prefixReference prefix for new invoice numbers
Invoice notesDefault footer text (payment terms, thank-you message, etc.)

Enable Auto-push to Xero only after you have validated a manual push for at least one pilot client.


Step 9: First Generate and Push

  1. Confirm active service contracts exist for pilot clients (with catalog-linked lines where possible).
  2. Open Generated invoices.
  3. Run a manual generate for the current period (or wait for auto-generate if enabled).
  4. Open a draft invoice and review line descriptions, quantities, tax, and totals.
  5. Issue the invoice, then click Push to Xero (unless auto-push is already enabled).
  6. Confirm the invoice appears in Xero with the expected contact, account codes, and tax types.

Compare the first BillingOne invoice against your last manual Xero invoice for each pilot client before rolling out to your full client base.


Platform admin: OAuth app registration

PanelOne operates a single platform-owned OAuth app per accounting provider. MSPs authorize their own Xero or QuickBooks organisation; tokens are stored per org in integration_secrets.

Platform operators configure Edge Function secrets and register redirect URIs once per PanelOne deployment.

Xero developer app

  1. Create an app at Xero Developer.

  2. Set OAuth 2.0 redirect URI to:

    {SUPABASE_URL}/functions/v1/xero-oauth-callback

    Example: https://abcdefghijklmnop.supabase.co/functions/v1/xero-oauth-callback

  3. Enable scopes: openid, profile, email, accounting.transactions, accounting.contacts.read, offline_access.

  4. Set Supabase Edge Function secrets:

    supabase secrets set XERO_CLIENT_ID=your_client_id
    supabase secrets set XERO_CLIENT_SECRET=your_client_secret
  5. Redeploy xero-auth and xero-oauth-callback.

  6. Confirm status in Admin → Settings → Integrations → Accounting OAuth apps.

QuickBooks Online developer app

  1. Create an app in the Intuit Developer Portal.

  2. Add Redirect URI:

    {SUPABASE_URL}/functions/v1/quickbooks-oauth-callback
  3. Set Supabase Edge Function secrets:

    supabase secrets set QUICKBOOKS_CLIENT_ID=your_client_id
    supabase secrets set QUICKBOOKS_CLIENT_SECRET=your_client_secret
  4. Redeploy quickbooks-auth and quickbooks-oauth-callback.

Replace {SUPABASE_URL} with your project URL from the Supabase dashboard (Settings → API).


Troubleshooting

OAuth connect fails immediately

SymptomLikely causeFix
"Platform not configured" / 503OAuth app secrets missing (platform mode)Platform admin: set XERO_CLIENT_ID / XERO_CLIENT_SECRET (or QBO equivalents) and redeploy; or MSP: switch to BYO mode and save your own app credentials
BYO credentials missingBYO mode selected but Client ID/Secret not savedSave BYO credentials on the integration and register the redirect URI in your developer app
Redirect error from Xero/IntuitRedirect URI mismatchRegister exact callback URL {SUPABASE_URL}/functions/v1/xero-oauth-callback or quickbooks-oauth-callback
Returns with xero_oauth=errorState expired or invalidRestart connect from Settings → Integrations; complete OAuth within 10 minutes
Multiple Xero tenantsOrg has several Xero companiesSelect the correct tenant when prompted after OAuth

Setup checklist stuck

SymptomFix
"Contacts synced" incompleteRun Sync contacts from Xero on Settings → Integrations → Client Mappings
"Clients mapped" incompleteMap contacts in the client mapping dialog or set xero_contact_id per client
"Catalog imported" incompleteOpen CatalogImport from Xero

Push failures

HintMeaningFix
missing_xero_contactClient is not mapped to a Xero contactSettings → Integrations → Client Mappings — link the client
missing_account_codeNo revenue account code on invoice linesRe-run Import from Xero on Catalog; set default revenue account on catalog rows
already_linkedInvoice was pushed beforeNormal — use force re-push only when intentionally replacing a Xero draft

QuickBooks Online (Parallel Path)

BillingOne supports QuickBooks Online as an alternative accounting provider. The onboarding flow is the same shape:

  1. Connect QuickBooks instead of (or alongside) Xero in Settings → Integrations (use the in-app wizard)
  2. Sync and map QBO customers to PanelOne clients
  3. Import from QuickBooks on the Catalog page
  4. Review QBO tax codes and revenue accounts on catalog rows
  5. Enable Auto-push to QBO in Invoice Settings
  6. Generate and Push to QuickBooks from Generated invoices

Only one accounting provider drives catalog sync UI at a time (whichever is connected/preferred). Do not connect both unless you understand which provider BillingOne uses for catalog and push on your organisation.


Next Steps

  • Billing ops verification — Manual smoke checklist for OAuth (platform/BYO), late-fee auto-push, statement cron, and COA push (internal runbook; not yet published in this help centre)
  • CSV Imports — Catalog and Gorelo contract CSV formats
  • Settings — All billing integrations and account options
  • Invoices — Tracking synced and generated invoices