ERP Webhook & Outbound Callback Support Comparison (2026)

Type: ERP Integration Systems: 12 ERPs compared Confidence: 0.86 Sources: 8 Verified: 2026-03-03 Freshness: current

TL;DR

System Profile

This comparison covers 12 major ERP systems across the spectrum of outbound event delivery capabilities, from native HTTP webhook support to event bus architectures to polling-only systems. The focus is on outbound notifications — what happens when a record changes inside the ERP and an external system needs to know about it.

This card does NOT cover inbound webhooks (external systems pushing data into the ERP). For deep-dive event architecture comparisons with protocol-level detail, see the ERP Event-Driven Integration Comparison card.

PropertyValue
Scope12 ERP systems (Salesforce, SAP S/4HANA, Oracle ERP Cloud, NetSuite, D365 F&O, D365 BC, Workday, IFS Cloud, Epicor Kinetic, Sage Intacct, Zoho, Acumatica)
FocusOutbound event delivery — webhook, push, event bus, polling
Card TypeCross-system comparison
Deployment ModelsCloud, hybrid, on-premise variants noted
Temporal Scope2024–2026 (current GA features only)

API Surfaces & Capabilities

Each ERP takes a different approach to outbound notifications. This table maps the primary outbound event mechanisms available on each platform. [src1, src2, src3, src4]

ERP SystemNative Outbound MechanismMechanism TypeProtocolRequires Add-on?Latency (Typical)
SalesforceOutbound Messages (SOAP)HTTP POST callbackSOAP/XMLNo1–5s
SalesforcePlatform Events / CDCEvent bus (pub/sub)gRPC (Pub/Sub API)High-volume license for >100K/day<1s–5s
SAP S/4HANA CloudSAP Event MeshEvent bus (pub/sub)AMQP / Webhook (HTTP POST)Yes (BTP subscription)1–30s
Oracle ERP CloudBusiness EventsEvent busOracle Integration CloudYes (OIC subscription)5–30s
NetSuiteSuiteScript User EventsCustom script (HTTP POST)REST/HTTPSNo (SuiteCloud Plus recommended)1–10s
D365 Finance & OperationsBusiness Events / Data EventsEvent busAzure Service Bus / HTTPSNo (Azure endpoint needed)2–15s
D365 Business CentralWebhook SubscriptionsHTTP POST callbackREST/JSONNo~30s (batched)
WorkdayNone (polling only)N/AN/AMiddleware required1–15 min (poll)
IFS CloudEvent ActionsWorkflow-triggered HTTP POSTREST/HTTPSNo2–10s
Epicor KineticNone native (BPM workaround)Custom code (REST call from BPM)REST/HTTPSNo (requires customization)2–15s
Sage IntacctPlatform Services (limited)Platform event triggersREST/HTTPSCustom Sender required5–30s
Zoho (Books/Inventory)Workflow WebhooksHTTP POST callbackREST/JSONNo<5s
AcumaticaPush NotificationsHTTP POST callbackREST/JSONNo1–10s

Rate Limits & Quotas

Outbound Event Delivery Limits

ERP SystemDaily Event LimitPer-Hour / Burst LimitRetry PolicyNotes
Salesforce (Outbound Msgs)No hard daily limit100 concurrentRetry 24h on failureMessages queue if endpoint down [src1]
Salesforce (Platform Events)100K std; 10M+ add-on250K/hour (high-vol)At-least-once, 24h replayReplay by replayId [src1]
SAP Event MeshBTP plan dependentThrottled per queueConfigurable retry + DLQ[src2]
Oracle ERP CloudNo published limitOIC throttledBest-effort, manual replayRequires OIC
NetSuite (SuiteScript)Governance-limited10 concurrent HTTP callsNo built-in retry[src3]
D365 F&ONo hard limitAzure throttledAzure Service Bus DLQFailed events go to DLQ
D365 Business CentralNo hard limit1,000 changes/30s batch36h retry (408,429,5xx)Auto-deletes on non-retryable error [src4]
WorkdayN/A (polling)API rate limits applyN/A[src5]
IFS CloudNo published limitServer resourcesConfigurable[src7]
Epicor KineticNo published limitServer resourcesNo built-in retryCustom BPM calls
Zoho500 (free) / 5,000 (paid)Plan burst limits2x retry on failure[src8]
AcumaticaNo hard limitGI refresh cycleConfigurable retries[src6]

