---
# === IDENTITY ===
id: business/erp-integration/webhook-callback-support-comparison/2026
canonical_question: "Which ERPs support outbound webhooks natively vs requiring polling for real-time integration?"
aliases:
  - "ERP webhook support comparison native outbound events vs polling"
  - "Which ERP systems have native webhook push notifications for integrations?"
  - "Compare real-time event delivery across Salesforce SAP Oracle NetSuite Dynamics 365 Workday"
  - "Do ERPs support outbound webhooks or do I need polling for real-time data?"
entity_type: erp_integration
domain: business > erp-integration > webhook-callback-support-comparison
region: global
jurisdiction: global
temporal_scope: 2024-2026

# === SYSTEM PROFILE ===
systems:
  - name: "Salesforce"
    vendor: "Salesforce"
    version: "API v62.0 (Spring '26)"
    edition: "Enterprise, Unlimited, Performance"
    deployment: cloud
    api_surface: "Outbound Messages, Platform Events, Change Data Capture, Pub/Sub API"
  - name: "SAP S/4HANA Cloud"
    vendor: "SAP"
    version: "2408"
    edition: "Public Cloud, Private Cloud"
    deployment: cloud
    api_surface: "SAP Event Mesh, Advanced Event Mesh (Solace), IDocs"
  - name: "Oracle ERP Cloud"
    vendor: "Oracle"
    version: "24B"
    edition: "Fusion Cloud ERP"
    deployment: cloud
    api_surface: "Business Events, Oracle Integration Cloud (OIC)"
  - name: "Oracle NetSuite"
    vendor: "Oracle"
    version: "2024.2"
    edition: "SuiteCloud Plus"
    deployment: cloud
    api_surface: "SuiteScript User Event Scripts, Workflow Actions, SuiteTalk"
  - name: "Microsoft Dynamics 365 Finance & Operations"
    vendor: "Microsoft"
    version: "10.0.40+"
    edition: "Finance, Supply Chain Management"
    deployment: cloud
    api_surface: "Business Events, Data Events, Dataverse Webhooks"
  - name: "Microsoft Dynamics 365 Business Central"
    vendor: "Microsoft"
    version: "v2.0 API"
    edition: "Essentials, Premium"
    deployment: cloud
    api_surface: "Webhook Subscriptions API"
  - name: "Workday"
    vendor: "Workday"
    version: "2024 R2"
    edition: "HCM, Financial Management"
    deployment: cloud
    api_surface: "PECI, Workday Web Services (SOAP), REST API"
  - name: "IFS Cloud"
    vendor: "IFS"
    version: "25R1"
    edition: "IFS Cloud"
    deployment: cloud
    api_surface: "Event Actions, IFS Workflow, REST API"
  - name: "Epicor Kinetic"
    vendor: "Epicor"
    version: "Kinetic 2024.2"
    edition: "Cloud, On-Premise"
    deployment: hybrid
    api_surface: "REST API, BPM/Functions"
  - name: "Sage Intacct"
    vendor: "Sage"
    version: "2025"
    edition: "Sage Intacct"
    deployment: cloud
    api_surface: "Web Services API, Platform Services"
  - name: "Zoho ERP (Books/Inventory)"
    vendor: "Zoho"
    version: "2025"
    edition: "Professional, Enterprise"
    deployment: cloud
    api_surface: "Webhooks (Workflow), REST API, Deluge Scripts"
  - name: "Acumatica"
    vendor: "Acumatica"
    version: "2024 R2"
    edition: "General Business, Distribution, Manufacturing"
    deployment: hybrid
    api_surface: "Push Notifications, Business Events, Contract-Based REST API"

# === VERIFICATION ===
last_verified: 2026-03-03
confidence: 0.86
version: 1.0
first_published: 2026-03-03

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: volatile
  last_breaking_change: "Salesforce Pub/Sub API replaced legacy Streaming API (Spring '23); D365 Data Events GA 10.0.39 (2024)"
  next_review: 2026-08-30
  change_sensitivity: high

# === CONSTRAINTS ===
constraints:
  - "No ERP offers HTTP webhook callbacks identical to Stripe/GitHub-style webhooks — all use platform-specific event mechanisms"
  - "Salesforce Platform Events require add-on high-volume license for >100K events/day"
  - "SAP Event Mesh requires BTP subscription (separate from S/4HANA license)"
  - "Workday has NO native outbound webhook or event push — polling is the only option without middleware"
  - "Epicor Kinetic has no native outbound webhook — requires BPM custom code or middleware"
  - "Webhook delivery guarantees vary: at-most-once (D365 BC) vs at-least-once (Salesforce Platform Events) vs best-effort (most others)"
  - "NetSuite SuiteScript outbound calls count against governance units — 5,000 units per script for scheduled, 1,000 for user event"
  - "Most ERP 'webhooks' are actually event buses or notification frameworks, not simple HTTP POST callbacks"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "User needs deep-dive on a single ERP's event architecture"
    use_instead: "business/erp-integration/erp-event-driven-comparison/2026"
  - condition: "User needs event payload schemas and protocol details"
    use_instead: "business/erp-integration/erp-event-driven-comparison/2026"
  - condition: "User needs polling implementation patterns specifically"
    use_instead: "business/erp-integration/erp-api-polling-patterns/2026"

