ml-connector
AcumaticaGusto

Acumatica and Gusto integration

Acumatica Cloud ERP runs your financials and operations. Gusto runs HR and payroll. Connecting the two keeps your general ledger and your workforce in agreement without re-keying. After each Gusto payroll is processed, the labor cost (gross pay, employer taxes, and deductions) posts into Acumatica as a balanced journal transaction, and new hires and terminations in Gusto line up with Acumatica employee records. ml-connector handles the very different APIs on each side and moves the data on the cadence you choose.

How Acumatica works

Acumatica exposes vendors, bills, GL accounts, journal transactions, payments, and employees through its Contract-Based REST API, with JSON over HTTPS on a tenant-specific URL whose endpoint version (for example 24.200.001) must exactly match the customer's ERP release or the call returns a 404. Authentication is OAuth2 via the built-in OpenID Connect identity server, with a Client ID that embeds the company name; a legacy cookie session login also exists. Every field value in a request or response is wrapped in a value object, and there is no native idempotency key. Acumatica can push change events via its Push Notifications feature, but the common and most reliable integration pattern is polling records by a LastModifiedDateTime filter.

How Gusto works

Gusto exposes companies, employees, jobs and compensations, pay schedules, processed payrolls, contractors, and benefits through its REST App Integrations API, with a required X-Gusto-API-Version header. Authentication is OAuth2 authorization-code only; there is no client-credentials option, and since the 2023-05 version each access token is scoped to a single company, so a multi-company customer authorizes each company separately. Access tokens last two hours and refresh tokens are single-use, so they rotate on every refresh. Payroll dollar amounts are returned as string decimals. Gusto pushes signed webhooks (HMAC-SHA256 in the X-Gusto-Signature header) for events such as payroll.processed, payroll.paid, employee.terminated, and employee.created.

What moves between them

The main flow runs from Gusto into Acumatica. When a Gusto payroll is processed, ml-connector reads the payroll's employee compensations (gross pay, net pay, taxes, and deductions) and posts a balanced journal transaction into Acumatica, with each pay component mapped to the matching Acumatica GL account and subaccount. Employee records flow the same direction so Acumatica headcount reflects Gusto hires and terminations. GL accounts in Acumatica are aligned first so every journal line references an account that already exists. Gusto has no general ledger of its own and is treated as a read-only payroll source, so ml-connector never writes financial entries back into Gusto.

How ml-connector handles it

ml-connector stores both credential sets encrypted. On the Gusto side it runs the authorization-code OAuth flow per company, refreshes the two-hour access token, and rotates the single-use refresh token on every renewal so a stale token never blocks a sync. On the Acumatica side it accepts the full tenant URL and the exact endpoint version per customer, obtains an OpenID Connect token, and wraps every field value in the required value object. Gusto payroll webhooks are verified against the X-Gusto-Signature HMAC before processing and start the posting work as soon as a payroll is processed, while a scheduled poll backfills anything a webhook missed. Because Gusto returns dollar amounts as string decimals, ml-connector parses them with decimal math so the journal balances to the cent. Pay components are mapped to Acumatica GL accounts first, so each journal line lands on a valid account. Acumatica has no idempotency-key header, so before posting, ml-connector checks for an existing journal by the payroll reference to avoid a duplicate, and it backs off on the 429 returned when the license rate limit is hit. Every record carries a full audit trail and can be replayed if a downstream call fails.

A real-world example

A mid-sized professional services firm of about 120 employees runs Acumatica Cloud ERP for project accounting and finance and uses Gusto for payroll and HR. Before the integration, an accountant exported the payroll summary from Gusto every pay period and hand-entered the wage, tax, and deduction totals into Acumatica as a manual journal, then spent the start of month-end close chasing differences between HR headcount and the payroll accounts in the ledger. With Acumatica and Gusto connected, each processed payroll posts into Acumatica automatically as a balanced journal split across the correct GL accounts, and employee changes keep the two systems aligned. Month-end close starts with the labor accounts already reconciled, and the manual re-keying step is gone.

What you can do

  • Post each processed Gusto payroll into Acumatica as a balanced journal transaction across the correct GL accounts.
  • Map Gusto gross pay, employer taxes, and deductions to your Acumatica chart of accounts and subaccounts.
  • Keep Acumatica employee records aligned with Gusto hires and terminations.
  • Authenticate Gusto with company-scoped authorization-code OAuth and Acumatica with its OpenID Connect token and matching endpoint version.
  • Start posting on a verified Gusto payroll webhook, with scheduled polling, retries, and a full audit trail on every record.

Questions

Which direction does data move between Acumatica and Gusto?
The main flow is Gusto into Acumatica. Processed payrolls become balanced journal transactions in Acumatica, and employee hires and terminations move from Gusto into Acumatica employee records. Gusto has no general ledger of its own, so ml-connector treats it as a read-only payroll source and never writes financial entries back into Gusto.
How does the integration handle Gusto's per-company tokens and rotating refresh tokens?
Each Gusto access token is scoped to a single company and lasts two hours, and the refresh token is single-use. ml-connector runs the authorization-code OAuth flow once per Gusto company, stores each token set encrypted, and rotates the refresh token on every renewal so a stale credential never interrupts a payroll post.
What keeps a payroll from posting to Acumatica twice?
Acumatica has no idempotency-key header, so ml-connector checks for an existing journal by the payroll reference before it posts a new one. It also verifies the Gusto webhook signature before acting and can replay a failed post from the audit trail, so a retried or duplicated webhook does not create a second journal.

Related integrations

Connect Acumatica and Gusto

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

Get started