ml-connector
Epicor KineticGusto

Epicor Kinetic and Gusto integration

Epicor Kinetic runs manufacturing finance and operations. Gusto runs payroll and HR. Connecting the two keeps your employee master, payroll GL, and cost center assignments in agreement across both systems. New hires and terminations in Gusto automatically sync to Epicor's employee master, and the labor cost entries Gusto generates after each payroll run flow into Epicor's general ledger without manual re-entry. ml-connector bridges the very different authentication flows and manages the polling and webhooks to keep both sides reconciled.

How Epicor Kinetic works

Epicor Kinetic exposes employees, vendors, GL accounts, cost centers, and expense dimensions through REST OData v4 endpoints, documented in Swagger within each cloud or on-premises instance. Cloud instances are accessed via https://<tenant>.epicorsaas.com/<instance>/api/v2/odata/<Company>/. Authentication uses Basic Auth, API Key, OAuth2 client credentials (cloud SaaS only), or Token Resource Service (on-premises). Because Epicor has no native webhooks, data is retrieved by polling with OData $filter on date fields to fetch changed records since the last sync, with offset pagination via $top and $skip. Writing employees and GL entries requires a two-step pattern: GetNew followed by UpdateMaster. Bearer tokens expire in roughly one hour, so refresh logic is required.

How Gusto works

Gusto exposes employees, jobs, compensations, payroll runs, contractors, and terminations through REST JSON endpoints at https://api.gusto.com/v1/ or https://api.gusto-demo.com/v1/ (sandbox). Authentication uses OAuth2 Authorization Code flow with a single-company-scoped token that expires in 2 hours and a refresh token that never expires but rotates on refresh. Gusto supports outbound webhooks for payroll events (created, updated, calculated, submitted, processed, paid, failed, reversed, cancelled), employee events (created, updated, onboarded, terminated), and termination events, with a 10-second response timeout and automatic retries over 3 days. Webhook signatures are verified via HMAC-SHA256. Gusto has no GL accounts, invoices, or accounting dimensions of its own, so all GL posting logic lives in the Epicor side. Rate limits are 200 requests per minute per OAuth grant.

What moves between them

Employee and termination records flow from Gusto into Epicor. When a new hire onboards in Gusto, the employee record syncs to Epicor's employee master with job code and cost center mapped from Gusto's job and location hierarchy. When a termination is recorded in Gusto, Epicor's employee record is marked inactive. After each payroll run closes in Gusto, ml-connector reads the payroll event, extracts labor cost totals by job and cost center, and posts GL entries into Epicor's general ledger allocated to the matching GL accounts and cost centers. Cost centers and GL accounts are configured upfront so every payroll posting lands on valid dimensions in Epicor. Payroll GL postings are read-only in Gusto, so no data flows back to payroll.

How ml-connector handles it

ml-connector stores both Gusto OAuth tokens (with refresh) and Epicor Bearer tokens (with hourly refresh) encrypted in the cell database. It refreshes the Gusto token on every 401 response and maintains an Epicor token cache. On the Gusto side, it subscribes to payroll and employee webhooks at provisioning time and listens for payroll.processed and employee.terminated events. When a payroll.processed webhook arrives, ml-connector queries Gusto's payroll object to extract pay distribution totals by job and location, maps them to Epicor cost centers and GL accounts, and uses Epicor's GetNewAPInvHed + UpdateMaster pattern to create GL journal entries. Employee records follow the same pattern: new employees are read from Gusto, mapped to Epicor cost centers, and created via GetNewPkgEmploy + UpdateMaster. Terminations trigger a Gusto employee.terminated webhook, which sets the employee record to inactive in Epicor. Because Gusto webhooks can arrive out of order or duplicate, ml-connector deduplicates using Gusto's object version field and the webhook timestamp. Epicor's one-hour Bearer token refresh is checked before every call, and Gusto's refresh token rotation is handled on every 401. Every record carries the full webhook payload and API response for audit and replay.

A real-world example

A mid-sized manufacturing company runs Epicor Kinetic for production, procurement, and finance across three plants, and uses Gusto for payroll across two regional offices and a head office. Before the integration, payroll closed in Gusto but the labor costs had to be exported and manually posted to Epicor's general ledger by cost center and plant, and new hires in Gusto had to be keyed into Epicor's employee master separately. Month-end reconciliation between HR headcount and the labor GL accounts took two days of back-and-forth. With Epicor and Gusto connected, each payroll run's labor costs post to Epicor automatically, allocated to the correct plant and cost center, and hires and terminations sync to the employee master in real time. The accounting team's month-end close now starts with the labor accounts already correct, and manual re-entry is eliminated.

What you can do

  • Sync Gusto employee hires, job assignments, and cost center allocation to Epicor's employee master.
  • Post Gusto payroll GL entries into Epicor's general ledger after each pay run, allocated to the correct cost centers and GL accounts.
  • Mark Epicor employee records inactive when Gusto terminations are recorded.
  • Bridge Gusto OAuth2 and Epicor Bearer token authentication, with automatic token refresh and timeout handling.
  • Listen to Gusto payroll and employee webhooks, deduplicate by object version, and replay via full audit trail if a downstream call fails.

Questions

What employee and payroll data flows from Gusto into Epicor?
Employee records flow from Gusto to Epicor with hire date, job code, location, and cost center assignment. After each payroll run closes in Gusto, payroll GL entries post into Epicor's general ledger allocated to the cost center for each employee's location or job. Termination records in Gusto trigger an inactive flag in Epicor's employee master. Pay rates and compensation details stay in Gusto and do not post to Epicor.
How does ml-connector handle Gusto webhooks and Epicor's lack of webhooks?
ml-connector subscribes to Gusto payroll and employee event webhooks at integration setup and listens for payroll.processed and employee.terminated events. Because Epicor has no native webhooks, ml-connector polls Epicor on a schedule between webhook triggers to fetch changed employee records and GL account assignments. Webhook deduplication is handled using Gusto's object version field and event timestamps to prevent duplicate GL postings if a webhook arrives twice.
What happens if a payroll GL posting fails in Epicor or a webhook arrives out of order?
Every webhook payload and Epicor API response is logged with full context in the audit trail. If an Epicor GL posting fails (e.g. GL account or cost center does not exist), ml-connector captures the error, logs it, and surfaces it in the dashboard for manual review and replay. If Gusto webhooks arrive out of order due to network delay, deduplication by object version prevents posting the same payroll twice.

Related integrations

Connect Epicor Kinetic and Gusto

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

Get started