# === AGENT HINTS ===
inputs_needed:
  - key: erp_system
    question: "Which ERP system(s) are you integrating?"
    type: choice
    options:
      - "Salesforce"
      - "SAP S/4HANA"
      - "Oracle ERP Cloud"
      - "NetSuite"
      - "Dynamics 365 F&O"
      - "Dynamics 365 Business Central"
      - "Workday"
      - "IFS Cloud"
      - "Epicor Kinetic"
      - "Sage Intacct"
      - "Zoho"
      - "Acumatica"
  - key: integration_pattern
    question: "What integration pattern do you need?"
    type: choice
    options:
      - "real-time push (webhook/event-driven, <5s latency)"
      - "near-real-time (event bus, <30s latency)"
      - "polling fallback (scheduled, 1-15 min intervals)"
  - key: direction
    question: "What's the data flow direction?"
    type: choice
    options:
      - "outbound (ERP pushes to external system)"
      - "inbound (external system pushes to ERP)"
      - "bidirectional sync"

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/business/erp-integration/webhook-callback-support-comparison/2026"
suggested_citation: "Source: knowledgelib.io — AI Knowledge Library (verified 2026-03-03)"

# === RELATED UNITS ===
related_kos:
  depends_on: []
  related_to:
    - id: "business/erp-integration/erp-event-driven-comparison/2026"
      label: "ERP Event-Driven Integration Comparison — Platform Events vs Event Mesh vs CDC vs Business Events"
  solves: []
  alternative_to:
    - id: "business/erp-integration/erp-event-driven-comparison/2026"
      label: "Deeper event architecture comparison (4 systems, protocol-level detail)"
  often_confused_with:
    - id: "business/erp-integration/erp-event-driven-comparison/2026"
      label: "Event-driven comparison focuses on event bus architectures; this card focuses on outbound webhook/push support breadth"

# === SOURCES ===
sources:
  - id: src1
    title: "Salesforce Webhooks: Your Guide to Real-Time Data Integration"
    author: Salesforce Ben
    url: https://www.salesforceben.com/salesforce-webhooks-deep-dive/
    type: technical_blog
    published: 2025-08-15
    reliability: high
  - id: src2
    title: "SAP Event Mesh — Manage Webhooks"
    author: SAP
    url: https://help.sap.com/docs/event-mesh/event-mesh/manage-webhooks
    type: official_docs
    published: 2025-12-01
    reliability: authoritative
  - id: src3
    title: "Real-Time NetSuite Data Synchronization: Enabling Event-Driven Integrations"
    author: Oracle
    url: https://blogs.oracle.com/developers/realtime-netsuite-data-synchronization-enabling-event-driven-integrations
    type: official_docs
    published: 2025-06-20
    reliability: authoritative
  - id: src4
    title: "Working with Webhooks in Dynamics 365 Business Central"
    author: Microsoft
    url: https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/api-reference/v2.0/dynamics-subscriptions
    type: official_docs
    published: 2025-10-01
    reliability: authoritative
  - id: src5
    title: "Workday API Integration Guide (In-Depth)"
    author: GetKnit
    url: https://www.getknit.dev/blog/workday-api-integration-in-depth
    type: technical_blog
    published: 2025-09-15
    reliability: moderate_high
  - id: src6
    title: "Acumatica Push Notifications via Business Events"
    author: Acumatica
    url: https://help.acumatica.com/Wiki/ShowWiki.aspx?pageid=7e137a19-be03-479f-b488-b9f3ab891c10
    type: official_docs
    published: 2025-03-01
    reliability: authoritative
  - id: src7
    title: "Events — Technical Documentation For IFS Cloud"
    author: IFS
    url: https://docs.ifs.com/techdocs/25r1/030_administration/090_automation_optimization/320_events/
    type: official_docs
    published: 2025-11-01
    reliability: authoritative
  - id: src8
    title: "Zoho ERP Webhooks — Workflow Actions"
    author: Zoho
    url: https://www.zoho.com/en-in/erp/help/automation/workflow-actions/webhooks.html
    type: official_docs
    published: 2025-06-01
    reliability: authoritative
---

# ERP Webhook & Outbound Callback Support Comparison (2026)

