Skip to content
ArticleMarch 9, 20269 min readhubspotwebhooksmakededuplicationautomation

HubSpot Contact Creation Webhooks: Stop Duplicate Contacts

HubSpot contact creation webhooks can fire multiple create and property-change events in Make.com. Learn burst control, dedupe keys, and safe contact writes.

Why one contact create can look like duplicate webhook chaos

I have seen this exact pattern in HubSpot-connected Make.com lanes: one contact is created once in HubSpot, but the receiver sees multiple webhook notifications close together and the downstream lane writes twice.

That is not one problem. It is usually a stack of three problems acting together:

  • HubSpot can send multiple notifications around one object change,
  • HubSpot does not guarantee notification order, and
  • Make.com scenarios often treat each inbound event as fresh create intent.

Recent HubSpot Community threads describe this almost word for word. One thread reports duplicate records because HubSpot sends multiple notifications for the same update on the same timestamp. Another says contact creation sometimes emits two webhook payloads: one propertyChange and one creation. A third thread calls it outright event spam because creation and property-change notifications arrive separately and sometimes out of order. Those reports are useful because they describe the operator pain precisely, even when the root cause is still mixed together. See the community threads on multiple notifications on create, contact or company create triggering multiple webhooks, and event spam on object creation.

HubSpot's current Webhooks API docs explain the technical side: HubSpot may send the same notification multiple times, and order is not guaranteed. That means your receiver must separate same notification retried from different notifications about the same object before any Make.com write path runs. The implementation consequence is straightforward: if the same contact create can arrive as multiple notifications or in mixed order, your Make.com lane needs event-level dedupe and object-level burst control before it ever calls Create Contact, Create Deal, or any downstream side effect. The safest service path for that is Make.com error handling. If duplicate contacts already damaged owners, lifecycle state, or handoff, pair containment with HubSpot workflow automation. The operating model behind this work is on About, and the closest published proof is the Typeform to HubSpot dedupe case.

What the community threads are actually describing

The three community complaints look similar on the surface, but they point to different control failures.

Failure mode 1: true retry of the same notification

This is the classic transport problem.

The same notification is delivered more than once because:

  • the receiver did not acknowledge fast enough,
  • the HTTP connection failed, or
  • the endpoint returned a retryable error.

In this case, the right dedupe key is event-level, usually eventId plus subscription context.

Failure mode 2: multiple legitimate notifications around one create

This is the object-burst problem.

One contact creation can be followed by additional property-change notifications while HubSpot finalizes or mutates related fields. Community reports show teams seeing one object create plus one or more property-change notifications around the same contact create. Even if those notifications are all legitimate, they do not all deserve a downstream create branch.

In this case, dedupe by eventId alone is not enough. You also need object-level burst control keyed by objectId and event type within a narrow window.

Failure mode 3: trigger topology noise

This is the subscription-design problem.

Teams often subscribe broadly to contact.creation plus several propertyChange events, then point all of them to the same Make.com scenario. The scenario receives a valid storm of notifications and treats them as duplicate-worthy create signals. Nothing is wrong with HubSpot transport here. The issue is that your downstream lane has no policy for which events may create, which may only update, and which must be ignored.

What HubSpot guarantees today

There are three official mechanics that matter here.

  1. HubSpot app webhooks follow at-least-once delivery. The same notification can be sent more than once. Official docs: Webhooks API.
  2. HubSpot does not guarantee order for webhook notifications. That means propertyChange may appear before or after another event you expected to arrive first. Official docs: Webhooks API.
  3. If your receiver has problems handling notifications, HubSpot retries on connection failures, timeouts over five seconds, and HTTP 4xx or 5xx responses for app webhooks. Official docs: Error handling.

These mechanics matter because they force one design rule:

never let one inbound HubSpot notification directly decide whether Make.com should create a contact.

The notification only tells you that something happened. Your lane still needs to classify whether this is:

  • a retried notification,
  • a burst around one object create,
  • or a new business event that deserves a write.

Why Make.com turns this into duplicate contacts

Make.com is not the cause. It is the amplifier when the lane is designed in the naive order.

The naive order looks like this:

  1. HubSpot sends webhook.
  2. Make.com receives payload.
  3. Scenario branches by event type.
  4. Scenario calls Search contacts or directly Create a record.
  5. A second notification from the same object arrives.
  6. The second run passes through the same create-worthy path.

That is how one contact create becomes:

  • duplicate contacts,
  • split owner assignment,
  • mismatched lifecycle history,
  • repeated Slack or task alerts,
  • cleanup work that should never have existed.

In most duplicate-contact incidents, the bug is not that HubSpot emitted multiple notifications. The bug is that the Make.com lane had no gate separating notification traffic from create intent.

That is the same implementation weakness behind how to prevent duplicate contacts in HubSpot workflows, HubSpot sends multiple webhooks: how to deduplicate in Make.com, and webhook retry logic for duplicate-safe writes.

The safe control model for contact creation webhooks

Use two gates, not one.

Gate 1: event-level retry gate

This answers: Have I already seen this exact notification?

Recommended key:

  • portalId + subscriptionId + eventId

Behavior:

  • if seen and completed -> skip,
  • if seen and processing -> hold or safe-exit,
  • if seen and failed -> controlled replay branch,
  • if missing -> continue.

This gate stops true retries.

Gate 2: object-level burst gate

