The Digital Developer Blog - Blogs by Computan

How to Sync Microsoft Dynamics 365 and HubSpot in Real Time Using Custom Middleware

Written by Simranjeet Singh | August 24, 2026 at 2:31 PM

Sales runs in Dynamics 365. Marketing runs in HubSpot. The moment those two systems fall out of step, reps are calling stale leads and marketing is sending offers to accounts that already closed. Connecting the two platforms sounds simple on paper, but real-time property synchronization is a different problem than "connect two APIs and let data flow." It requires an event layer, a processing layer, and a plan for the things that inevitably go wrong: duplicate events, sync loops, and missed updates.

This guide walks through how a custom middleware architecture keeps Dynamics 365 and HubSpot in sync in near real time, using Dataverse webhooks, a Laravel processing layer, and a reconciliation job as a safety net.

TL;DR

  • Native and no-code HubSpot-Dynamics 365 connectors run on a schedule and only support standard fields, which leaves data stale for teams making decisions right now.[1][2]
  • Real-time synchronization needs an event layer, not just two APIs pointed at each other. Dataverse webhooks fill that role.[3][4]
  • A Laravel middleware layer receives the webhook, processes it asynchronously through a queued job, applies field mapping, and updates the matching HubSpot record through the API.[12][13]
  • Loop prevention and duplicate-event protection require tracking sync history and the origin of a change, not just catching the update itself.[9][15]
  • Dataverse Change Tracking should run alongside webhooks as a reconciliation layer, catching anything a webhook missed.[7][8]

Why Sync Microsoft Dynamics 365 and HubSpot in Real Time?

Sales and marketing teams need to be looking at the same version of the truth. When an Account, Contact, or Opportunity changes in Dynamics 365, whoever is working that record in HubSpot needs to see the update quickly, not the next morning after a batch job runs.

  • Keeping sales and marketing data consistent avoids the awkward moment where marketing nurtures a contact sales already closed.
  • Reducing manual data entry cuts down on the copy-paste errors that come from someone updating one system and forgetting the other.
  • Near real-time updates on Accounts, Contacts, and Opportunities mean HubSpot workflows, lead scoring, and reporting are working from current information instead of a stale snapshot.

Why Standard Dynamics 365-HubSpot Integrations May Not Be Enough

HubSpot's native Dynamics 365 integration and most no-code connectors cover the basics well, but they run into limits fast once a business has custom objects, complex field logic, or specific rules about what should and should not sync.

  • Generic connectors typically sync one object at a time, and updates land on a schedule rather than instantly, so "real-time" often means a few minutes of lag at best.[2]
  • Lookup fields, multi-select options, and certain custom entities frequently fall outside what an out-of-the-box connector can map.[2]
  • There is no room for custom business logic. If a property should only sync under certain conditions, or a value needs to be transformed before it lands in HubSpot, a closed connector cannot do that.
  • Preventing duplicate updates and sync loops (where system A updates system B, which updates system A again) is not something most off-the-shelf tools expose control over.

A custom API integration solves these problems by giving a development team full control over the data flow, the business logic, and what triggers a sync, at the cost of needing developer resources to build and maintain it.[2]

How a Custom Middleware Architecture Connects Dynamics 365 and HubSpot

The architecture that makes real-time sync possible looks like this:

Dynamics 365 → Dataverse → Webhook → Laravel Middleware → HubSpot API

  • Dynamics 365 is the source system where the change originates.
  • Dataverse acts as the event layer, detecting the change and preparing a notification.
  • Webhooks push that notification out in real time rather than waiting for a poll.[3]
  • Laravel middleware receives the event, validates it, and processes it through a background job.
  • The HubSpot API receives the mapped, validated update and applies it to the matching record.
  • A middleware database holds sync history and ID mappings between the two systems, which is what makes matching, loop prevention, and reconciliation possible later.

This is the strongest part of the architecture because every other piece (field mapping, duplicate protection, retries, reconciliation) hangs off of it.