## TL;DR

- **Bottom line**: Only 4 of 12 major ERPs offer true native outbound webhook/push capabilities without add-ons: Dynamics 365 Business Central (subscription webhooks), Zoho (workflow webhooks), Acumatica (push notifications), and Salesforce (Outbound Messages). The rest require event bus infrastructure, custom scripting, or middleware.
- **Key limit**: Workday and Epicor Kinetic have NO native outbound push mechanism — you must poll or use iPaaS middleware to simulate webhooks.
- **Watch out for**: ERP vendors use "webhook" loosely — Salesforce Platform Events, SAP Event Mesh, and Oracle Business Events are event bus architectures requiring subscribers to connect via gRPC, AMQP, or dedicated clients, not simple HTTP POST callbacks.
- **Best for**: Architects evaluating which ERPs can push data in real-time vs. which require polling or middleware to achieve the same result.
- **Authentication**: Varies per system — OAuth 2.0 (Salesforce, D365), certificate-based (SAP BTP), token-based authentication (NetSuite TBA), or API keys (Zoho, Acumatica).

## 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), which is a different integration pattern. For deep-dive event architecture comparisons with protocol-level detail, see the related ERP Event-Driven Integration Comparison card.

| Property | Value |
|---|---|
| **Scope** | 12 ERP systems (Salesforce, SAP S/4HANA, Oracle ERP Cloud, NetSuite, D365 F&O, D365 BC, Workday, IFS Cloud, Epicor Kinetic, Sage Intacct, Zoho, Acumatica) |
| **Focus** | Outbound event delivery — webhook, push, event bus, polling |
| **Card Type** | Cross-system comparison |
| **Deployment Models** | Cloud, hybrid, on-premise variants noted |
| **Temporal Scope** | 2024-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, src5, src6, src7, src8]

| ERP System | Native Outbound Mechanism | Mechanism Type | Protocol | Requires Add-on? | Latency (Typical) |
|---|---|---|---|---|---|
| Salesforce | Outbound Messages (SOAP) | HTTP POST callback | SOAP/XML | No | 1-5s |
| Salesforce | Platform Events / CDC | Event bus (pub/sub) | gRPC (Pub/Sub API) | High-volume license for >100K/day | <1s-5s |
| SAP S/4HANA Cloud | SAP Event Mesh | Event bus (pub/sub) | AMQP / Webhook (HTTP POST) | Yes (BTP subscription) | 1-30s |
| Oracle ERP Cloud | Business Events | Event bus | Oracle Integration Cloud | Yes (OIC subscription) | 5-30s |
| NetSuite | SuiteScript User Events | Custom script (HTTP POST) | REST/HTTPS | No (SuiteCloud Plus recommended) | 1-10s |
| D365 Finance & Operations | Business Events / Data Events | Event bus | Azure Service Bus / HTTPS | No (Azure endpoint needed) | 2-15s |
| D365 Business Central | Webhook Subscriptions | HTTP POST callback | REST/JSON | No | 30s (batched) |
| Workday | None (polling only) | N/A | N/A | Middleware required | 1-15 min (poll interval) |
| IFS Cloud | Event Actions | Workflow-triggered HTTP POST | REST/HTTPS | No | 2-10s |
| Epicor Kinetic | None native (BPM workaround) | Custom code (REST call from BPM) | REST/HTTPS | No (requires customization) | 2-15s |
| Sage Intacct | Platform Services (limited) | Platform event triggers | REST/HTTPS | Custom Sender required | 5-30s |
| Zoho (Books/Inventory) | Workflow Webhooks | HTTP POST callback | REST/JSON | No | <1s-5s |
| Acumatica | Push Notifications | HTTP POST callback | REST/JSON | No | 1-10s |

## Rate Limits & Quotas

### Outbound Event Delivery Limits