This answers: Should this object be allowed to create again inside a short create window?

Recommended key:

  • objectId + objectType + short_window

Behavior:

  • first create-worthy event inside window -> may create,
  • later property-change events inside same window -> update-only or ignore,
  • create after existing CRM match -> update-only,
  • ambiguous object state -> exception queue.

This gate stops legitimate multi-notification bursts from turning into duplicate contacts.

A Make.com contract that actually works

Use one contract like this before any create branch:

hubspot_contact_create_control:
  intake:
    source: hubspot_webhook
    receiver: make_webhook_or_gateway
  retry_key:
    fields: [portalId, subscriptionId, eventId]
  burst_key:
    fields: [objectId, subscriptionType]
    window_seconds: 45
  allowed_create_events:
    - contact.creation
  update_only_events:
    - contact.propertyChange
  contact_identity:
    search_by:
      - normalized_email
      - external_source_id
  state_model:
    - received
    - processing
    - completed
    - failed
    - quarantined
  action_policy:
    repeated_retry_event: skip
    later_property_change_same_window: update_only
    missing_identity_fields: quarantine
    existing_contact_match: update_only

The important part is not the YAML itself. The important part is the policy separation:

  • one key for notification-level retries,
  • one window for object-level create bursts,
  • one rule for which events may create,
  • and one requirement that all later writes become update-only once identity is known.

Implementation path

Contact creation webhooks already creating duplicate contacts?

Use Make.com error handling for event-level dedupe, burst control, and safe create-versus-update routing. If duplicate contacts already broke HubSpot owners or lifecycle history, fix that lane separately after the intake path is stable.

The router shape I use in production

For HubSpot -> Make.com contact intake, the safe router is boring on purpose.

HubSpot webhook batch
  -> normalize notification
  -> retry gate by eventId
  -> classify subscriptionType
  -> burst gate by objectId + short window
  -> search contact by canonical identity
     -> existing contact: update-only branch
     -> no contact + allowed create event: create branch
     -> ambiguous identity: quarantine branch
  -> mark state and emit alert if needed

Two operator rules matter here.

Rule 1: only one branch is allowed to create

If both creation and propertyChange can create, you have already lost. Pick one event class that may create. Force all other notifications into update-only or ignore.

Rule 2: identity must be stronger than the event

Once you know the contact identity, downstream writes should follow the contact, not the incoming notification type. That is why create logic belongs after identity resolution, not before it.

How to audit this in one hour

If you already suspect this problem, audit the lane in this order.

  1. List active HubSpot subscriptions hitting the same receiver.
  2. Pull one duplicate-contact incident and compare all notification payloads for that object.
  3. Separate same event repeated from different events around one object.
  4. Check whether any event other than the designated create event can still trigger a create path.
  5. Check whether Make.com stores event-level state before writes.
  6. Check whether object-level burst logic exists.
  7. Verify whether Search Contact plus Create Contact is protected by the same state and identity rules.

If any of those are missing, the lane is not duplicate-safe yet.

The two common bad fixes

Bad fix 1: ignore all property-change notifications

This looks attractive because it reduces noise quickly.

It also breaks legitimate update flows if your lane depends on later property changes for owner assignment, enrichment, or sync.

The correct move is not ignore everything after create. The correct move is make only one event class create-worthy and keep the rest update-only.

Bad fix 2: dedupe only by objectId forever

This suppresses real updates after the first event.

A contact may legitimately need later updates, task creation, routing, or sync actions. If you dedupe forever by object ID, you flatten real business changes. Use short create-window burst control, not blanket object-level suppression.

What success looks like after the fix

You know the design is right when:

  • one contact create produces one contact write,
  • repeated notifications no longer create second records,
  • property-change bursts become explainable update-only traffic,
  • operators can trace one object through event-level and object-level state,
  • duplicate-prevented counts are visible instead of hidden in logs.

That is the point where the lane becomes safe enough to scale, enrich, or hand off to AI without multiplying bad identity decisions. The delivery model for fixing one lane at a time is documented on How It Works, and the fastest prep step is still the free reliability checklist.

FAQ

Why does HubSpot send property-change events right after contact creation?

Because object creation and field mutation do not always collapse into one semantic notification. Community threads show creation followed by property-change notifications, and HubSpot docs separately state that order is not guaranteed and the same notification may appear more than once.

Should I ignore all property-change notifications on create?

No. That usually hides legitimate updates. The better pattern is to allow only one event class to create and force later notifications into update-only or quarantine paths.

Do I dedupe by eventId or objectId?

Both, but for different reasons. eventId handles true retries of the same notification. objectId plus a short window handles create bursts around one object where several valid notifications arrive close together.

How do I stop duplicate contacts in Make.com from these webhook bursts?

Put event-level state before the first write, classify create versus update-only events, search by canonical identity, and allow only one branch to create. If two branches can create, duplicates will eventually come back.

Next steps

Free checklist: HubSpot workflow reliability audit.

Get the PDF immediately after submission. Use it to catch duplicate contacts, retries, routing gaps, and required-field misses before your next workflow change.

Free 30-minute discovery call available after review. Paid reliability audit from €500 if fit is confirmed.

Next step

Need HubSpot contact create webhooks to stop duplicating records?

Start with Make.com error handling to separate retries, object bursts, and create-worthy events before the next write. If duplicate contacts already polluted HubSpot, move the damaged lane into workflow repair next.