How to Configure Dataverse Webhooks for Dynamics 365 Changes

Dataverse lets you register a webhook that fires an HTTP POST to an external endpoint whenever a specific operation happens on a table, such as an update to an Account, Contact, or Opportunity.[4] Setting this up involves a few steps:

  • Preparing Dataverse permissions and confirming the app user has the access it needs.
  • Connecting the Plug-in Registration Tool (PRT) to the correct Dynamics 365 environment.[3]
  • Registering the webhook endpoint, which requires a name, an endpoint URL, and an authentication method the receiving service expects.[3]
  • Securing the webhook configuration so only Dataverse can call the endpoint.
  • Filtering notifications so only the properties that matter for the sync trigger a webhook call, instead of every field change on the record.

Registering a webhook through PRT works the same way as registering a plug-in step: pick the message (create, update, delete), the table, and the fields to watch.[4]

How to Trigger HubSpot Updates When Dynamics 365 Properties Change

Once webhooks are registered, each entity type needs its own notification setup and its own field mapping logic.

Syncing Dynamics 365 Account Changes to HubSpot

Account-level changes (name, industry, address, ownership) typically map to HubSpot Companies. Filtering the webhook to only the Account properties that actually feed HubSpot fields keeps the middleware from processing noise.

Syncing Dynamics 365 Contact Changes to HubSpot

Contact changes map to HubSpot Contacts. This is usually the highest-volume entity in the sync, so it benefits the most from queued, asynchronous processing rather than handling each update inline.

Syncing Dynamics 365 Opportunity Changes to HubSpot

Opportunity stage and amount changes typically map to HubSpot Deals. Because deal stage often drives downstream workflows and reporting in HubSpot, these updates are usually the most time-sensitive of the three.

Building a Laravel Middleware Layer for Dynamics 365 and HubSpot

The middleware is where the actual work happens. A Laravel webhook handler generally does the following:

  • Receives the webhook event and returns a fast response so Dataverse does not treat the call as failed.
  • Validates the incoming notification before doing anything with it.
  • Identifies the changed Dynamics record and which entity type it belongs to.
  • Hands the event off to a queued job rather than processing it inline, which is the standard pattern for webhook-heavy Laravel applications.[12][13]
  • Calls the HubSpot API from within that background job.

Separating webhook reception from processing matters for response times. If Dataverse is waiting on a slow HubSpot API call before it gets a 200 response back, that is a fragile design. Queuing the work lets the endpoint acknowledge the event immediately and process it a moment later, with retry logic built in if something downstream fails.[13][14]

How to Map Dynamics 365 Fields to HubSpot Properties

Field mapping is where most of the "custom" in custom middleware actually lives:

  • Creating a mapping strategy that covers both standard and custom properties on each side.
  • Handling differences in data formats, such as picklists in Dynamics that need to become specific HubSpot property values.
  • Mapping the IDs between systems so a Dynamics record and its HubSpot counterpart can always be found again.
  • Managing value transformations, like currency formatting or date conversions, consistently in one place instead of scattered across the codebase.

How to Match Dynamics 365 Records With Existing HubSpot Records

Before the middleware can update a HubSpot record, it has to find the right one. This is where a lot of integrations go wrong.

  • Using stable CRM IDs (not names or email addresses alone) as the primary match key.
  • Resolving IDs locally first, against the middleware's own mapping database, before ever calling out to Dynamics or HubSpot.
  • Maintaining that middleware mapping database as the source of truth for "this Dynamics record equals this HubSpot record."
  • Avoiding unnecessary Dynamics 365 API calls by caching what the middleware already knows instead of re-fetching it on every sync.

This local-first approach is what keeps a real-time sync fast and within API rate limits as record volume grows.

How to Prevent Duplicate Updates and Infinite Sync Loops

