Skip to content

Xero integration

Liminal connects to Xero Accounting through hosted OAuth on vireondynamics.com — users never create their own Xero app or paste client secrets into .env.

  1. Run Liminal web UI (liminal web or npm run web:dev).
  2. Settings → Integrations → Xero → Connect.
  3. Complete Xero consent in the browser tab.
  4. Close the tab when you see Connected — tokens are stored under ~/.liminal/oauth/xero/.

Or ask the agent: connect_provider({ provider: "xero" }) after OAuth is on disk.

Read vs write

  • Read + write (default): full accounting toolset — list/get org settings, invoices, bills, contacts, payments, bank transactions, journals, and financial reports; create/update drafts (writes are approval-gated).
  • Read only: granular read scopes — reconnect to change mode.

After upgrading Liminal (or if tools return HTTP 401 AuthorizationUnsuccessful on payments, bank, journals, or reports): Disconnect Xero in Settings → Integrations, then Connect again with Read + write. OAuth tokens keep the scopes granted at connect time — refresh does not add new ones. The hosted connect site must also be deployed with the full granular scope list.

Process receipts (guided preset)

A fixed workflow — not open-ended chat — for supplier receipts → DRAFT bills in Xero:

  1. Attach one or more receipt images (paste, drop, or file picker).
  2. Optional note in the composer (e.g. fuel receipt).
  3. Start via Process receipts (web/desktop composer) or slash: /receipt, /receipts, /process-receipts [note]. Type / in the composer for tab-completion of all slash commands (/help lists them).

The harness activates the xero family and injects the recipe: find/create contact → suggest purchase lines → xero_duplicate_invoice_checkxero_create_bill (DRAFT) → xero_upload_attachment (source file required) → plain-language summary. Bank accounts are listed for context; this preset always creates a draft bill (not spend-money) unless you ask otherwise in chat.

Agent tools

Activate the xero family if lazy loading is on: activate_tool_family({ family: "xero" }).

Disable REST tools with AGENT_XERO_REST=0.

Organisation & settings

ToolPurpose
xero_list_organisationsLinked Xero orgs (tenant ids)
xero_get_organisationOrg profile, currency, financial year
xero_list_accountsChart of accounts
xero_get_accountOne account by GUID
xero_list_tax_ratesTax / GST codes
xero_list_tracking_categoriesTracking dimensions

Discovery (use before creates)

ToolPurpose
xero_find_contactSearch contacts by name/email
xero_list_bank_accountsBank AccountIDs for payments & bank txns
xero_suggest_line_itemDefault AccountCode + TaxType for sales/purchase lines

Invoices & AR/AP

ToolPurpose
xero_list_invoicesList invoices and bills
xero_get_invoiceFetch one by GUID
xero_create_invoiceCreate ACCREC sales invoice (approval)
xero_create_billCreate ACCPAY supplier bill (approval)
xero_set_invoice_statusApprove/void (minimal payload)
xero_update_invoiceUpdate lines/dates (not status)
xero_authorise_and_email_invoiceApprove + email in one step (approval)
xero_record_invoice_paymentPay invoice/bill (defaults to AmountDue)
xero_quote_to_invoiceConvert quote → invoice (approval)
xero_po_to_billConvert PO → supplier bill (approval)
xero_email_invoiceEmail authorised invoice (approval)
xero_list_credit_notesCredit notes
xero_create_credit_noteCreate credit note (approval)
xero_list_purchase_ordersPurchase orders
xero_list_quotesSales quotes
xero_list_itemsInventory / service items
xero_get_item / xero_create_item / xero_update_itemItem catalog

Contacts

ToolPurpose
xero_list_contactsCustomers/suppliers
xero_get_contactOne contact by GUID
xero_create_contactCreate contact (approval)
xero_update_contactUpdate contact (approval)

Quotes, POs, credit notes (lifecycle)

ToolPurpose
xero_set_quote_status / xero_update_quoteQuote status & edits
xero_set_purchase_order_status / xero_update_purchase_orderPO status & edits
xero_set_credit_note_status / xero_update_credit_noteCredit note status & edits
xero_allocate_credit_noteApply credit note to invoice/bill

