Workflow · Api

Acumatica Webhooks vs REST Polling — When to Use Which

How Acumatica push notifications (webhooks) compare to REST polling, with concrete guidance on when each pattern wins and the operational gotchas that come with each.

John Kihiu12 min read

Acumatica gives you two ways to find out something changed: have it tell you (business events pushing to a webhook) or ask it repeatedly (polling the contract-based REST API on a schedule). Most integrations default to whichever pattern the developer built last, when the right choice actually depends on latency needs, endpoint availability, and how much you trust delivery guarantees.

How business event webhooks work

A business event in Acumatica watches for a condition — a document reaching a status, a field changing value — and fires a defined action when it's met. One of those actions can be an HTTP callout: Acumatica posts a payload to an external URL the moment the condition is satisfied. This gets you near-real-time notification without your integration ever asking Acumatica "did anything change." The AR Invoice released, the webhook fires seconds later, downstream systems react immediately.

The catch is that Acumatica's webhook delivery is fire-and-forget in the common configuration — there's no built-in dead-letter queue or guaranteed redelivery if your endpoint is down or returns an error. If your receiving service has an outage during the exact window a webhook fires, that event can simply be lost unless you've built retry logic on the Acumatica side (via a custom notification handler) or accept the gap.

How REST polling works

Polling flips the responsibility: a scheduled job calls the contract-based REST API on an interval, filtering for records modified since the last successful run (typically using a LastModifiedDateTime filter), and processes whatever comes back. Nothing gets silently lost — if a poll fails, the next one picks up the same unprocessed window, as long as you're tracking the watermark correctly.

JS · POLLING LOOP
async function pollInvoices(lastRunIso) {
  const filter = `LastModifiedDateTime gt datetimeoffset'${lastRunIso}'`;
  const res = await fetch(
    `${BASE_URL}/entity/Default/23.200.001/Invoice?$filter=${encodeURIComponent(filter)}`,
    { headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' } }
  );
  if (!res.ok) throw new Error(`Poll failed: ${res.status}`);
  const invoices = await res.json();
  for (const inv of invoices) {
    await processInvoice(inv);
  }
  return new Date().toISOString(); // new watermark, persist this
}

The trade-off is latency and cost: poll every five minutes and your worst-case delay is five minutes, poll every 30 seconds and you're hammering the API (and likely the license/session limits) for records that mostly haven't changed. Polling is inherently wasteful when nothing's happening, which is most of the time for a low-volume tenant.

Trade-offs at a glance

Webhooks (business events)REST polling
LatencySecondsBounded by poll interval
Delivery guaranteeFire-and-forget by defaultGuaranteed if watermark tracked correctly
Infra requirementPublic HTTPS endpointNone — outbound calls only
Load on AcumaticaMinimal, event-drivenRecurring API/session cost
ReconciliationNeeds a separate safety netNaturally self-healing

When polling is the safer choice

Webhooks assume the receiving side has a stable, publicly reachable HTTPS endpoint — not always true for an on-prem integration behind a corporate firewall, or during early development when you don't want to expose anything to the internet yet. Polling also wins when you need a full reconciliation pass rather than a stream of deltas: end-of-day jobs that need to confirm every invoice is accounted for are naturally a polling problem, since "ask for everything modified since midnight" is a more complete guarantee than trusting that every webhook fired and was received.

Webhooks don't survive Acumatica downtime cleanly

If Acumatica itself is down or mid-upgrade when a business event would have fired, that event doesn't queue and retry once the instance comes back — it just doesn't happen. Any integration relying solely on webhooks needs a periodic reconciliation poll to catch what was missed during an outage window.

The hybrid pattern most integrations end up with

In practice, the reliable answer is both: use a webhook for near-real-time reaction to the events that matter, and run a much less frequent polling job — hourly or nightly — purely as a reconciliation safety net that catches anything the webhook missed. The webhook handles the "user expects to see this immediately" cases; the poll handles "make sure nothing fell through the cracks." Keep the reconciliation poll idempotent so reprocessing an already-handled record is harmless, and you get low latency without betting the integration's correctness on webhook delivery alone.

Wrapping up

Webhooks give you speed, polling gives you certainty — pick webhooks for responsiveness and pair them with a periodic poll for reconciliation rather than treating either pattern as sufficient on its own. That combination is what actually survives an Acumatica outage or a flaky endpoint without silently dropping data.

John Kihiu
Acumatica ERP Developer · Laravel Engineer

Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.