Xero and Zuora integration
Xero runs your general ledger and accounts. Zuora runs your subscription billing and order-to-cash. Connecting the two keeps your revenue recognized and accounts reconciled without re-keying. Invoices generated by Zuora after each billing run post automatically into Xero, mapped to the correct revenue and AR accounts. Payments received in Zuora update cash accounts in Xero in real time. ml-connector handles the multi-region Zuora URLs, OAuth2 on both sides, and the full record flow from billing to accounting.
What moves between them
Invoices created in Zuora post automatically into Xero's general ledger when the Zuora invoice is marked posted. Payments received in Zuora flow into Xero cash and AR accounts in real time. Both directions use the same account and tracking category mappings so revenue recognition and cash reconciliation are accurate from the start. The sync runs on a cadence tied to your billing cycle rather than waiting for individual webhooks, ensuring batch invoice runs post completely into Xero before the next cycle begins.
How ml-connector handles it
ml-connector stores Xero OAuth2 credentials and Zuora's multi-region base URL and client credentials, refreshing each token when a request returns 401 or after the token expiry window. It registers a webhook endpoint with both systems and validates incoming Zuora Callout Notifications with HMAC-SHA256 signatures, discarding invalid or replay requests. When a Zuora invoice or payment arrives, ml-connector maps the Zuora account, product, and amount to the pre-configured Xero accounts and tracking categories, then posts a manual journal or payment into Xero's general ledger. Because Zuora webhook payloads are metadata-only, ml-connector calls back to Zuora to fetch the full invoice or payment record before posting. Invoices and payments are deduplicated by their Zuora identifiers so accidental replays do not create duplicate GL entries. Xero's 30-minute token expiry is handled transparently; failed requests that need a new token are retried without blocking the pipeline. The full trace of every record, from Zuora receipt through Xero GL posting, is stored in the audit log.
A real-world example
A SaaS company with 200 customers runs Zuora for subscription management and Xero for accounting. Before the integration, the finance team received Zuora invoice reports each billing cycle and manually entered revenue and AR transactions into Xero, a process that took two to four hours and frequently introduced errors. With Zuora and Xero connected, subscription invoices and payments flow automatically into Xero's general ledger, allocated to the correct revenue and AR accounts. The finance team now spends the time saved on month-end reconciliation instead of transaction entry, and the trial balance balances the same day billing runs complete.
What you can do
- Post Zuora subscription invoices into Xero's general ledger automatically, mapped to the correct revenue accounts and tracking categories.
- Sync Zuora customer payments into Xero cash and AR accounts in real time, keeping your trial balance current.
- Handle multi-region Zuora URLs and client credentials, and refresh OAuth2 tokens on both sides automatically.
- Deduplicate Zuora invoices and payments by identifier, so webhook retries and re-deliveries do not create duplicate GL entries.
- Validate Zuora Callout Notification signatures with HMAC-SHA256 and retry failed Xero postings with a full audit trail.
Questions
- Which direction does data flow between Xero and Zuora?
- The main flow is Zuora into Xero. Subscription invoices and payments move from Zuora into Xero's general ledger, mapped to revenue and AR accounts. Reference data such as account mappings and tracking categories is configured once and reused for every invoice and payment that flows through.
- How does the integration handle Zuora's multi-region URLs and webhook limitations?
- ml-connector stores the full Zuora base URL per customer, since each tenant has a region-specific endpoint. It registers a webhook endpoint with Zuora and validates incoming Callout Notifications with HMAC-SHA256 signatures. Because Zuora webhook payloads contain only object IDs, ml-connector calls back to Zuora to fetch the full invoice or payment record before posting to Xero.
- What happens if an OAuth2 token expires or a Zuora payment webhook is retried?
- ml-connector refreshes Xero's 30-minute access tokens and Zuora's one-hour tokens transparently, retrying the request without blocking the pipeline. Duplicate payments and invoices are blocked by deduplication on the Zuora identifier, so webhook retries and platform retries do not create duplicate GL entries.
Related integrations
More Xero integrations
Other systems that connect to Zuora
Connect Xero and Zuora
Free to use. Add your credentials, ping your real systems, and see if we fit.
Get started