| ERP System | Daily Event Limit | Per-Hour / Burst Limit | Retry Policy | Notes |
|---|---|---|---|---|
| Salesforce (Outbound Messages) | No hard daily limit | 100 concurrent deliveries | Retry for 24h on failure | Messages queue if endpoint down [src1] |
| Salesforce (Platform Events) | 100K standard; 10M+ with add-on | 250K/hour (high-volume) | At-least-once, 24h replay | Replay by replayId for recovery [src1] |
| SAP Event Mesh | Depends on BTP plan (10K-1M+/month) | Throttled per queue | Configurable retry + DLQ | Webhook subscriptions with retry count [src2] |
| Oracle ERP Cloud | No published hard limit | Throttled by OIC instance | Best-effort, manual replay | Requires OIC to route events externally |
| NetSuite (SuiteScript) | Limited by governance units (5K/scheduled script) | 10 concurrent HTTP calls per script | No built-in retry (custom implementation) | Each https.post() costs governance units [src3] |
| D365 F&O (Business Events) | No hard daily limit | Throttled by Azure endpoint | Retry configurable in Azure Service Bus | Failed events go to DLQ in Azure |
| D365 Business Central | No hard daily limit | 1,000 changes batch in 30s window | Retry for 36h (408, 429, 5xx) | Subscription auto-deleted if non-retryable error [src4] |
| Workday | N/A (polling only) | API rate limits apply to polling | N/A | PECI outbound is scheduled, not event-driven [src5] |
| IFS Cloud | No published hard limit | Limited by server resources | Configurable in event action | Event actions can call REST endpoints [src7] |
| Epicor Kinetic | No published limit for BPM calls | Limited by server resources | No built-in retry | Custom REST calls from BPM/Functions |
| Sage Intacct | No published limit | Throttled by API rate limits | No built-in retry | Custom Sender implementations only |
| Zoho | 500 webhooks/day (free), 5,000/day (paid) | Burst limits per plan | Retry 2x on failure | Workflow-based — limited to workflow triggers [src8] |
| Acumatica | No hard daily limit | Batch-triggered per GI refresh | Configurable retry attempts | Push Notification triggers on GI data changes [src6] |

## Authentication

| ERP System | Auth for Outbound Delivery | Callback Verification | Notes |
|---|---|---|---|
| Salesforce | N/A (SF initiates call) | Session ID in SOAP header | Endpoint must accept SOAP; verify SF IP ranges [src1] |
| SAP Event Mesh | OAuth 2.0 (BTP) | HMAC signature optional | Event Mesh webhook can include auth headers [src2] |
| Oracle ERP Cloud | OIC handles auth | OIC-managed | External endpoint auth configured in OIC connection |
| NetSuite | TBA or OAuth 2.0 | Custom header injection | SuiteScript can set Authorization header on outbound call [src3] |
| D365 F&O | Azure AD / SAS token | Azure Service Bus verification | Business Events use Azure endpoint auth |
| D365 Business Central | N/A (BC initiates call) | clientState secret in payload | Handshake validation required on subscription [src4] |
| Workday | N/A (polling) | N/A | External system authenticates to Workday API [src5] |
| IFS Cloud | Custom header in event action | No built-in verification | Workflow can set custom headers [src7] |
| Zoho | Custom header in webhook config | No built-in HMAC | Can include auth token in URL or headers [src8] |
| Acumatica | Custom header or URL token | No built-in HMAC | Push Notification URL can include auth parameters [src6] |

### Authentication Gotchas

- Salesforce Outbound Messages send a session ID that the receiving endpoint can use to call back into Salesforce — but this session expires, so do not rely on it for delayed processing [src1]
- D365 Business Central subscriptions require a handshake: the subscriber must echo back the validationToken in the body with HTTP 200 within a few seconds, or the subscription is rejected [src4]
- SAP Event Mesh webhook subscriptions support optional HMAC signatures, but many implementations skip this — always enable HMAC in production [src2]

## Constraints
<!-- Agents: read this section before recommending any integration approach from this unit.
     These are hard constraints that must not be violated. -->

- Workday has NO native outbound push mechanism — the only options are scheduled PECI extracts or polling the REST/SOAP API from the external side [src5]
- Epicor Kinetic has no built-in webhook or event push — outbound calls require custom BPM code (Epicor Functions) that make REST calls during transaction processing
- Salesforce Outbound Messages are SOAP-only — if your endpoint only accepts REST/JSON, you need middleware or Platform Events + a custom subscriber
- D365 Business Central webhook notifications are batched with a 30-second delay by default — if something changes, BC waits 30s before sending the notification [src4]
- NetSuite outbound HTTP calls from SuiteScript consume governance units — a scheduled script gets 5,000 units, and each https.post() costs ~10 units, effectively limiting you to ~500 outbound calls per script execution [src3]
- SAP Event Mesh requires a separate BTP subscription — it is not included in the S/4HANA Cloud license [src2]
- Zoho webhook limits are plan-dependent: free plans get 500 webhooks/day, paid plans up to 5,000/day [src8]
- Oracle ERP Cloud Business Events cannot directly POST to external URLs — they must route through Oracle Integration Cloud (OIC) or Oracle's event infrastructure