Sync loops happen when an update from Dynamics writes to HubSpot, and something about that write looks like a new change to the sync, which triggers a write back to Dynamics, which triggers another update to HubSpot, and so on.

  • Tracking the source of every update (which system it originated from) is the core defense against loops.[15]
  • Maintaining sync history in the middleware database, including a last-synced timestamp per record.
  • Using that last-synced information to recognize "this change is just an echo of a sync we already processed" and skip it.
  • Protecting against duplicate webhook events, since most webhook providers guarantee at-least-once delivery, not exactly-once, which means the same event can legitimately arrive more than once.[9][11]

The standard pattern is to assign or read a unique event identifier, check it against a table of already-processed events before doing any work, and treat a repeat as a no-op rather than a new update.[10][11]

How to Handle Failed Webhooks, Retries, and Integration Errors

Things will fail. APIs time out, tokens expire, rate limits get hit. A production-ready middleware layer plans for it:

  • Logging every synchronization event, successful, failed, or skipped, with enough detail to debug it later.
  • Distinguishing temporary API failures (which should retry) from permanent ones (which should not retry forever).
  • Building retry mechanisms with backoff, so a failing downstream service does not get hammered with immediate repeat attempts.[13]
  • Making sure retries do not cause duplicate processing, which loops back to the idempotency work described above.[9]
  • Creating logs that are actually useful for troubleshooting, not just a raw dump of every payload.

How to Add Reconciliation to a Real-Time CRM Integration

Even a well-built webhook system will occasionally miss an event, whether from a dropped connection, a deployment window, or a webhook that was misconfigured for a short period. Real-time sync needs a backup mechanism.

  • Dataverse Change Tracking lets an external system query for everything that changed since the last check, using a data token instead of a full re-scan.[7]
  • Running a periodic reconciliation job against Change Tracking catches anything the webhook layer missed.[7][8]
  • A naive polling approach based on a "modified since" filter has real gaps, deletions do not show up, and a modified date can be overridden, which is exactly why a dedicated change tracking feature exists instead.[8]

Real-time webhooks plus periodic reconciliation is a more resilient architecture than either approach on its own.

How to Test a Real-Time Dynamics 365 and HubSpot Integration

Before anything goes to production, testing needs to cover the full surface area of the integration, not just the happy path:

  • Account, Contact, and Opportunity property changes, tested end to end
  • Webhook delivery and payload accuracy
  • Field mapping correctness, including edge cases like blank or null values
  • HubSpot record matching, especially for records that do not have a clean ID match yet
  • Duplicate events, sent deliberately to confirm the middleware ignores the repeat
  • Failed API requests and how the system responds
  • Retry behavior under simulated downtime
  • Sync-loop prevention, by making a change in HubSpot and confirming it does not bounce back and forth

Deploying a Production-Ready Dynamics 365 to HubSpot Integration

Moving from staging to production is its own checklist:

  • Production webhook configuration, pointed at the live endpoint with the right authentication
  • Environment settings separated cleanly from staging
  • Background queues sized and monitored for the expected event volume
  • Logging that is actually reviewed, not just written
  • Security review of the webhook endpoint and credentials
  • Monitoring in place before go-live, not added after the first incident

Real-Time Sync vs. Scheduled Dynamics 365 and HubSpot Synchronization

Factor Scheduled Sync Real-Time Middleware
Data freshness Delayed Near real time
Custom business logic Limited High flexibility
Field mapping Varies by connector Fully customizable
Error handling Depends on connector Customizable
Duplicate protection Limited Can be designed into middleware
Reconciliation Depends on platform Can be built in

When Should You Build a Custom Dynamics 365 and HubSpot Integration?

A custom middleware approach is not the right call for every team. It tends to make sense when a business has:

  • Complex field mappings that a standard connector cannot express
  • Custom objects or custom properties that need to sync alongside standard fields
  • A genuine real-time requirement, not just "close enough within an hour"
  • Existing middleware infrastructure it wants to extend rather than replace
  • A need for detailed, queryable logging of every sync event
  • Strict duplicate prevention requirements
  • Custom authentication or security requirements that off-the-shelf connectors do not support
  • Business-specific synchronization rules, like syncing only certain deal stages or certain account types

