ml-connector
Wave AccountingHubSpot

Wave Accounting and HubSpot integration

Wave Accounting runs invoicing and customer billing for small businesses. HubSpot runs the CRM and sales pipeline. Connecting the two keeps your customer records and invoicing data in the same system. Customers created in Wave flow into HubSpot as contacts, and invoices sync across so your sales team sees the full billing history alongside deal activity. ml-connector handles Wave's GraphQL transport, HubSpot's REST layer, and the mapping between Wave's customer and invoice entities and HubSpot's contact and commerce invoice objects.

How Wave Accounting works

Wave Accounting exposes customers, invoices, transactions, products, and chart of accounts through a GraphQL API at https://gql.waveapps.com/graphql/public. The platform authenticates via OAuth 2.0 Authorization Code Flow with 2-hour access tokens and refresh tokens requiring the offline_access scope. Wave requires an active Wave Pro subscription for API access and publishes webhooks for invoice.created, invoice.updated, invoice.paid, payment.created, customer.created, customer.updated, transaction.created, product.created, and product.updated events with 5-minute replay windows. Webhook payloads are signed with HMAC-SHA256 (x-wave-signature header).

How HubSpot works

HubSpot exposes contacts, companies, deals, and commerce objects (invoices, line items, payments, orders) through REST JSON API at https://api.hubapi.com with date-versioned paths. Authentication uses Private App Access Token (Bearer token starting with pat-) for server-to-server integrations, with the token and numeric hub ID required per request. HubSpot enforces rate limits (100 to 190 requests per 10 seconds depending on plan tier), cursor-based pagination with 200-record max per request, and a 10,000-record limit on Search API queries. Invoices and commerce objects require associations to contacts and line items to be valid. HubSpot also supports webhook subscriptions, requiring a Public App registration separate from the Private App token.

What moves between them

The main flow runs from Wave into HubSpot. Customer records created or updated in Wave flow into HubSpot as contacts via the webhook stream. Invoices sync from Wave into HubSpot's commerce invoice object with associated line items mapped from Wave products, and invoice payments are tracked via Wave's payment.created and payment.updated events. Transactions created in Wave may also flow to HubSpot for the full financial audit trail. The sync is bidirectional for customer metadata so HubSpot contact updates (phone, email, billing address) can be written back to Wave if configured, though the primary flow is Wave source to HubSpot destination.

How ml-connector handles it

ml-connector receives Wave's incoming webhooks at a registered endpoint, validates each signature against the x-wave-signature header using HMAC-SHA256, and queues the event for processing. For customer records, ml-connector upserts HubSpot contacts by matching Wave customer email to HubSpot email. For invoices, ml-connector creates a HubSpot commerce invoice object and associates it with the corresponding HubSpot contact, then creates line items from Wave's invoice line details using Wave product IDs as identifiers. It handles HubSpot's 100-record batch limit and per-request rate limits by backing off on 429 responses. Wave's OAuth tokens expire after 2 hours, so ml-connector refreshes the token on 401 responses before retrying. Every record carries an audit trail including the original Wave webhook payload, the transformed HubSpot JSON, and the outcome of each API call. If a HubSpot write fails, the job is retried with exponential backoff.

A real-world example

A small business offers SaaS services and uses Wave Accounting to issue monthly invoices to customers and track accounts receivable. The same business uses HubSpot to manage customer relationships and track which deals are won and active. Before the integration, the sales team had to manually copy customer information and recent invoices from Wave into HubSpot notes to see the full customer financial picture during renewal conversations. With Wave and HubSpot connected, each new customer created in Wave automatically appears as a HubSpot contact, and each invoice syncs across with payment status and line details. The sales team can now see both the deal pipeline and the invoice history for each customer without leaving HubSpot, and month-end renewal cycles move faster because all data is current.

What you can do

  • Sync Wave customers into HubSpot as contacts, mapped by email address with full contact details.
  • Create HubSpot commerce invoices from Wave invoices, with line items mapped from Wave products.
  • Track invoice payments from Wave into HubSpot so sales teams see payment status alongside deals.
  • Validate Wave webhook signatures (HMAC-SHA256) and handle Wave's OAuth 2.0 token refresh automatically.
  • Handle HubSpot's rate limits and 100-record batch operations with retry logic and a full audit trail.

Questions

How does ml-connector map Wave customers and invoices to HubSpot?
Wave customers are mapped to HubSpot contacts by matching email address; if a Wave customer has no email, ml-connector creates a contact using the customer name and queues the email for manual entry. Wave invoices become HubSpot commerce invoice objects associated with the matching contact, and line items are created from Wave invoice lines using Wave product IDs. If a Wave invoice has no associated customer email, the invoice is queued for manual routing.
Does ml-connector handle Wave OAuth token refresh and HubSpot rate limits?
Yes. Wave access tokens expire after 2 hours, so ml-connector automatically refreshes the token when a request returns 401 and retries without manual intervention. For HubSpot, ml-connector tracks the per-tier rate limit (100 to 190 requests per 10 seconds), backs off and retries on 429 responses with exponential backoff, and batches operations under the 100-record limit per request.
What happens if a Wave webhook fails to reach HubSpot or HubSpot returns an error?
Every record carries a full audit trail including the original Wave webhook, the transformed HubSpot JSON, and the API response. If HubSpot rejects an invoice or contact, the job is retried with exponential backoff. If retries exhaust, the record is flagged in the audit log with the error reason so it can be replayed manually or fixed and retried.

Related integrations

Connect Wave Accounting and HubSpot

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

Get started