## 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 business 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 extract, 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) or D365 F&O (Azure Service Bus 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 System | Native HTTP Webhook? | Event Bus? | Polling Required? | Best Real-Time Option | Delivery Guarantee |
|---|---|---|---|---|---|
| **Salesforce** | Yes (Outbound Messages, SOAP) | Yes (Platform Events, CDC) | No | Platform Events + Pub/Sub API | At-least-once (replay) |
| **SAP S/4HANA** | Via Event Mesh (add-on) | Yes (Event Mesh, AEM) | Fallback | Event Mesh webhook subscription | Configurable (DLQ) |
| **Oracle ERP Cloud** | No (requires OIC) | Yes (Business Events) | Fallback | Business Events via OIC | Best-effort |
| **NetSuite** | Via SuiteScript (custom) | No | Fallback | User Event Script → https.post() | No (custom retry) |
| **D365 F&O** | Via Azure endpoints | Yes (Business Events, Data Events) | No | Business Events → Azure Service Bus | At-least-once (Azure DLQ) |
| **D365 Business Central** | Yes (Subscription API) | No | No | Webhook Subscriptions (30s batch) | At-most-once (36h retry) |
| **Workday** | No | No | Yes (required) | Poll REST API | N/A |
| **IFS Cloud** | Via Event Actions | No | Fallback | Event Action → REST POST | Best-effort |
| **Epicor Kinetic** | No (BPM workaround) | No | Fallback | BPM → REST POST (custom) | No (custom retry) |
| **Sage Intacct** | No (Custom Sender) | No | Recommended | Poll Web Services API | N/A |
| **Zoho** | Yes (Workflow Webhooks) | No | No | Workflow → Webhook POST | Best-effort (2 retries) |
| **Acumatica** | Yes (Push Notifications) | No | No | GI Push Notification → HTTP POST | Configurable retries |

[src1, src2, src3, src4, src5, src6, src7, src8]

## Cross-System Comparison

| Capability | Salesforce | SAP S/4HANA | Oracle ERP Cloud | NetSuite | D365 F&O | D365 BC | Workday | IFS Cloud | Epicor Kinetic | Sage Intacct | Zoho | Acumatica |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| **Native outbound webhook** | Outbound Messages (SOAP) | No (Event Mesh add-on) | No (OIC required) | No (SuiteScript custom) | No (Azure endpoints) | Yes (Subscription API) | No | Event Actions (REST) | No (BPM custom) | No | Yes (Workflow) | Yes (Push Notifications) |
| **Event bus available** | Platform Events, CDC | Event Mesh, AEM | Business Events | No | Business Events, Data Events | No | No | No | No | No | No | No |
| **Protocol** | SOAP (OM), gRPC (Pub/Sub) | AMQP, HTTP (webhook) | OIC (REST/SOAP) | HTTPS (SuiteScript) | Azure Service Bus, HTTPS | REST/JSON | N/A | REST/HTTPS | REST/HTTPS | REST/HTTPS | REST/JSON | REST/JSON |
| **Setup complexity** | Low (OM), Medium (PE) | High (BTP + Event Mesh) | High (OIC config) | Medium (SuiteScript) | Medium (Azure setup) | Low | N/A | Medium | High (BPM dev) | High | Low | Low-Medium |
| **Latency** | 1-5s | 1-30s | 5-30s | 1-10s | 2-15s | ~30s (batched) | 1-15 min (poll) | 2-10s | 2-15s | 5-30s | <5s | 1-10s |
| **Delivery guarantee** | At-least-once (PE) | Configurable (DLQ) | Best-effort | None (custom) | At-least-once (Azure DLQ) | At-most-once (36h retry) | N/A | Best-effort | None (custom) | None | Best-effort (2x retry) | Configurable |
| **Replay/recovery** | Yes (24h replay by ID) | Yes (DLQ + replay) | Manual (OIC) | No | Yes (Azure DLQ) | No | N/A | No | No | No | No | No |
| **Event filtering** | By object/field (CDC) | By event type | By business event ID | By script logic | By category | By resource | N/A | By event type | By BPM logic | By trigger type | By workflow rule | By GI criteria |
| **Max payload size** | 1 MB (Platform Event) | 1 MB (Event Mesh) | Varies by event | Custom (script-defined) | 1 MB | Collection of entity changes | N/A | Custom | Custom | Custom | Custom (JSON) | Custom (GI fields) |
| **Additional cost** | High-volume PE license | BTP subscription required | OIC subscription | Included (SuiteCloud Plus) | Azure resource costs | Included | N/A | Included | Included | Included | Plan-dependent | Included |
| **Best for** | Complex event flows | SAP-centric landscapes | Oracle ecosystem | Mid-market custom | Microsoft/Azure shops | SMB real-time sync | N/A (use polling) | IFS-centric workflows | Manufacturing events | Financial triggers | SMB workflows | Mid-market push |

[src1, src2, src3, src4, src5, src6, src7, src8]

## Step-by-Step Integration Guide

### 1. Evaluate your ERP's outbound capabilities

Before designing your integration, classify your ERP into one of three tiers based on the comparison table above. [src1, src4, src6, src8]

