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 Settings → Integrations
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)
- Open BillingOne → Dashboard and expand the Xero setup checklist, or go to Settings → Integrations.
- Find Xero under Billing Integrations and click Configure (or Connect in the setup wizard).
- Complete the OAuth authorization flow — you will be redirected to Xero to grant access.
- 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):
- Create a developer app at Xero Developer or the Intuit Developer Portal.
- Register the PanelOne redirect URI shown in the wizard (
{SUPABASE_URL}/functions/v1/xero-oauth-callbackorquickbooks-oauth-callback). - 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
- On the Integrations tab, open Client Mappings (or click Map Xero contacts to clients on the Xero card).
- Click Sync contacts from Xero to pull customer contacts into BillingOne.
- 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.
- In the Map Xero contacts to clients dialog, review the suggested matches (exact name matches are applied automatically).
- For unmatched or fuzzy matches, select the correct PanelOne client from the dropdown.
- 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
- Open BillingOne → Catalog (sidebar).
- Click Import from Xero in the page header.
- 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:
- On the Catalog page, open a row to edit (or review synced rows in the table).
- Confirm the default revenue account (GL code) is set — synced Xero items inherit account mappings where available.
- Confirm the Xero tax code (
xero_tax_type) is correct for each sellable item. - 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:
- On Catalog, click Import CSV or New catalog item.
- CSV rows become
source: csv; manual rows becomesource: manual. - 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
- Go to Contracts → Templates.
- Create a template that mirrors your standard agreement structure (e.g. per-device managed services, platform fee, labour block).
- Attach catalog items to template lines so generated invoices inherit correct codes and pricing.
- 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
- Open Settings → Integrations → Invoice Settings.
- Review and save:
| Setting | What it controls |
|---|---|
| Billing period | Monthly, quarterly, or annual generate cycle |
| Generate on day | Day of month for scheduled generation |
| Auto-generate | Whether invoices are created on schedule |
| Include service contracts | Pull recurring contract lines into generated invoices |
| Include subscriptions / device counts | Pax8 and metered sources |
| Auto-push to Xero | Push to Xero automatically after generation |
| Invoice prefix | Reference prefix for new invoice numbers |
| Invoice notes | Default 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
- Confirm active service contracts exist for pilot clients (with catalog-linked lines where possible).
- Open Generated invoices.
- Run a manual generate for the current period (or wait for auto-generate if enabled).
- Open a draft invoice and review line descriptions, quantities, tax, and totals.
- Issue the invoice, then click Push to Xero (unless auto-push is already enabled).
- 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
-
Create an app at Xero Developer.
-
Set OAuth 2.0 redirect URI to:
{SUPABASE_URL}/functions/v1/xero-oauth-callbackExample:
https://abcdefghijklmnop.supabase.co/functions/v1/xero-oauth-callback -
Enable scopes:
openid,profile,email,accounting.transactions,accounting.contacts.read,offline_access. -
Set Supabase Edge Function secrets:
supabase secrets set XERO_CLIENT_ID=your_client_id
supabase secrets set XERO_CLIENT_SECRET=your_client_secret -
Redeploy
xero-authandxero-oauth-callback. -
Confirm status in Admin → Settings → Integrations → Accounting OAuth apps.
QuickBooks Online developer app
-
Create an app in the Intuit Developer Portal.
-
Add Redirect URI:
{SUPABASE_URL}/functions/v1/quickbooks-oauth-callback -
Set Supabase Edge Function secrets:
supabase secrets set QUICKBOOKS_CLIENT_ID=your_client_id
supabase secrets set QUICKBOOKS_CLIENT_SECRET=your_client_secret -
Redeploy
quickbooks-authandquickbooks-oauth-callback.
Replace {SUPABASE_URL} with your project URL from the Supabase dashboard (Settings → API).
Troubleshooting
OAuth connect fails immediately
| Symptom | Likely cause | Fix |
|---|---|---|
| "Platform not configured" / 503 | OAuth 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 missing | BYO mode selected but Client ID/Secret not saved | Save BYO credentials on the integration and register the redirect URI in your developer app |
| Redirect error from Xero/Intuit | Redirect URI mismatch | Register exact callback URL {SUPABASE_URL}/functions/v1/xero-oauth-callback or quickbooks-oauth-callback |
Returns with xero_oauth=error | State expired or invalid | Restart connect from Settings → Integrations; complete OAuth within 10 minutes |
| Multiple Xero tenants | Org has several Xero companies | Select the correct tenant when prompted after OAuth |
Setup checklist stuck
| Symptom | Fix |
|---|---|
| "Contacts synced" incomplete | Run Sync contacts from Xero on Settings → Integrations → Client Mappings |
| "Clients mapped" incomplete | Map contacts in the client mapping dialog or set xero_contact_id per client |
| "Catalog imported" incomplete | Open Catalog → Import from Xero |
Push failures
| Hint | Meaning | Fix |
|---|---|---|
missing_xero_contact | Client is not mapped to a Xero contact | Settings → Integrations → Client Mappings — link the client |
missing_account_code | No revenue account code on invoice lines | Re-run Import from Xero on Catalog; set default revenue account on catalog rows |
already_linked | Invoice was pushed before | Normal — 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:
- Connect QuickBooks instead of (or alongside) Xero in Settings → Integrations (use the in-app wizard)
- Sync and map QBO customers to PanelOne clients
- Import from QuickBooks on the Catalog page
- Review QBO tax codes and revenue accounts on catalog rows
- Enable Auto-push to QBO in Invoice Settings
- 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