Authentication

ERP SystemAuth for Outbound DeliveryCallback VerificationNotes
SalesforceN/A (SF initiates)Session ID in SOAP headerVerify SF IP ranges [src1]
SAP Event MeshOAuth 2.0 (BTP)HMAC signature (optional)[src2]
Oracle ERP CloudOIC-managedOIC connection authExternal endpoint auth in OIC
NetSuiteTBA or OAuth 2.0Custom header injection[src3]
D365 F&OAzure AD / SAS tokenAzure Service Bus verifyAzure endpoint auth
D365 Business CentralN/A (BC initiates)clientState secret in payloadHandshake required [src4]
WorkdayN/A (polling)N/A[src5]
IFS CloudCustom headerNo built-in verification[src7]
ZohoCustom headerNo built-in HMAC[src8]
AcumaticaCustom header/URL tokenNo built-in HMAC[src6]

Authentication Gotchas

Constraints

Integration Pattern Decision Tree

START -- Need real-time outbound notifications from ERP
|-- Which ERP?
|   |-- Salesforce
|   |   |-- Simple field-change notifications -> Outbound Messages (SOAP callback)
|   |   |-- Structured events with replay -> Platform Events + Pub/Sub API (gRPC)
|   |   +-- Full change tracking -> Change Data Capture + Pub/Sub API
|   |-- SAP S/4HANA Cloud
|   |   |-- Have BTP subscription? -> SAP Event Mesh (AMQP or Webhook)
|   |   +-- No BTP? -> Poll OData API or use IDocs (legacy)
|   |-- Oracle ERP Cloud
|   |   |-- Have OIC? -> Business Events -> OIC -> external webhook
|   |   +-- No OIC? -> Poll REST API (no native push available)
|   |-- NetSuite
|   |   |-- Simple triggers -> User Event Script afterSubmit -> https.post()
|   |   |-- Workflow-driven -> Workflow Action Script -> https.post()
|   |   +-- High volume -> Scheduled Script with SuiteQL batch + push
|   |-- D365 Finance & Operations
|   |   |-- Standard processes -> Business Events -> Azure endpoint
|   |   |-- Data-level changes -> Data Events -> Azure Service Bus
|   |   +-- Simple CRUD -> Dataverse webhooks (if using Dataverse)
|   |-- D365 Business Central
|   |   +-- Any entity change -> Webhook Subscription API (REST, 30s batched)
|   |-- Workday
|   |   |-- Payroll changes -> PECI (scheduled, not real-time)
|   |   +-- All other data -> Poll REST/SOAP API from external system
|   |-- IFS Cloud
|   |   +-- Record changes -> Event Action -> REST POST to external URL
|   |-- Epicor Kinetic
|   |   +-- Transaction events -> Custom BPM/Function -> REST POST
|   |-- Sage Intacct
|   |   +-- Limited events -> Custom Sender or poll Web Services API
|   |-- Zoho
|   |   +-- Workflow triggers -> Webhook action (HTTP POST, JSON)
|   +-- Acumatica
|       +-- Data changes -> Generic Inquiry + Push Notification (HTTP POST)
|-- Need guaranteed delivery?
|   |-- YES -> Salesforce Platform Events (replay) or SAP Event Mesh (DLQ)
|   +-- NO -> Any native push mechanism + custom retry
+-- Latency requirement?
    |-- <5 seconds -> Salesforce, Zoho, D365 F&O, IFS Cloud, Acumatica
    |-- <30 seconds -> D365 BC, SAP Event Mesh, Oracle (via OIC)
    +-- Minutes acceptable -> Polling (any ERP), Workday PECI