Cash & journals

ToolPurpose
xero_list_paymentsPayments on invoices
xero_get_payment / xero_delete_paymentFetch or void a payment
xero_create_paymentRecord payment (approval)
xero_allocate_overpayment / xero_allocate_prepaymentApply unallocated cash
xero_list_bank_transactionsSpent/received money
xero_create_bank_transactionCreate bank txn (approval)
xero_list_manual_journalsManual journals
xero_create_manual_journalCreate journal (approval)

Reports

ToolPurpose
xero_report_profit_and_lossP&L
xero_report_balance_sheetBalance sheet
xero_report_trial_balanceTrial balance
xero_report_aged_receivablesWho owes you
xero_report_aged_payablesWhat you owe
xero_report_bank_summaryBank balances
xero_report_executive_summaryDashboard summary
xero_report_tax_summaryGST / tax summary (BAS prep)

Pass fromDate, toDate, or date (YYYY-MM-DD) where applicable.

Attachments

ToolPurpose
xero_list_attachmentsList files on invoice/bill/PO/quote/etc.
xero_get_attachmentDownload by file name (save_path or base64)
xero_upload_attachmentUpload PDF/image from workspace path or base64 (approval)
xero_delete_attachmentRemove attachment (approval)

parent_type: Invoices, CreditNotes, PurchaseOrders, Quotes, BankTransactions, Contacts, Accounts, ManualJournals.

Reconciliation & batch

ToolPurpose
xero_list_batch_paymentsPayment runs
xero_create_batch_paymentPay multiple invoices from one bank account (approval)
xero_list_repeating_invoicesRecurring invoice templates
xero_get_repeating_invoiceOne template by GUID
xero_create_repeating_invoiceCreate template (approval)
xero_list_linked_transactionsBank line ↔ document links
xero_create_linked_transactionCreate reconciliation link (approval)
xero_list_overpayments / xero_get_overpaymentCustomer/supplier overpayments
xero_list_prepayments / xero_get_prepaymentPrepayments
xero_list_bank_transfersInter-account transfers
xero_create_bank_transferMove cash between bank accounts (approval)

Quotes & purchase orders (create)

ToolPurpose
xero_get_quote / xero_create_quoteFetch or draft a quote
xero_get_purchase_order / xero_create_purchase_orderFetch or draft a PO

Settings (extra)

ToolPurpose
xero_list_branding_themesInvoice branding
xero_list_currenciesOrg currencies

Escape hatch

ToolPurpose
xero_requestRaw Accounting API call for uncovered endpoints (approval-gated)

Operator setup (Vireon — one time)

Register a Web app at developer.xero.com:

FieldValue
App nameLiminal AI
Integration typeWeb app
AI training on Xero data?No
Security requirementsYes
Company URLhttps://www.vireondynamics.com/liminal
Redirect URIhttps://www.vireondynamics.com/connect/xero/callback (must include /callback — not /connect/xero alone)

