Wave Accounting and Gusto integration
Wave Accounting and Gusto serve different parts of small business operations. Wave manages invoicing and accounting; Gusto handles payroll and HR. Connecting the two keeps your customer records aligned with your employee base and lets you track labor costs against the invoices Wave generates. Customer invoices from Wave can be annotated with payroll allocations from Gusto, and employee records flow from Gusto into Wave for accurate headcount and labor cost reconciliation.
What moves between them
The main data flow runs from Gusto into Wave Accounting. ml-connector polls Gusto for new employees, job assignments, and payroll data and maps them into Wave customers and transactions for labor cost tracking. Wave invoices flow into Gusto in the other direction so that payroll allocations can be matched against sales invoices for project-based cost analysis. Employee terminations in Gusto trigger customer archival in Wave. Reference data such as job codes and compensation types are aligned between the systems so that labor allocations land on invoice line items that already exist in Wave. The sync runs on a daily cadence tied to payroll periods and invoice creation cycles.
How ml-connector handles it
ml-connector stores OAuth2 credentials for both systems encrypted and handles token refresh for both Wave (with offline_access scope) and Gusto (managing single-use rotating refresh tokens per company). It validates Wave webhook signatures using HMAC-SHA256 against the x-wave-signature header with a 5-minute replay window and Gusto webhook signatures using X-Gusto-Signature header. Because Wave exposes payroll only through Gusto webhooks and GraphQL has no push mechanism, ml-connector polls Gusto's payroll endpoint on a fixed daily schedule and posts the labor cost transactions into Wave via GraphQL mutations. It maps Gusto employee IDs and job codes to Wave customer records so that payroll allocations reference customers that exist in Wave. Because Gusto rate-limits to 200 requests per minute per OAuth token and Wave webhook retries can spike traffic, ml-connector queues requests and backs off when it hits the rate limit, tracking the window to avoid conflicts. Gusto's requirement for version fields on PUT requests means ml-connector must read the current version before updating. Every transaction carries a full audit trail of the source Gusto payroll record, the Wave invoice it maps to, and the timestamp of the sync.
A real-world example
A small digital agency runs Wave Accounting for client invoicing and expense tracking, and uses Gusto for payroll of its core team plus contractors. Before the integration, the finance manager invoiced clients by project in Wave, then manually allocated the labor costs from Gusto payroll exports to each invoice for project profitability analysis. At month-end, reconciling invoiced work against actual payroll disbursed took hours of spreadsheet matching. With Wave and Gusto connected, each payroll run in Gusto flows into Wave as labor cost transactions tied to the matching customer, so invoices automatically show the labor cost for every project. Month-end reconciliation is now a quick verification rather than a manual data entry task.
What you can do
- Sync Gusto employees and contractors into Wave customers so payroll records tie to the invoiced client.
- Map Gusto payroll data into Wave transactions and allocate labor costs to the correct invoice line items.
- Refresh OAuth2 tokens for both Wave (with offline_access) and Gusto (managing rotating single-use refresh tokens).
- Verify webhook signatures from both Wave (HMAC-SHA256 x-wave-signature header) and Gusto (X-Gusto-Signature header) with replay-window protection.
- Poll Gusto payroll on a daily schedule, respect rate limits (200 requests per minute), and maintain a full audit trail of every labor cost transaction.
Questions
- Which direction does data move between Wave Accounting and Gusto?
- The main flow is Gusto into Wave Accounting. Employees, payroll records, and labor costs move from Gusto into Wave as customers and transactions. Wave invoices can flow into Gusto for project cost allocation. Because Wave exposes no payroll data, all labor cost data comes from Gusto webhooks and polling.
- How does ml-connector handle Wave's GraphQL API and Gusto's REST API differences?
- ml-connector translates Gusto's REST payroll objects into Wave GraphQL mutations for transaction creation, mapping Gusto employee and job IDs to Wave customer and account dimensions. It manages two separate OAuth2 flows: Wave with offline_access scope for long-lived refresh capability, and Gusto with single-use rotating refresh tokens per company. Token refresh logic is tailored to each system's behavior.
- What happens when rate limits or webhook retries cause traffic spikes?
- ml-connector queues Gusto API requests and backs off when hitting the 200-requests-per-minute limit, tracking the rolling window to avoid conflicts. Wave webhook retries are handled by verifying signatures and idempotency tokens so duplicate deliveries do not create duplicate transactions. Both systems' payloads carry timestamps and version fields that allow ml-connector to deduplicate across retries.
Related integrations
More Wave Accounting integrations
Other systems that connect to Gusto
Connect Wave Accounting and Gusto
Free to use. Add your credentials, ping your real systems, and see if we fit.
Get started