Quick Reference

Webhook/Push Support at a Glance

ERP SystemNative HTTP Webhook?Event Bus?Polling Required?Best Real-Time OptionDelivery Guarantee
SalesforceYes (Outbound Messages, SOAP)Yes (Platform Events, CDC)NoPlatform Events + Pub/Sub APIAt-least-once (replay)
SAP S/4HANAVia Event Mesh (add-on)Yes (Event Mesh, AEM)FallbackEvent Mesh webhook subscriptionConfigurable (DLQ)
Oracle ERP CloudNo (requires OIC)Yes (Business Events)FallbackBusiness Events via OICBest-effort
NetSuiteVia SuiteScript (custom)NoFallbackUser Event ScriptNo (custom retry)
D365 F&OVia Azure endpointsYes (Business/Data Events)NoBusiness Events -> AzureAt-least-once (Azure DLQ)
D365 BCYes (Subscription API)NoNoWebhook Subscriptions (30s batch)At-most-once (36h retry)
WorkdayNoNoYes (required)Poll REST APIN/A
IFS CloudVia Event ActionsNoFallbackEvent Action -> REST POSTBest-effort
Epicor KineticNo (BPM workaround)NoFallbackBPM -> REST POST (custom)No (custom retry)
Sage IntacctNo (Custom Sender)NoRecommendedPoll Web Services APIN/A
ZohoYes (Workflow Webhooks)NoNoWorkflow Webhook POSTBest-effort (2 retries)
AcumaticaYes (Push Notifications)NoNoGI Push NotificationConfigurable retries

Cross-System Comparison

CapabilitySalesforceSAP S/4HANAOracle ERP CloudNetSuiteD365 F&OD365 BCWorkdayIFS CloudEpicorSage IntacctZohoAcumatica
Native outbound webhookOM (SOAP)No (add-on)No (OIC)No (custom)No (Azure)YesNoEvent ActionsNo (BPM)NoYesYes
Event busPE, CDCEvent MeshBiz EventsNoBiz/Data EventsNoNoNoNoNoNoNo
ProtocolSOAP, gRPCAMQP, HTTPOICHTTPSAzure SBREST/JSONN/ARESTRESTRESTREST/JSONREST/JSON
Setup complexityLow-MedHighHighMediumMediumLowN/AMediumHighHighLowLow-Med
Latency1–5s1–30s5–30s1–10s2–15s~30s1–15m2–10s2–15s5–30s<5s1–10s
Delivery guaranteeAt-least-onceConfigurableBest-effortNoneAt-least-onceAt-most-onceN/ABest-effortNoneNoneBest-effortConfigurable
Replay/recoveryYes (24h)Yes (DLQ)ManualNoYes (Azure DLQ)NoN/ANoNoNoNoNo
Event filteringObject/fieldEvent typeEvent IDScript logicCategoryResourceN/AEvent typeBPM logicTriggerWorkflowGI criteria
Max payload1 MB (PE)1 MBVariesCustom1 MBCollectionN/ACustomCustomCustomCustomCustom
Additional costHigh-vol PE lic.BTP requiredOIC requiredIncludedAzure costsIncludedN/AIncludedIncludedIncludedPlan-dep.Included

Step-by-Step Integration Guide

1. Evaluate your ERP's outbound capabilities

Classify your ERP into one of three tiers. [src1, src4, src6, src8]

Tier 1 — Native HTTP Webhooks (D365 BC, Zoho, Acumatica, Salesforce Outbound Messages): ERP pushes HTTP POST natively.

Tier 2 — Event Bus or Custom Script (Salesforce PE, SAP Event Mesh, Oracle via OIC, NetSuite SuiteScript, D365 F&O, IFS Cloud): Events emitted to bus or custom script pushes.

Tier 3 — Polling Required (Workday, Sage Intacct, Epicor without customization): No push mechanism.

Verify: Check the Quick Reference table to confirm your ERP's tier.