**Tier 1 — Native HTTP Webhooks** (D365 BC, Zoho, Acumatica, Salesforce Outbound Messages):
Your ERP can push HTTP POST requests to external URLs natively. Start here.

**Tier 2 — Event Bus or Custom Script** (Salesforce Platform Events, SAP Event Mesh, Oracle via OIC, NetSuite SuiteScript, D365 F&O, IFS Cloud):
Your ERP emits events to a bus or can be scripted to push. You need a subscriber or custom script.

**Tier 3 — Polling Required** (Workday, Sage Intacct, Epicor Kinetic without customization):
No push mechanism. Design a polling integration with change detection.

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

### 2. For Tier 1 (native webhooks): Configure the subscription

Example: D365 Business Central webhook subscription. [src4]

```bash
# Register a webhook subscription for Sales Orders in D365 Business Central
curl -X POST "https://{tenant}.api.businesscentral.dynamics.com/v2.0/{environment}/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"
  }'
# Response includes subscriptionId — store this for management
```

**Verify**: POST to the subscription endpoint → BC sends a validation request to your notificationUrl with validationToken → your endpoint echoes it back with HTTP 200.

### 3. For Tier 2 (event bus): Set up subscriber infrastructure

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

```python
# Input: Salesforce Connected App credentials
# Output: Real-time event stream from Platform Events

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="integration@yourorg.com"
)

# Subscribe to a custom Platform Event
for event in client.subscribe("/event/Order_Created__e", replay_preset="LATEST"):
    # Process each event as it arrives
    print(f"Order created: {event.payload}")
    # Forward to your webhook endpoint if needed
```

**Verify**: Publish a test Platform Event in Salesforce → your subscriber receives it within 1-5 seconds.

### 4. For Tier 3 (polling): Implement efficient change detection

Example: Workday — poll for recent changes. [src5]

```python
# Input: Workday API credentials, last poll timestamp
# Output: Changed records since last poll

import requests
from datetime import datetime, timedelta

def poll_workday_changes(tenant, token, last_poll_time):
    """Poll Workday for worker changes since 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,
        # Workday REST API supports effective date filtering
    }
    response = requests.get(url, headers=headers, params=params)
    response.raise_for_status()
    return response.json().get("data", [])

# Poll every 5 minutes — this is the best you can do with Workday
# Store last_poll_time in persistent storage for recovery
```

**Verify**: Run the poll → compare record counts with Workday UI → confirm delta detection works.

## Error Handling & Failure Points

### Common Error Codes

| ERP | Error | Meaning | Cause | Resolution |
|---|---|---|---|---|
| Salesforce | OUTBOUND_MSG_FAILED | Outbound Message delivery failed | Endpoint unreachable or timed out | Check endpoint URL, ensure it accepts SOAP; SF retries for 24h [src1] |
| D365 BC | Subscription deleted | Non-retryable error code returned | Endpoint returned 4xx (not 408/429) or 3xx | Fix endpoint to return 200 on success, 5xx for temporary failures [src4] |
| NetSuite | SSS_REQUEST_LIMIT_EXCEEDED | Governance limit reached | Too many https.post() calls in script | Batch outbound calls or switch to scheduled script [src3] |
| SAP Event Mesh | 429 | Rate limit exceeded | Too many webhook deliveries | Increase Event Mesh plan or implement consumer-side backpressure [src2] |
| Acumatica | Push notification failed | Target URL unreachable | Endpoint down or auth failure | Check Push Notification configuration in SM302000, verify URL [src6] |
| Zoho | WEBHOOK_LIMIT_REACHED | Daily webhook quota exceeded | Exceeded plan limit (500 or 5,000/day) | Upgrade plan or batch notifications [src8] |

### Failure Points in Production

- **D365 BC subscription silently deleted**: If your endpoint returns any non-retryable HTTP status (anything other than 408, 429, 5xx), BC permanently deletes the webhook subscription without notification. Fix: `Always return 200 on success, 500 for temporary failures. Monitor subscription existence with periodic GET /subscriptions.` [src4]
- **Salesforce Outbound Messages queue indefinitely**: If the endpoint is down, messages queue for 24h with retries. If the endpoint comes back but is slow, the queue can overwhelm it. Fix: `Implement rate limiting on the receiving endpoint. Process messages asynchronously (acknowledge immediately, process in background).` [src1]
- **NetSuite governance exhaustion mid-batch**: A User Event Script making outbound calls for each record save can exhaust governance units when bulk imports trigger it. Fix: `Use nlapiScheduleScript() to defer outbound calls to a Scheduled Script with higher governance limits (5,000 units).` [src3]
- **SAP Event Mesh webhook delivery delays under load**: During peak periods, Event Mesh webhook delivery can experience 30+ second delays. Fix: `Switch to AMQP protocol for lower latency, or implement queue-based consumption instead of webhook push.` [src2]
- **Acumatica Push Notifications trigger on GI refresh, not real-time**: Push Notifications are tied to Generic Inquiry evaluation cycles, not individual record saves. If the GI refresh interval is long, notifications are delayed. Fix: `Configure the GI with appropriate refresh settings or use Business Events with custom actions for true real-time needs.` [src6]

