ml-connector
Wave AccountingZuora

Wave Accounting and Zuora integration

Wave Accounting runs invoicing and customer accounting for small businesses. Zuora runs subscription billing and order-to-cash. Connecting the two synchronizes your customer records and invoices from Wave into Zuora so your subscription billing reflects your accounting source of truth. New customers created in Wave flow into Zuora as accounts, and invoices trigger corresponding Zuora orders and invoices aligned with the same customers. ml-connector bridges the GraphQL and REST APIs and keeps both systems in sync.

How Wave Accounting works

Wave Accounting exposes customers, invoices, products, accounts, transactions, and vendors through a GraphQL API at https://gql.waveapps.com/graphql/public. Authentication uses OAuth 2.0 Authorization Code Flow with 2-hour access tokens and refresh tokens. Wave supports webhooks for invoice events (created, updated, paid), payment events, and customer changes. Webhook delivery is retried by Wave if not acknowledged with HTTP 200, and webhook signatures use HMAC-SHA256 for verification. The connected business must have an active Wave Pro subscription to use the API.

How Zuora works

Zuora exposes accounts, subscriptions, invoices, payments, and payment methods through a REST API with a multi-region design, so each customer's tenant base URL must be captured at setup (rest.zuora.com, rest.apisandbox.zuora.com, or regional variants). Authentication uses OAuth 2.0 Client Credentials with 1-hour token expiry. Zuora supports webhooks called Callout Notifications for billing, payment, subscription, and account events, with HMAC-SHA256 signatures and a fixed 25-second timeout. Payment notifications fire only for electronic payments, not manual or external entries. Zuora enforces strict rate limits of 50,000 requests per minute in production.

What moves between them

Wave is the source of truth for accounting. When a new customer is created in Wave, ml-connector reads the customer record and creates a matching account in Zuora. When an invoice is created or paid in Wave, ml-connector syncs the invoice to Zuora as an order and posts corresponding payment records if payment is recorded in Wave. The main flow is customer and invoice data from Wave into Zuora. Reference data such as products is aligned so Zuora orders map to the same products in Wave.

How ml-connector handles it

ml-connector stores Wave OAuth tokens and refresh them as needed when calls return 401. It polls Wave GraphQL for customer and invoice data, and listens for Wave webhooks on invoice.created, invoice.updated, invoice.paid, and customer events. On the Zuora side, ml-connector determines the customer's region and base URL, obtains an OAuth token via Client Credentials, and posts the customer as a Zuora account and the invoice as a Zuora order. Because Zuora payment notifications fire only for electronic payments, ml-connector tracks Wave payment records separately and creates Zuora payment entries when Wave marks an invoice as paid. Webhook signatures on both sides are verified with HMAC-SHA256 before processing. The 25-second Zuora webhook timeout is observed when acknowledging Callout Notifications, so heavy processing is deferred to background jobs. Every customer and invoice transformation is logged with the Wave source record ID and the Zuora account/order ID for audit and replay.

A real-world example

A small software-as-a-service company uses Wave Accounting to invoice customers and track revenue. As the business grows and moves to subscription billing, the team switches to Zuora for order-to-cash and revenue recognition while keeping Wave as the primary accounting ledger. When a new customer is added in Wave, the sales team no longer needs to manually recreate the account in Zuora. When Wave records an invoice and payment, Zuora receives the same customer and transaction data automatically, and month-end reconciliation between Wave and Zuora is automated rather than manual.

What you can do

  • Sync Wave customers into Zuora as accounts, with automatic account creation and updates.
  • Create Zuora orders and invoices when Wave invoices are created, ensuring billing records match accounting.
  • Post Wave payments to Zuora payment methods so payment status stays in sync.
  • Authenticate Wave with OAuth2 refresh tokens and Zuora with multi-region Client Credentials, handling token refresh and region routing.
  • Verify webhook signatures on both Wave (HMAC-SHA256) and Zuora (HMAC-SHA256) events, with a full audit log of every customer and invoice moved.

Questions

What customer data flows from Wave to Zuora?
When a customer is created or updated in Wave, ml-connector reads the customer record via GraphQL and creates or updates a matching account in Zuora. Customer name, email, and billing address are synchronized. Products are aligned so invoices created in Wave can reference the same product catalog in Zuora.
How does ml-connector handle Wave and Zuora's different authentication models?
Wave uses OAuth 2.0 Authorization Code Flow with refresh tokens, so ml-connector stores the refresh token and obtains new access tokens as needed. Zuora uses OAuth 2.0 Client Credentials, so ml-connector stores the client ID and client secret and obtains a new token every hour. ml-connector also captures the customer's Zuora region and constructs the correct base URL for multi-region deployments.
Why does ml-connector handle Wave payments separately from Zuora payment notifications?
Zuora payment notifications fire only for electronic payments, not manual or external payments. Wave invoices can be marked paid by any payment method. ml-connector reads Wave payment records and creates corresponding Zuora payment entries independently, ensuring both systems see the same payment activity regardless of the payment method recorded in Wave.

Related integrations

Connect Wave Accounting and Zuora

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

Get started