ml-connector
XeroADP

Xero and ADP integration

Xero runs accounting for the business. ADP runs payroll and HR. Connecting the two keeps the general ledger and the workforce in agreement. The labor cost document ADP generates after each payroll run posts into Xero as a manual journal without re-keying, and ADP hires and terminations stay reflected in the Xero contacts and tracking dimensions you report against. ml-connector handles the very different APIs on each side and moves the data on a schedule you control.

How Xero works

Xero exposes contacts (customers and suppliers), invoices and bills under a single Invoices object, chart of accounts, tracking categories, manual journals, and payments through its REST Accounting API at api.xero.com. It authenticates with OAuth 2.0 authorization code flow: a 30-minute access token refreshed from a 60-day refresh token, with every call carrying a Xero-tenant-id header to target one organization. Lists use page-based pagination at 100 records per page, and the If-Modified-Since header supports incremental sync. Xero also pushes metadata-only webhooks signed with HMAC-SHA256, but those cover only a subset of objects and never payroll, so each event needs a follow-up GET.

How ADP works

ADP exposes workers, payroll pay-data input, pay distributions, cost center validation tables, and general ledger documents through ADP API Central, a paid REST add-on that also supports OData query parameters. Every call requires OAuth2 client credentials and a mutual TLS client certificate, and the TLS handshake fails without the certificate. Writes to ADP go through event endpoints rather than direct field updates, and the general ledger documents ADP generates after payroll are read-only. ADP can push worker and payroll event notifications to a registered endpoint, acknowledged with a 2xx status, though it does not document an HMAC signature scheme.

What moves between them

The main flow runs from ADP into Xero. After each payroll run, ml-connector reads ADP's general ledger document and posts the labor cost lines into Xero as a manual journal, mapped to the matching Xero account codes and tracking category options. Worker records flow the same direction so the contacts and tracking dimensions in Xero reflect ADP hires, terminations, and rehires. Reference data such as cost centers and departments is aligned so every journal line references a Xero account and tracking option that already exists. The ADP general ledger document is read-only, so ml-connector never writes financial entries back into payroll.

How ml-connector handles it

ml-connector stores both credential sets encrypted and presents the ADP client certificate at the TLS layer on every request, refreshing the ADP bearer token when a call returns 401. On the Xero side it runs the OAuth authorization code flow, refreshes the 30-minute access token from the 60-day refresh token before it lapses, and attaches the Xero-tenant-id header so each call lands in the right organization. Because the ADP GL document is a read-only output, ml-connector polls ADP on a schedule tied to your payroll calendar rather than waiting for a push, and uses If-Modified-Since against Xero to pull only changed records. ADP cost centers and departments map to Xero account codes and tracking options first, so every payroll journal line lands on a dimension that already exists. Xero allows at most two active tracking categories, so cost center and department are mapped within that limit. ADP rate limits return HTTP 429 per gateway node and Xero enforces a 60-call-per-minute and 5,000-call-per-day cap per tenant, so ml-connector backs off and retries within those budgets, and it tracks the ADP certificate expiry so a renewal does not turn into an outage. Each manual journal is posted under the ADP document identifier so a re-run does not create a duplicate, and every record carries a full audit trail and can be replayed if a Xero post fails.

A real-world example

A services firm of about 150 staff runs Xero for accounting and ADP Workforce Now for payroll across two offices. Before the integration, the finance team exported the payroll register from ADP every pay period and hand-keyed the wage, tax, and deduction totals into Xero as a journal, then spent the first days of month-end close chasing differences between headcount and the labor accounts. With Xero and ADP connected, each payroll run's general ledger document posts into Xero automatically as a manual journal, split by office using tracking categories, and worker 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 the ADP payroll general ledger document into Xero as a manual journal after every pay run.
  • Allocate payroll journal lines to the correct Xero account codes and tracking category options.
  • Keep Xero contacts and tracking dimensions aligned with ADP hires, terminations, and rehires.
  • Authenticate ADP with OAuth2 client credentials and the required mutual TLS certificate, and Xero with its OAuth token and tenant header.
  • Poll ADP on a schedule tied to your payroll calendar, with retries and a full audit trail on every record.

Questions

Which direction does data move between Xero and ADP?
The main flow is ADP into Xero. The payroll general ledger document and worker records move from ADP into Xero, while cost centers and departments are aligned so journals land on valid dimensions. The ADP general ledger document is read-only, so ml-connector does not write financial entries back into payroll.
Does ADP's mutual TLS certificate requirement need special setup?
Yes. ADP requires a client certificate at the TLS layer on every call in addition to OAuth2 client credentials, and the handshake fails without it. ml-connector stores the certificate encrypted, presents it on each request, and tracks its expiry so a renewal is handled before it can cause an outage.
How does the integration avoid duplicate journals in Xero?
Each payroll run's general ledger document is posted as a single Xero manual journal keyed to the ADP document identifier, so re-running the same pay period updates that journal rather than creating a second one. ml-connector also uses Xero's If-Modified-Since header to pull only records changed since the last sync, which keeps polling within Xero's per-minute and daily call limits.

Related integrations

Connect Xero and ADP

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

Get started