## Anti-Patterns

### Wrong: Assuming all ERPs have Stripe-style webhooks

```
// BAD — designing integration expecting simple HTTP POST from any ERP
// This works for D365 BC, Zoho, Acumatica, but fails for 8+ other ERPs
app.post('/webhook/erp', (req, res) => {
  const event = req.body;
  processERPEvent(event);
  res.status(200).send('OK');
});
// Salesforce sends SOAP XML, not JSON
// SAP sends via AMQP, not HTTP
// 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' }),
};
// Each adapter normalizes to a common internal event format
```

### Wrong: Using SuiteScript User Events for high-volume outbound calls

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

### Correct: Batch and defer outbound calls in NetSuite

```javascript
// GOOD — queue records, send in batch via Scheduled Script
function afterSubmit(context) {
  // Store record ID in a custom queue record (cheap — 10 governance units)
  var queue = record.create({ type: 'customrecord_outbound_queue' });
  queue.setValue({ fieldId: 'custrecord_record_id', value: context.newRecord.id });
  queue.save();
}
// Scheduled Script processes queue in bulk with 5,000 governance units
```

### Wrong: Not handling D365 BC subscription expiry

```javascript
// BAD — register webhook once and forget about it
// D365 BC subscriptions expire after 3 days if not renewed
await registerWebhook(resource, notificationUrl);
// 3 days later: subscription silently expires, no more notifications
```

### Correct: Implement subscription renewal for D365 BC

```javascript
// GOOD — renew subscription before expiry
// D365 BC subscriptions have expirationDateTime (max 3 days)
async function maintainSubscription(subscriptionId) {
  // Renew every 2 days (before 3-day expiry)
  const renewed = await fetch(`/subscriptions(${subscriptionId})`, {
    method: 'PATCH',
    body: JSON.stringify({
      expirationDateTime: new Date(Date.now() + 3 * 86400000).toISOString()
    })
  });
  if (renewed.status === 404) {
    // Subscription was deleted — re-register
    await registerWebhook(resource, notificationUrl);
  }
}
// Run on a 2-day interval (cron, Azure Timer, etc.)
```

## Common Pitfalls

- **Assuming "webhooks" means HTTP POST everywhere**: Each ERP's "webhook" or "event" mechanism differs fundamentally in protocol, payload format, and delivery semantics. Salesforce Outbound Messages use SOAP XML. SAP Event Mesh uses AMQP. Oracle routes through OIC. Fix: `Read the Cross-System Comparison table and implement per-ERP adapters.` [src1, src2]
- **Ignoring delivery guarantee differences**: Salesforce Platform Events offer at-least-once with 24h replay. D365 BC offers at-most-once with 36h retry. Workday offers nothing. Fix: `For zero-loss requirements, use systems with replay capability (Salesforce, SAP Event Mesh, D365 F&O via Azure DLQ) and implement idempotent event processing.` [src1, src4]
- **Not accounting for event batching delays**: D365 Business Central deliberately batches webhook notifications with a 30-second delay. If >1,000 records change in that window, a single collection notification is sent instead of individual ones. Fix: `Design your endpoint to handle both single and collection notifications. Don't assume 1:1 event-to-notification ratio.` [src4]
- **Exceeding NetSuite governance on outbound calls**: Each https.post() in SuiteScript costs governance units. A User Event Script triggered by a CSV import of 5,000 records can exhaust the 1,000-unit limit after just ~100 outbound calls. Fix: `Use Map/Reduce scripts (10,000 units) or Scheduled Scripts (5,000 units) for bulk outbound scenarios. Queue events in a custom record and process them in batch.` [src3]
- **Forgetting that Workday requires polling**: Workday has no event-driven outbound mechanism. PECI (Payroll Effective Change Interface) is scheduled, not real-time. Fix: `Design a polling architecture from the start. Use Workday Report-as-a-Service (RaaS) with timestamp-based filtering. Poll every 5-15 minutes for near-real-time.` [src5]
- **SAP Event Mesh without BTP budget**: Event Mesh is a separate BTP service with its own pricing. Many projects discover this after designing an event-driven architecture. Fix: `Confirm BTP licensing and Event Mesh quota before committing to event-driven SAP integration. For budget-constrained projects, consider polling OData APIs instead.` [src2]

