ml-connector
XeroSnowflake

Xero and Snowflake integration

Xero runs your accounting records. Snowflake stores and queries your data. Connecting the two keeps a live copy of your invoices, payments, and contacts in Snowflake for reporting, analytics, and audit trails. New transactions in Xero flow automatically into Snowflake tables, and you can query the warehouse directly to answer questions about cash, AR aging, AP schedules, and customer or vendor trends without exporting to spreadsheets.

How Xero works

Xero Accounting API exposes contacts, invoices, purchase orders, payments, accounts, manual journals, bank transactions, tracking categories, and items through a REST API at https://api.xero.com/api.xro/2.0/. Authentication uses OAuth2 Authorization Code flow with 30-minute access tokens and 60-day refresh tokens (offline_access scope). Xero supports webhooks for Contact, Invoice, CreditNote, Payment, ManualJournal, PurchaseOrder, and BankTransaction CREATE and UPDATE events, though webhook payloads contain metadata only and require a follow-up GET request to fetch full record details. All requests require the Xero-tenant-id header to target the correct organization. Xero rate limits at 5 concurrent calls and 60 requests per minute per tenant.

How Snowflake works

Snowflake is a cloud data warehouse accessed via REST API at https://<account_identifier>.snowflakecomputing.com/api/v2/statements. Authentication uses Key Pair Authentication (RSA private key with JWT) for secure server-to-server integration. Snowflake is pull-only; there are no webhooks for external endpoints. It uses SQL-based queries to manage data, with native change detection options including timestamp watermarks (SELECT WHERE updated_at > last_sync) or Snowflake Streams for capturing inserts, updates, and deletes. All SQL statements execute asynchronously via the SQL API. Snowflake requires a warehouse with AUTO_RESUME enabled and uses uppercase unquoted identifiers by default.

What moves between them

Invoices, payments, and contacts flow from Xero into Snowflake. When Xero sends a webhook event (CREATE or UPDATE), ml-connector fetches the full record from Xero and writes it into a Snowflake table. The sync captures the transaction date, account coding, amounts, and descriptions, so your Snowflake tables stay synchronized with Xero's current state. Deleted records are not synced. Contact and vendor data can also be pulled on a schedule for dimension tables. Because Xero webhooks include only metadata, ml-connector performs a follow-up GET request to retrieve the complete record before writing to Snowflake.

How ml-connector handles it

ml-connector stores your Xero OAuth2 credentials and Snowflake private key encrypted, then listens for Xero webhook events. When an invoice, payment, or contact event arrives, ml-connector validates the webhook signature using Xero's signing key, fetches the full record from Xero (respecting the per-tenant Xero-tenant-id header), transforms the data to match your Snowflake table schema, and writes it via SQL INSERT or UPDATE. For Snowflake, ml-connector uses Key Pair Authentication with JWT, which avoids long-lived bearer tokens. Because Snowflake case-folds unquoted identifiers to uppercase, ml-connector quotes column names consistently so your schema remains predictable. If a Snowflake write fails due to rate limits (HTTP 429), ml-connector backs off and retries. Xero's 5-concurrent-call limit is respected by queuing webhook follow-ups, and the 60-request-per-minute per-tenant rate limit is tracked across all active flows. Transaction deltas can also be detected via timestamp watermarks in Snowflake (SELECT WHERE updated_at > last_sync) if you prefer polling to webhooks.

A real-world example

A mid-sized SaaS company uses Xero for accounting across three business units. The finance team needs real-time visibility into cash flow, AR aging, and AP schedules for monthly reporting and forecasting. Previously, they exported monthly invoices and payments from Xero to CSV, loaded them into Excel, and wrote custom SQL queries in a BI tool. With Xero and Snowflake connected, every invoice and payment lands in Snowflake automatically within seconds of creation. The team runs SQL queries directly against live data, builds dashboards from up-to-date tables, and replaces the monthly export ritual with a scheduled refresh. The audit trail in Snowflake shows every transaction state change, and the warehouse retains historical snapshots for year-end reconciliation without manual intervention.

What you can do

  • Sync Xero invoices, payments, and credit notes into Snowflake tables on webhook events or a scheduled cadence.
  • Authenticate Xero with OAuth2 and Snowflake with secure Key Pair Authentication, handling credential encryption and token refresh automatically.
  • Validate Xero webhook signatures and fetch full record details for every CREATE and UPDATE event before writing to Snowflake.
  • Maintain historical snapshots in Snowflake by storing every state change, enabling audit trails and point-in-time queries for reconciliation.
  • Query live Xero data directly from Snowflake using SQL, eliminating manual exports and enabling real-time reporting and analytics.

Questions

Why does ml-connector fetch the full record from Xero after receiving a webhook?
Xero webhooks include resource metadata only (the ID, date, and type), not the complete transaction details. ml-connector makes a follow-up GET request to retrieve the full invoice, payment, or contact record (amounts, account codes, descriptions) before writing it to Snowflake. This ensures your warehouse has complete, queryable data.
How does ml-connector handle Xero's per-tenant authentication and rate limits?
ml-connector stores the Xero OAuth2 credentials encrypted and includes the Xero-tenant-id header on every API request to target the correct organization. It tracks the 60-request-per-minute rate limit across all flows for that tenant, queues webhook follow-ups to stay within the 5-concurrent-call limit, and refreshes the OAuth2 access token when it expires (every 30 minutes).
Can I query historical transaction data from Snowflake if a record is updated in Xero?
Yes. ml-connector writes every state change (CREATE and UPDATE events) into Snowflake, creating a timestamped audit trail. You can use SQL queries like 'SELECT WHERE transaction_id = X ORDER BY updated_at' to see the full history of any invoice or payment, enabling reconciliation and point-in-time analysis without re-keying or manual tracking.

Related integrations

Connect Xero and Snowflake

Free to use. Add your credentials, ping your real systems, and see if we fit.

Get started