For businesses looking for a reliable web development and integration company in Canada, Computan brings deep experience in building custom digital solutions and connecting complex business systems. Computan has been part of the HubSpot community since 2015 and builds 20-25 custom integrations every month between HubSpot and accounting, CRM, ERP, and SaaS platforms. 

Frequently Asked Questions About Dynamics 365 and HubSpot Integration

Can Dynamics 365 and HubSpot sync data in real time?

Yes. HubSpot's native connector and most no-code tools sync on a schedule, which is near real time at best.[2] True real-time sync requires an event-driven layer, typically Dataverse webhooks paired with custom middleware that processes and forwards the change immediately.

How do I connect Dynamics 365 to HubSpot?

The simplest path is HubSpot's native Dynamics 365 integration from the App Marketplace, which covers standard objects and fields.[1] For custom fields, complex logic, or true real-time updates, a custom middleware layer built on Dataverse webhooks and the HubSpot API is the more capable option.

What is Dataverse used for in a Dynamics 365 HubSpot integration?

Dataverse is the underlying data platform for Dynamics 365. It is where webhooks get registered and where Change Tracking lives, which makes it the event source for a real-time integration and the reconciliation source for catching anything the event layer missed.[4][7]

Can I sync custom Dynamics 365 properties to HubSpot?

Yes, but it usually requires custom middleware. Native and no-code connectors are typically limited to standard fields and basic data types, so lookup fields, multi-select options, and custom entities often need a custom field-mapping layer to sync correctly.[2]

How do I prevent duplicate records when syncing Dynamics 365 and HubSpot?

Match records on stable CRM IDs rather than names or emails, maintain a middleware mapping table between the two systems, and treat repeated webhook events as no-ops by checking a processed-events table before taking any action.[9][10]

Do I need middleware for a Dynamics 365 and HubSpot integration?

Not always. If standard objects and a few minutes of sync delay are acceptable, HubSpot's native connector or a no-code platform can cover it. Middleware becomes necessary once real-time updates, custom fields, custom business logic, or strict duplicate and loop prevention are requirements.[2]

Conclusion

Real-time synchronization between Dynamics 365 and HubSpot requires more than connecting two APIs. Webhooks provide the event-driven layer that makes near-instant updates possible, but middleware is what actually makes the integration trustworthy: it controls field mapping, record matching, retries, logging, and the rules that keep updates from looping back on themselves. Pairing real-time webhooks with a periodic reconciliation job against Dataverse Change Tracking closes the gap for anything the event layer misses, which is what turns a fast integration into a reliable one.

Sources

  1. HubSpot Knowledge Base: Connect HubSpot and Microsoft Dynamics 365
  2. Rand Group: Dynamics 365 and HubSpot Integration
  3. Microsoft Learn: Register a WebHook (Power Apps Developer Guide)
  4. Microsoft ISE Developer Blog: Plugins in Dataverse
  5. Esamatic: Dataverse, Webhook and Service Bus/Event Hubs
  6. Amit Anand: Serverless CRM Mastery, Azure + Dataverse Integration
  7. Microsoft Learn: Use Change Tracking to Synchronize Data with External Systems
  8. Ben Gribaudo: Dataverse Web API Tip #9, Deltas and Tracking Changes
  9. Hookdeck: How to Implement Webhook Idempotency
  10. Svix: Idempotency and Deduplication
  11. Digital Applied: Webhook Reliability, Idempotency and Retry Reference
  12. Spatie: laravel-webhook-client (GitHub)
  13. Skyline: Laravel Background Jobs, 12 Best Practices
  14. IGC: Laravel Background Jobs, Queues Built for Production
  15. Stacksync: Real-Time Sync, Dynamics 365 F&O and HubSpot