ml-connector
AcumaticaBILL

Acumatica and BILL integration

Acumatica Cloud ERP runs your finance and procurement records. BILL runs vendor payments and AP workflow. Connecting the two lets approved bills and their vendors move from Acumatica into BILL for payment, and lets the resulting payment status flow back into Acumatica so the ledger stays current. ml-connector handles the two different auth models and moves records on a schedule you control, with webhook updates from BILL where they are configured. Purchase orders stay in Acumatica, since BILL does not model them, and are sent across as bills instead.

How Acumatica works

Acumatica exposes vendors, AP bills, purchase orders, payments, GL accounts, and journal transactions through its Contract-Based REST API, served over HTTPS as JSON on a tenant-specific instance URL. The endpoint path embeds the exact ERP version, such as 24.200.001, and a mismatch returns HTTP 404. Auth is OAuth 2.0 through the built-in identity server, or a legacy cookie session that expires after about 20 minutes. All field values are wrapped in value objects, and there is no shared hostname across customers. Acumatica can push events through its Push Notifications screen, but most integrations poll using a filter on LastModifiedDateTime.

How BILL works

BILL exposes vendors, bills, payments, customers, invoices, and chart-of-accounts records through its v3 REST API at a fixed gateway URL. There is no OAuth; every call uses a sessionId obtained by posting a developer key plus org username, password, and organization ID to the login endpoint, and that session expires after 35 minutes of inactivity. BILL allows only three concurrent requests per org and has no native idempotency key. It can push webhooks for vendor, bill, and payment events, signed with HMAC-SHA256 in the x-bill-sha-signature header over the minified body.

What moves between them

The main flow runs from Acumatica into BILL. When an AP bill is released in Acumatica, ml-connector creates or updates the matching vendor in BILL, then creates the bill there with its line items mapped to BILL GL accounts. Payment status moves the other direction: ml-connector reads BILL payments, by webhook where subscriptions are configured and by scheduled polling otherwise, and records the result against the originating Acumatica bill. Vendor records are kept aligned so a bill never references a payee that BILL has not seen. Purchase orders are not sent, because BILL has no purchase order model.

How ml-connector handles it

ml-connector stores both credential sets encrypted. On the Acumatica side it accepts the full instance URL and endpoint version per customer, requests an OAuth token or opens a cookie session, and wraps every field value in the required value object. On the BILL side it logs in with the developer key and org credentials, caches the sessionId, and re-logs in on a 401 since BILL reports expiry only as an auth error. Acumatica GL accounts and subaccounts are mapped to BILL chart-of-accounts entries and department classifications first, so every bill line lands on a valid account. BILL webhook deliveries are verified by recomputing the HMAC-SHA256 signature over the minified payload before they are trusted. Because BILL permits only three concurrent calls per org and Acumatica throttles near its license limit, ml-connector queues work and backs off on 429, and it watches the BILL subscription enabled flag so a failed-delivery auto-disable is caught and re-enabled.

A real-world example

A growing professional services firm of about 120 staff runs Acumatica Cloud ERP for its general ledger and approvals, but pays vendors through BILL because of its check and ACH handling. Before the integration, an AP clerk re-keyed every approved Acumatica bill into BILL to pay it, then typed the payment date and method back into Acumatica once the money moved. Bills were occasionally entered twice, and the ledger lagged real payment status by days. With Acumatica and BILL connected, released bills and their vendors flow into BILL automatically, and payment status posts back against the original bill, so the clerk reviews exceptions instead of copying every record by hand.

What you can do

  • Push released Acumatica AP bills and their vendors into BILL so payments run from one queue.
  • Record BILL payment status back against the originating Acumatica bill to keep the ledger current.
  • Map Acumatica GL accounts and subaccounts to BILL chart-of-accounts and department classifications.
  • Bridge Acumatica OAuth or session login and BILL's session token, refreshing each side on a 401.
  • Verify BILL webhook signatures, poll where webhooks are absent, and retry within BILL's concurrency limit.

Questions

Which direction does data move between Acumatica and BILL?
Bills and vendors move from Acumatica into BILL, and payment status moves from BILL back into Acumatica. Acumatica stays the system of record for the ledger, while BILL handles the actual vendor payment. Purchase orders are not sent, because BILL has no purchase order model.
How does the integration handle the two different logins?
Acumatica uses OAuth 2.0 or a legacy cookie session against a tenant-specific URL, while BILL uses a sessionId from a developer key plus org credentials. ml-connector stores both credential sets encrypted and obtains each token on its own terms. BILL sessions expire after 35 minutes and report expiry only as an auth error, so the connector treats a 401 as a signal to re-login and retry.
What happens with BILL's webhooks and low concurrency limit?
Where BILL webhook subscriptions exist, ml-connector verifies the HMAC-SHA256 signature over the minified payload before acting, and it polls for payment updates where webhooks are not configured. BILL disables a subscription after repeated delivery failures, so the connector watches the enabled flag and re-enables it. Because BILL allows only three concurrent calls per org, requests are queued and backed off rather than sent in parallel.

Related integrations

Connect Acumatica and BILL

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

Get started