Webhooks in Dynamics 365 Sales use the Service Endpoint + Plugin Registration Tool (or Power Platform CLI) pipeline, not a pure REST webhook subscription. Understanding that architecture is essential before you swap out polling.
How D365 Webhook Delivery Actually Works
D365 posts to your endpoint synchronously during the platform event pipeline. If your endpoint returns anything other than 2xx within the timeout window (~60 seconds, verify in your version), the platform marks the step as failed. Critically: D365 does not have a built-in retry queue with exponential backoff. Failed webhook calls surface as Plugin Trace Log entries and System Job failures, but the event is not automatically replayed. This is your primary reliability risk.
Webhook Registration (Plugin Registration Tool)
Service Endpoint:
- Contract: WebHook
- URL: https://your-middleware.example.com/d365-hook/account
- Auth: HttpHeader → X-API-Key: <secret>
Step Registration:
- Message: Update
- Primary Entity: account
- Filtering Attributes: name, telephone1, address1_city, <your critical fields>
- Execution Mode: Asynchronous ← use this, not Synchronous
- Deployment: Server
Running the step Asynchronous offloads execution to the async service, decouples it from the user transaction, and allows the System Job to surface failures—but still does not auto-retry.
Handling Delivery Failures
Your middleware/endpoint layer must carry the reliability burden:
- Implement an idempotent receiver keyed on
x-ms-dynamics-request-id (header injected by D365) to safely handle duplicates if you build your own retry.
- Front your endpoint with a durable queue (Azure Service Bus, SQS, etc.). D365 posts → queue ingests → downstream consumer processes. Queue handles your endpoint unavailability window cleanly.
- Enable dead-letter queues and alert on them. This is your data-loss safety net.
- Log
organizationid + entityid + changedfields immediately on receipt before any processing.
Hybrid Pattern for Your 30-Second SLA
Neither pure webhooks nor pure polling alone is optimal here. Use both:
| Layer |
Mechanism |
Purpose |
| Primary |
Webhooks (async step) |
Sub-30s delivery on happy path |
| Recovery |
Change tracking poll (15–30 min interval) |
Catch missed events, gap-fill |
| Validation |
modifiedon watermark comparison |
Detect drift between DW and D365 |
The OData change tracking endpoint ($select=name,modifiedon&$deltatoken=...) remains your consistency guarantee. Reduce polling to 15–30 minutes—you’re not relying on it for latency, only for gap recovery.
Version Compatibility Note
Webhook behavior, async service throughput limits, and System Job retention policies vary between on-premises 9.x and online. Verify your async service concurrency limits and System Job purge schedules in your specific deployment—online environments purge completed/failed jobs on a rolling schedule that can affect your failure audit window.
Operational Reality
Webhook-only for a DW sync with no retry infrastructure is fragile. The durable queue pattern eliminates the false choice between “elegant but risky” and “polling forever.”
This draft is based on general Microsoft Dynamics 365 Sales knowledge. It has not been verified against your specific version and environment. Practitioners: verify the steps and share your experience below.