Add to Vercel env for vireondynamics-website (not the user's .env):

env
XERO_OAUTH_CLIENT_ID=...
XERO_OAUTH_CLIENT_SECRET=...
INTEGRATION_OAUTH_STATE_SECRET=...   # optional HMAC for OAuth state; defaults to client secret

Architecture

text
Liminal (local) → opens vireondynamics.com/connect/xero
                → Xero consent
                → site /connect/xero/callback (token exchange)
                → POST tokens to localhost:3001/api/integrations/oauth/handoff
                → ~/.liminal/oauth/xero/<account>.json (encrypted)

Same hosted handoff pattern as Vireon license connect (/connect/harness).

Phase 3 — GL journals, Files, Projects, Payroll

Requires reconnect after upgrade (new OAuth scopes: accounting.journals.read, files, projects, payroll.*).

General ledger journals

ToolPurpose
xero_list_journalsPosted GL journal lines
xero_get_journalOne journal by JournalID
xero_get_journal_by_numberOne journal by number

Files cabinet (org-wide)

ToolPurpose
xero_files_list / xero_files_getBrowse file metadata
xero_files_downloadSave to workspace or base64
xero_files_upload / xero_files_deleteManage files (approval on write)
xero_files_list_folders / xero_files_get_folderFolder structure
xero_files_list_associationsLinks to invoices, contacts, etc.

Projects (job costing / time)

ToolPurpose
xero_list_projects / xero_get_projectProjects with WIP totals
xero_create_project / xero_update_projectProject lifecycle
xero_list_project_tasks / xero_create_project_taskBillable tasks
xero_list_project_time_entries / xero_create_project_time_entryTime logging
xero_list_project_usersUsers assignable to time

Payroll (AU v1.0 / UK+NZ v2.0)

ToolPurpose
xero_payroll_regionDetect AU vs UK vs NZ from org country
xero_list_payroll_employees / xero_get_payroll_employeeStaff records
xero_list_payroll_payruns / xero_get_payroll_payrunPay run status
xero_list_payroll_timesheets / xero_get_payroll_timesheetTimesheets
xero_get_payroll_settingsPayroll org config
xero_get_payroll_payslipPayslip detail
xero_create_payroll_timesheetCreate draft timesheet (approval)

Pass payroll_region (AU | UK | NZ) to override auto-detection.

Bank feeds (not available)

xero_bank_feeds_info — direct bank feed import requires Xero partner approval and is not in hosted OAuth. Use bank transactions + linked transactions instead.

Phase 3.5 — composites, payroll writes, accounting mutations

Composites

ToolPurpose
xero_upsert_contactFind by email/name → update or create
xero_project_to_invoiceBill unbilled project time (grouped by task)
xero_month_end_closeP&L, BS, trial, aged AR/AP, bank + close checklist
xero_duplicate_invoice_checkMatch reference/number/amount before creating

Payroll writes

ToolPurpose
xero_create_payroll_payrunDraft pay run for calendar period
xero_update_payroll_payrunPost/finalise pay run
xero_update_payroll_employeeUpdate employee record
xero_update_payroll_timesheetCorrect timesheet lines

Accounting mutations

ToolPurpose
xero_update_bank_transaction / xero_void_bank_transactionFix or remove bank lines
xero_create_account / xero_update_accountChart of accounts
xero_create_tracking_category / xero_create_tracking_option / xero_update_tracking_categoryTracking dimensions
xero_list_expense_claims / xero_get_expense_claim / xero_create_expense_claimStaff reimbursements
xero_update_repeating_invoice / xero_delete_repeating_invoiceRecurring billing lifecycle
xero_send_invoice_reminderPayment reminder email
xero_list_budgets / xero_get_budgetBudget vs actual

Troubleshooting

  • "Harness rejected handoff" / "Failed to fetch" / CSP form-action — Liminal must be running (liminal web or desktop) before Connect. The site POSTs tokens to loopback (127.0.0.1 or localhost, dynamic port on desktop). Update vireondynamics.com if you see form-action 'self' blocked.
  • No organisation — reconnect; the harness stores the first linked tenant from GET /connections.
  • 403 on API calls — wrong tenant or missing scope; revoke in Integrations and reconnect with the mode you need.
  • invalid_scope on Xero sign-in — Post–2026-03-02 apps need granular scopes (default). Connect with Full accounting scopes and Extended APIs unchecked first. Never request accounting.budgets (write) or accounting.journals.read on new apps — use accounting.budgets.read only. Pre–2026-03-02 apps: set AGENT_XERO_OAUTH_SCOPE_STYLE=legacy and XERO_OAUTH_SCOPE_STYLE=legacy on Vercel.
  • Supabase “invalid flow state” after Xero consent — Xero ?code= was misrouted to /auth/callback (especially when the redirect URI omitted /callback). Deploy latest vireondynamics.com connect middleware, confirm the Xero app redirect URI ends with /connect/xero/callback, clear cookies for vireondynamics.com, retry in a private window.

Liminal AI · Beta docs (v0.1.2) · Marketing: vireondynamics.com/liminal · Compare: vireondynamics.com/liminal/compare