ml-connector
XeroDeel

Xero and Deel integration

Xero runs your bookkeeping and accounts. Deel runs your payroll and workforce across borders. Connecting the two keeps your labor costs and headcount in sync. Worker invoices from Deel flow into Xero's general ledger automatically after each payroll run, mapped to the cost centers and accounts you specify. Deel worker data and contract changes flow into Xero so your headcount records stay accurate without manual re-entry.

How Xero works

Xero Accounting API is a REST API covering invoices, contacts, accounts, purchase orders, payments, manual journals, tracking categories, and bank transactions. It authenticates with OAuth2 Authorization Code flow; access tokens expire in 30 minutes and refresh tokens in 60 days. Every call requires the Xero-tenant-id header to target the specific organization. Webhooks are available for invoices, payments, manual journals, and bank transactions, but they carry metadata only and require a follow-up GET to fetch the full record. Rate limits are 5 concurrent calls, 60 per minute per tenant, and 5000 per day. The API uses page-based pagination with 100 records per page.

How Deel works

Deel is a REST API for payroll, contracts, and workforce across 150+ countries. It supports OAuth2 or bearer tokens (API or personal tokens); OAuth2 tokens expire after 30 days with refresh tokens valid for 90 days. Webhooks emit events for contract creation, employee updates, termination, and other HRIS and accounting changes, signed with HMAC-SHA256. Deel is HRIS and payroll only; it does not expose vendor masters, purchase orders, or standalone GL accounts. Worker invoice and payslip payloads embed cost allocation data. API tokens can be scoped with fine-grained resource permissions. Rate limits are not published but responses include a Retry-After header on 429 responses. Pagination is offset-based with 25 records per page by default.

What moves between them

The main flow runs from Deel into Xero. After each payroll run, ml-connector reads Deel invoices and worker cost records and posts them as manual journal entries into Xero's accounts, mapped to the correct Xero accounts and cost centers. Worker contract changes and terminations from Deel flow into Xero so headcount records stay aligned. Tracking categories (cost centers, departments) are mapped first, so every labor cost line references a Xero account that already exists. Because Xero webhooks carry metadata only, ml-connector polls Deel on a schedule tied to your payroll calendar and also listens for Deel webhook events where they are configured.

How ml-connector handles it

ml-connector stores both OAuth2 credentials encrypted and refreshes Deel tokens when a call returns 401, using the same refresh token up to the 90-day limit. On the Xero side it caches the tenant ID per customer and validates that all accounts and tracking categories exist before posting manual journals. Deel webhooks are verified by computing HMAC-SHA256 over the raw request body using the webhook signing key from your Deel settings. Because Xero's webhook payload is metadata-only, ml-connector polls the Xero API on a schedule even when webhooks are enabled to fetch full invoice and payment records. Deel's worker invoice amounts are mapped to Xero accounts using a stored mapping table; if an account mapping is missing, the record is quarantined with an audit note until the mapping is added. Deel rate limits return HTTP 429 with a Retry-After header, so ml-connector backs off and retries, and it detects when a Deel API token is about to expire by checking the refresh token expiry so a renewal does not cause an outage. Every record is logged in the audit trail and can be replayed if a downstream post fails.

A real-world example

A services company with contractors and employees in 12 countries runs Deel for workforce and payroll, and Xero for accounting. Before the integration, finance exported Deel invoices and payslips every month and manually entered labor costs into Xero, then spent hours reconciling headcount between Deel and Xero's employee tracking category. With Deel and Xero connected, each payroll run's worker invoices post automatically into Xero's labor accounts, allocated to the correct cost center per contractor location, and employee changes keep the two systems aligned. Month-end accounting starts with the labor accounts already posted and verified, and the manual data entry step is eliminated.

What you can do

  • Post Deel worker invoices into Xero's general ledger after each payroll run, allocated to the correct cost centers and accounts.
  • Keep Xero headcount and contractor records aligned with Deel employee additions, updates, and terminations.
  • Map Deel cost centers and departments to Xero tracking categories so labor expenses land on the correct accounts.
  • Authenticate Deel with OAuth2 bearer tokens and Xero with tenant ID headers, and verify Deel webhook signatures with HMAC-SHA256.
  • Poll on a schedule tied to your payroll calendar, with retries, token refresh, and a full audit trail on every record.

Questions

Which direction does data move between Xero and Deel?
The main flow is Deel into Xero. Worker invoices, payslips, and cost records flow from Deel into Xero, while employee and contractor records are aligned in both directions. Xero invoices and payments can also flow back to Deel for reconciliation. Xero's general ledger entries are read-only once posted, so ml-connector does not modify them after they are created.
Does Xero's webhook system work for this integration, or does ml-connector have to poll?
Xero webhooks are available for invoices, payments, and manual journals, but the webhook payload contains metadata only. ml-connector must follow up with a GET request to fetch the full record, so polling on a schedule tied to your payroll calendar is more efficient. ml-connector can also listen for Deel webhook events and reconcile both directions on a cadence you define.
How does ml-connector handle token refresh and rate limits?
ml-connector stores OAuth2 credentials encrypted and refreshes the Deel bearer token when a call returns 401, reusing the same refresh token up to its 90-day expiry. For Xero, it caches the tenant ID to avoid repeating lookups. When either system returns HTTP 429, ml-connector backs off and retries with exponential jitter, and it checks token expiry proactively so a renewal does not cause an outage.

Related integrations

Connect Xero and Deel

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

Get started