2. For Tier 1: Configure webhook subscription

Example: D365 Business Central. [src4]

# Register a webhook subscription for Sales Orders in D365 Business Central
curl -X POST "https://{tenant}.api.businesscentral.dynamics.com/v2.0/{env}/api/v2.0/subscriptions" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "notificationUrl": "https://your-endpoint.example.com/webhook/d365bc",
    "resource": "salesOrders",
    "clientState": "your-secret-state-value"
  }'

Verify: BC sends validation request → endpoint echoes validationToken → HTTP 200.

3. For Tier 2: Set up subscriber infrastructure

Example: Salesforce Platform Events via Pub/Sub API. [src1]

# Subscribe to Salesforce Platform Events via gRPC Pub/Sub API
import grpc
from salesforce_pubsub import PubSubClient

client = PubSubClient(
    instance_url="https://yourorg.my.salesforce.com",
    client_id="your_connected_app_id",
    client_secret="your_connected_app_secret",
    username="[email protected]"
)
for event in client.subscribe("/event/Order_Created__e", replay_preset="LATEST"):
    print(f"Order created: {event.payload}")

Verify: Publish test Platform Event → subscriber receives within 1–5s.

4. For Tier 3: Implement efficient polling

Example: Workday. [src5]

# Poll Workday REST API for worker changes
import requests

def poll_workday_changes(tenant, token, last_poll_time):
    url = f"https://wd5-impl-services1.workday.com/ccx/api/v1/{tenant}/workers"
    headers = {"Authorization": f"Bearer {token}"}
    params = {"limit": 100, "offset": 0}
    response = requests.get(url, headers=headers, params=params)
    response.raise_for_status()
    return response.json().get("data", [])
# Poll every 5 minutes -- store last_poll_time for recovery

Verify: Run poll → compare record counts with Workday UI.

Error Handling & Failure Points

Common Error Codes

ERPErrorMeaningResolution
SalesforceOUTBOUND_MSG_FAILEDEndpoint unreachable/timeoutCheck endpoint URL; SF retries 24h [src1]
D365 BCSubscription deletedNon-retryable error codeFix endpoint to return 200 or 5xx only [src4]
NetSuiteSSS_REQUEST_LIMIT_EXCEEDEDGovernance limit reachedBatch calls or use scheduled script [src3]
SAP429Rate limit exceededIncrease Event Mesh plan [src2]
AcumaticaPush notification failedTarget URL unreachableVerify URL in SM302000 [src6]
ZohoWEBHOOK_LIMIT_REACHEDDaily quota exceededUpgrade plan or batch [src8]

Failure Points in Production

Anti-Patterns

Wrong: Assuming all ERPs have Stripe-style webhooks

// BAD -- designing integration expecting simple HTTP POST from any ERP
app.post('/webhook/erp', (req, res) => {
  const event = req.body; // Salesforce sends SOAP XML, not JSON
  processERPEvent(event); // SAP sends via AMQP, not HTTP
  res.status(200).send('OK'); // Workday doesn't send anything at all
});

Correct: Design per-ERP adapter with fallback to polling

// GOOD -- ERP-specific adapter pattern
const adapters = {
  'd365bc':     new WebhookAdapter({ format: 'json', verify: 'clientState' }),
  'salesforce': new SOAPAdapter({ verify: 'sessionId', ipWhitelist: SF_RANGES }),
  'zoho':       new WebhookAdapter({ format: 'json', verify: 'header-token' }),
  'acumatica':  new WebhookAdapter({ format: 'json', verify: 'url-token' }),
  'workday':    new PollingAdapter({ interval: '5m', changeDetection: 'timestamp' }),
  'sap':        new AMQPAdapter({ queue: 'event-mesh', protocol: 'amqp10' }),
};

Wrong: SuiteScript User Events for high-volume outbound calls