## Diagnostic Commands

```bash
# Salesforce: Check Outbound Message delivery status
# Setup → Outbound Messages → View Message Delivery Status
curl -H "Authorization: Bearer $SF_TOKEN" \
  "https://yourorg.my.salesforce.com/services/data/v62.0/query?q=SELECT+Id,Name+FROM+OutboundMessage+LIMIT+5"

# 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 in SuiteScript logs
# Navigation: Customization → Scripting → Script Execution Log
# Filter by Script type = "User Event" and check governance remaining column

# 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 configuration
# Navigation: System → Integration → Push Notifications (SM302000)
# Check Status column for each notification — should show "Active"

# Zoho: Check webhook execution log
# Navigation: Setup → Automation → Workflow Rules → select rule → View Webhook Log
```

## Version History & Compatibility

| ERP | Feature | Introduced | Current Status | Notes |
|---|---|---|---|---|
| Salesforce | Outbound Messages | ~2006 | GA (legacy, still supported) | SOAP-only; Platform Events preferred for new development |
| Salesforce | Platform Events | Spring '17 | GA | Replaced Streaming API for event delivery |
| Salesforce | Pub/Sub API (gRPC) | Spring '22 | GA | Replaced CometD-based Streaming API |
| SAP | Event Mesh | 2020 | GA | Requires BTP; replaced SAP Enterprise Messaging branding |
| SAP | Advanced Event Mesh (Solace) | 2023 | GA | Enterprise tier with guaranteed delivery |
| Oracle ERP Cloud | Business Events | 2019 | GA | Requires OIC for external delivery |
| NetSuite | SuiteScript 2.0 | 2016 | GA | https module for outbound calls |
| D365 F&O | Business Events | 10.0.22 (2022) | GA | Azure Service Bus, HTTPS, Power Automate endpoints |
| D365 F&O | Data Events | 10.0.39 (2024) | GA | CRUD-level events, more granular than Business Events |
| D365 BC | Webhook Subscriptions | v1.0 API (2018) | GA | v2.0 API is current; 30s batching, 3-day subscription expiry |
| IFS Cloud | Event Actions | IFS Cloud 21R2 | GA | REST POST via workflow actions |
| Acumatica | Push Notifications | 2019 R1 | GA | Based on Generic Inquiries |
| Zoho | Workflow Webhooks | ~2018 | GA | Plan-based daily limits |

### Deprecation Notes

- Salesforce deprecated CometD-based Streaming API in favor of Pub/Sub API (gRPC). Existing Streaming API integrations still work but receive no new features. Migrate to Pub/Sub API for new development. [src1]
- SAP rebranded Enterprise Messaging to Event Mesh in 2022. API endpoints changed. Old Enterprise Messaging subscriptions were auto-migrated but new development should use Event Mesh endpoints. [src2]

## When to Use / When Not to Use

| Use When | Don't Use When | Use Instead |
|---|---|---|
| You need to compare webhook support across multiple ERPs for architecture decisions | You need deep-dive on a single ERP's event system | business/erp-integration/erp-event-driven-comparison/2026 |
| You're evaluating which ERP to select and real-time integration is a key requirement | You've already chosen an ERP and need implementation details | System-specific API capability card |
| You need to determine if an ERP requires middleware for push notifications | You need webhook payload schemas and field mappings | System-specific integration playbook |
| You're building an iPaaS adapter layer that supports multiple ERPs | You only integrate with one ERP | Single-system event configuration guide |

## Important Caveats

- Webhook/event capabilities change with each ERP release — features listed as "not available" (e.g., Workday, Epicor) may gain support in future releases. Always verify against the vendor's current release notes.
- "Native webhook" definitions vary by vendor — this card classifies only simple HTTP POST callbacks as "native webhooks." Event bus architectures (Platform Events, Event Mesh, Business Events) require dedicated subscriber infrastructure.
- Delivery guarantees are best-case scenarios — network issues, endpoint downtime, and vendor infrastructure problems can cause missed events even in "at-least-once" systems. Always implement idempotent event processing.
- Pricing and licensing for event features are not covered in detail — SAP Event Mesh, Salesforce high-volume Platform Events, and Oracle OIC all require separate licensing.
- This card covers outbound (ERP-to-external) direction only. Inbound webhook support (external-to-ERP) is a separate integration concern with different capabilities per system.
- Latency figures are typical ranges observed in production environments — actual latency depends on payload size, network conditions, endpoint response time, and system load.

## Related Units

- [ERP Event-Driven Integration Comparison](/business/erp-integration/erp-event-driven-comparison/2026) — deeper comparison of event bus architectures (Platform Events vs Event Mesh vs CDC vs Business Events) across 4 major ERPs