// BAD -- calling external API in afterSubmit for every record
function afterSubmit(context) {
  var record = context.newRecord;
  https.post({ url: WEBHOOK_URL, body: JSON.stringify(record) });
  // Bulk import of 1,000 records = governance exhaustion
}

Correct: Batch and defer outbound calls in NetSuite

// GOOD -- queue records, send in batch via Scheduled Script
function afterSubmit(context) {
  var queue = record.create({ type: 'customrecord_outbound_queue' });
  queue.setValue({ fieldId: 'custrecord_record_id', value: context.newRecord.id });
  queue.save(); // Cheap: ~10 governance units
}
// Scheduled Script processes queue with 5,000 governance units

Wrong: Not handling D365 BC subscription expiry

// BAD -- register webhook once and forget
await registerWebhook(resource, notificationUrl);
// 3 days later: subscription silently expires

Correct: Implement subscription renewal

// GOOD -- renew D365 BC subscription before 3-day expiry
async function maintainSubscription(subscriptionId) {
  const renewed = await fetch(`/subscriptions(${subscriptionId})`, {
    method: 'PATCH',
    body: JSON.stringify({
      expirationDateTime: new Date(Date.now() + 3 * 86400000).toISOString()
    })
  });
  if (renewed.status === 404) await registerWebhook(resource, notificationUrl);
}
// Run on a 2-day interval

Common Pitfalls

Diagnostic Commands

# Salesforce: Check Outbound Message delivery status
# Setup -> Outbound Messages -> View Message Delivery Status

# D365 Business Central: List active webhook subscriptions
curl -H "Authorization: Bearer $BC_TOKEN" \
  "https://{tenant}.api.businesscentral.dynamics.com/v2.0/{env}/api/v2.0/subscriptions"

# NetSuite: Check governance usage
# Customization -> Scripting -> Script Execution Log (filter by script type)

# SAP Event Mesh: Check webhook subscription status
curl -H "Authorization: Bearer $BTP_TOKEN" \
  "https://enterprise-messaging-pubsub.cfapps.{region}.hana.ondemand.com/messagingrest/v1/subscriptions"

# Acumatica: Verify Push Notification config
# System -> Integration -> Push Notifications (SM302000) -- check Status column

# Zoho: Check webhook execution log
# Setup -> Automation -> Workflow Rules -> select rule -> View Webhook Log

Version History & Compatibility

ERPFeatureIntroducedCurrent StatusNotes
SalesforceOutbound Messages~2006GA (legacy)SOAP-only; Platform Events preferred
SalesforcePlatform EventsSpring '17GAReplaced Streaming API
SalesforcePub/Sub API (gRPC)Spring '22GAReplaced CometD Streaming API
SAPEvent Mesh2020GARequires BTP; rebranded from Enterprise Messaging
SAPAdvanced Event Mesh2023GAEnterprise tier (Solace-based)
Oracle ERPBusiness Events2019GARequires OIC for external delivery
NetSuiteSuiteScript 2.02016GAhttps module for outbound
D365 F&OBusiness Events10.0.22 (2022)GAAzure endpoints
D365 F&OData Events10.0.39 (2024)GAMore granular CRUD-level events
D365 BCWebhook Subscriptionsv1.0 API (2018)GA30s batching, 3-day expiry
IFS CloudEvent Actions21R2GAREST POST via workflow
AcumaticaPush Notifications2019 R1GABased on Generic Inquiries
ZohoWorkflow Webhooks~2018GAPlan-based daily limits

When to Use / When Not to Use

Use WhenDon't Use WhenUse Instead
Comparing webhook support across multiple ERPs for architecture decisionsDeep-dive on single ERP's event systemERP Event-Driven Comparison
Evaluating ERPs where real-time integration is a key requirementAlready chosen an ERP and need implementation detailsSystem-specific API capability card
Determining if an ERP requires middleware for push notificationsNeed webhook payload schemas and field mappingsSystem-specific integration playbook
Building iPaaS adapter layer supporting multiple ERPsOnly integrating with one ERPSingle-system event configuration guide

Important Caveats

Related Units