# Pipedrive Webhooks: Fix Missing Deal Updates, Retries and Integration Loops

General Pipedrive webhooks need three checks before you investigate a missing deal update: the subscription must exist, its owner must be allowed to see the deal, and the receiving endpoint must be accepting deliveries. Use the v2 payload contract, preserve receipts before acknowledging them, and plan for lost notifications during a webhook ban. Restarting a receiver alone does not recover the missing business state.

Canonical URL: https://www.martechdevs.com/blog/pipedrive-webhooks

By [Jafrin Akter Alo](https://www.martechdevs.com/authors/jafrin-akter-alo)

Data Engineer and Co-founder at [Martechdevs](https://www.martechdevs.com) and [Growth and Analytics Partners](https://www.growthandanalytics.com)

[LinkedIn](https://linkedin.com/in/jafrinalo)

Last updated: 2026-10-25

Next step: [Pipedrive Pricing: Seats, Add-Ons and the Cost of Your Workflow](https://www.martechdevs.com/blog/pipedrive-pricing)

A webhook can work for one deal and miss another because of visibility. It can also work for months, fail during a deployment and resume with a gap after a temporary ban. Those failures need different fixes, even if the CRM team reports the same symptom: “the integration stopped updating.”

Begin with one controlled deal and trace its source change, subscription, delivery attempt and destination result. Keep that evidence while changing the narrow cause.

## Which Pipedrive webhook route fits the job?

Use general webhooks for object-change notifications, app-specific webhooks for a Marketplace app's managed subscriptions, and an Automation webhook for a deliberate conditional step in a business process.

| Route | Where it is managed | Suitable job | Diagnostic boundary |
| --- | --- | --- | --- |
| General v2 webhook | Webhook settings or API | Observe selected deal, person or other object changes | Subscription owner and delivery state |
| App-specific webhook | Marketplace app through its API access | Maintain an app's installed integration | App lifecycle and its own subscription inventory |
| Automation webhook | Automation configuration | Send a configured request after business conditions | Automation entry, action and execution limits |

App-specific webhooks are not shown in the ordinary Pipedrive UI. They require the app's admin scope, are queried and deleted through the app, and are removed when the user uninstalls that app. An empty UI list does not prove that a Marketplace integration has no subscription. [App-specific webhook rules](https://pipedrive.readme.io/docs/webhooks-for-apps).

Automation webhooks are separately created and cannot reuse an existing ordinary webhook. Creation requires a global admin; any user can trigger the automation webhook regardless of their visibility or admin permissions. The request method and body are configured as part of the action, and execution follows automation limits. [Automation webhook setup](https://support.pipedrive.com/en/article/automations-webhook-requests).

Current plans include regular webhooks across Lite, Growth, Premium and Ultimate; automation begins at Growth. Older plan names can still appear in feature-specific help, so confirm the actual entitlement on the account. [Current plan features](https://support.pipedrive.com/en/article/what-features-do-the-pipedrive-plans-have). The [Pipedrive pricing guide](https://www.martechdevs.com/blog/pipedrive-pricing) covers the broader subscription decision.

## How do you configure a controlled v2 subscription?

Start with one object and action that corresponds to the actual business change, and explicitly select payload version `2.0`.

The management endpoint remains `POST /api/v1/webhooks`; that URL version is separate from the delivered webhook version. The API accepts a public destination URL, event action, event object, name, owner and optional HTTP Basic credentials. The URL must not redirect. [Webhook creation API](https://developers.pipedrive.com/docs/api/v1/Webhooks).

This is an illustrative request body for one general subscription. Replace the destination with the controlled HTTPS endpoint and provision credentials securely through your management process; do not store secrets in a published configuration file.

```json
{
  "name": "Deal change reconciliation",
  "subscription_url": "https://hooks.example.com/pipedrive/deals",
  "event_action": "change",
  "event_object": "deal",
  "version": "2.0"
}
```

The body omits credentials deliberately; it is not a complete authenticated production setup. The next section describes the receiving-end authentication requirement.

1. **Choose the owning user.** Verify access to the records the integration is supposed to cover.
2. **Create the narrow subscription.** Prefer a controlled `change.deal` pilot before subscribing to every object and action.
3. **Confirm the saved ID and version.** Keep the subscription ID in the integration's operational inventory.
4. **Change a visible test deal.** Inspect the resulting event and its destination record.
5. **Change a deliberately restricted deal.** Confirm the expected access boundary rather than broadening permissions by default.
6. **Test an endpoint failure.** Observe its retry and recovery path before release.

For a deal-owner change, subscribe to changes on `deal`; subscribing to `user` observes changes to the user object. The distinction follows the changed entity, not the human involved in the business event. [Selecting the event object](https://pipedrive.readme.io/docs/guide-for-webhooks-v2).

## Why does the webhook owner's visibility matter?

For general subscriptions, Pipedrive checks each event against the owning user and sends it only when that user can access the relevant object. If `user_id` is omitted when creating the webhook, the current user is used. [Webhook authorization scope](https://developers.pipedrive.com/docs/api/v1/Webhooks).

Treat that owner as part of the integration's configuration. Record what happens when the person changes role, loses access or leaves the company. Compare a visible record and a restricted record under the same subscription before blaming network delivery.

Do not solve an unexplained gap by granting a top-level administrator's access automatically. First define the intended record population. If the integration legitimately needs broader access, assign an accountable identity with the appropriate approved permissions and repeat the negative tests.

Your receiver must also bind the authenticated route to the expected Pipedrive company. A payload's `company_id` should select a known mapping after validation; it must not supply arbitrary credentials or choose an unrelated customer's destination.

## How should the receiving endpoint authenticate Pipedrive?

For a general webhook, configure the endpoint's HTTP Basic username and password using the webhook's `http_auth_user` and `http_auth_password` fields, and require them over HTTPS before accepting the payload. Those are credentials for your receiving endpoint, not a Pipedrive API token. [Supported endpoint credentials](https://developers.pipedrive.com/docs/api/v1/Webhooks).

Use a dedicated random secret, keep it out of URLs and logs, and compare credentials with a suitable constant-time mechanism in the receiving service. A secret embedded in a query string is more likely to appear in proxy and access logs.

Do not copy a HubSpot or Stripe HMAC verifier into this receiver. The configured Basic credentials authenticate this connection; they do not create a provider-signed body timestamp. Preserve transport security, tenant routing and replay protection as separate responsibilities.

During rotation, plan how the subscription and receiver will overlap the old and new credential briefly, verify a controlled delivery, then retire the old value. A receiver that returns 401 throughout an uncoordinated rotation can accumulate delivery failures and enter a ban.

## What changed in the v2 payload?

V2 changes both field locations and meaning, so replacing one version string is insufficient for migration.

| V1 assumption | V2 contract | Required parser change |
| --- | --- | --- |
| Object values are in `current` | Values are in `data` | Read the correct envelope |
| Retry counter is top-level `retry` | Attempt is `meta.attempt`, starting at 1 | Separate delivery attempts from event identity |
| `previous` is a full prior object | It contains changed fields | Do not clear fields missing from the patch |
| Custom fields behave like top-level values | They are under `data.custom_fields` with typed structures | Parse the field type and preserve IDs/currency |
| A merge is a distinct `merged` action | Merge produces delete/change notices with merge references | Reconcile the old and surviving records |

The current `data` object is also a reduced representation, not a promise of the entire API record. Retrieve required missing fields through the appropriate API. [V2 migration and payload guide](https://pipedrive.readme.io/docs/webhooks-v2-migration-guide).

For example, an absent `status` in `previous` means the patch does not provide an old status. It does not mean the prior status was empty. An explicit `null` is a different representation and needs the field's defined clearing behaviour.

For a single-option custom field, the payload may carry an option ID rather than its display text. Keep the ID stable in the integration and resolve labels through the relevant field metadata when needed. Do not overwrite an approved label map by treating a numeric ID as the customer's answer.

### A parser that creates a safe processing instruction

This Python example handles authenticated general v2 deal notices only. It validates the expected company and object identity, then returns a processing instruction. It does not authenticate HTTP requests, write to Pipedrive, merge customers or decide that a deal is eligible for a sales action.

```python
def parse_deal_notice(payload, *, expected_company):
    def record_id(value):
        if type(value) is int and value > 0:
            return str(value)
        if isinstance(value, str) and value.isascii() and value.isdigit():
            if int(value) > 0:
                return str(int(value))
        raise ValueError("Expected a positive record identifier")

    company = record_id(expected_company)
    if not isinstance(payload, dict) or not isinstance(payload.get("meta"), dict):
        raise ValueError("Missing event metadata")
    meta = payload["meta"]
    if meta.get("version") != "2.0" or meta.get("type") != "general":
        raise ValueError("Expected a general v2 notification")
    if meta.get("entity") != "deal" or record_id(meta.get("company_id")) != company:
        raise ValueError("Wrong entity or company")
    object_id = record_id(meta.get("entity_id"))
    event_id = meta.get("id")
    if not isinstance(event_id, str) or not event_id.strip():
        raise ValueError("Missing event identifier")
    if event_id != event_id.strip():
        raise ValueError("Unexpected surrounding whitespace in event identifier")
    action = meta.get("action")
    if not isinstance(action, str) or action not in {"create", "change", "delete"}:
        raise ValueError("Unsupported action")
    if "data" not in payload or "previous" not in payload:
        raise ValueError("Missing event envelope fields")
    data, previous = payload.get("data"), payload.get("previous")
    merge_target = None
    if action == "delete":
        if data is not None or not isinstance(previous, dict):
            raise ValueError("Invalid delete payload")
        if meta.get("merged_to_id") is not None:
            merge_target = record_id(meta["merged_to_id"])
        intent = "reconcile_merge" if merge_target else "reconcile_deletion"
    else:
        if not isinstance(data, dict) or record_id(data.get("id")) != object_id:
            raise ValueError("Data and metadata identifiers disagree")
        if action == "create" and previous is not None:
            raise ValueError("Unexpected previous object on create")
        if action == "change" and not isinstance(previous, dict):
            raise ValueError("Missing changed-field patch")
        intent = "refresh"
    return {
        "receipt_key": (company, event_id),
        "object_key": (company, "deal", object_id),
        "intent": intent,
        "merge_target": merge_target,
    }
```

Store the original event alongside this instruction. Scope the receipt key to this consumer; it is not the idempotency key for every business effect. A parser rejection should enter an observable exception path, rather than disappear as an apparently successful update.

The parser intentionally refuses other objects, app-specific deliveries and old payload versions. Extend it with fixtures when the supported contract changes. Do not loosen validation until any dictionary-shaped request reaches a worker.

## Does v2 remove the need for duplicate protection?

V2 reduces multiple change notifications caused by a single edit, but your receiving service still needs protection against repeated delivery and repeated business actions.

Pipedrive's migration guide describes one `change` event per edit, while its delivery guide separately defines retries after failed responses. Those statements concern event generation and transport respectively. An acknowledged remote task whose response was lost can still be created twice by an unsafe retry. [V2 event behaviour](https://pipedrive.readme.io/docs/webhooks-v2-migration-guide), [delivery retries](https://pipedrive.readme.io/docs/guide-for-webhooks-v2).

Keep delivery identity and business identity separate. A repeated event can refer to the same task episode; several legitimate events can also request the same operational action. Define a key such as the account, deal and approved handoff version, then enforce uniqueness atomically where the action is claimed.

If the destination accepts the write but the acknowledgement is uncertain, reconcile by its supported idempotency key or stable external reference before retrying. Do not interpret a timeout as proof that nothing happened.

For a current-state mirror, serialize processing by company and deal, retrieve the required source fields and write only the fields the integration owns. Keep historical transition evidence separately if it matters. The [CRM property ownership guide](https://www.martechdevs.com/blog/crm-property-ownership) explains why the most recently received value is not necessarily authoritative.

## What happens when deliveries fail or the webhook is banned?

Pipedrive retries failed deliveries briefly, then can suspend or delete a failing subscription. You need an alert and a reconciliation plan before those states create an unexplained gap.

| Condition | Published behaviour | Operational response |
| --- | --- | --- |
| Non-2xx response or ten-second timeout | Three retries after 3, 30 and 150 seconds | Commit promptly and keep repeat handling safe |
| Ten first-attempt failures on a webhook | Thirty-minute ban | Repair the receiver and identify the missing interval |
| Events occur during the ban | Messages are lost rather than retained for later retry | Reconcile source state after restoration |
| No successful deliveries for three consecutive days | Webhook is deleted | Detect the missing subscription and recreate it deliberately |

Retry failures do not increment the ban counter in the same way as first-attempt failures. Any 2xx is treated as a successful delivery, so returning success before durable receipt can conceal lost work. [Retry and ban policy](https://pipedrive.readme.io/docs/guide-for-webhooks-v2).

Keep the receipt path short: authenticate, validate the expected route, commit the event and acknowledge. Move slower API calls and destination writes to workers. Measure queue age separately from HTTP success so a healthy-looking endpoint cannot hide stalled processing.

Do not return 200 for every request simply to avoid a ban. That suppresses the sender's recovery mechanism without preserving the event. Repair the underlying authentication, storage or response-time failure and reconcile the affected period.

## How do you recover the gap after an outage?

Recover the source population affected by the outage and verify the destination, rather than assuming restored webhook delivery also backfills the missing interval.

1. **Record the gap.** Preserve the last trustworthy delivery and processing checkpoints, observed failure period and affected subscriptions.
2. **Restore the intended subscription.** Confirm its existence, version, owner, destination and credentials. Avoid creating a second subscription accidentally.
3. **Choose the recovery source.** Use a supported current-state or change-history API for the affected object types and permissions.
4. **Load a bounded overlap.** Paginate to completion, preserve stable IDs and keep historical recovery from triggering unapproved new outreach.
5. **Reconcile results.** Compare known records, amounts and statuses, then investigate missing, merged or deleted objects separately.
6. **Release the hold.** Resume consequential downstream actions after the recovered population and duplicate checks pass.

Pipedrive's Recents endpoint accepts a UTC `since_timestamp`, selected item types and pagination parameters. It can help identify changed records, but its supported item list is not every v2 webhook object. [Recents API scope](https://developers.pipedrive.com/docs/api/v1/Recents).

For deal-level work, the Deals API exposes current details, field-change history and separate archived-deal routes. Choose the source that answers the recovery question. [Deal retrieval and history endpoints](https://developers.pipedrive.com/docs/api/v1/Deals).

A current deal snapshot cannot prove every intermediate transition occurred. A failed fetch also needs classification: permission loss, an unavailable service, a merge and a deletion do not justify the same downstream action. Preserve unresolved cases rather than converting them all into deletion commands.

![A missing deal update is first checked for an existing subscription and owner visibility. Configuration/access failures go to repair; delivery or processing failures go to receiver repair and outage reconciliation. Otherwise inspect mapping and eligibility. Every branch requires controlled-change and recovery checks to pass before normal actions resume.](https://www.martechdevs.com/assets/blog/pipedrive-webhooks.svg)

Diagram connections:

- Investigate a missing deal update to Subscription exists and owner can see deal?. 
- Subscription exists and owner can see deal? to Repair configuration or approved access: No. 
- Subscription exists and owner can see deal? to Delivery and processing healthy?: Yes. 
- Delivery and processing healthy? to Repair receiver and reconcile outage gap: No. 
- Delivery and processing healthy? to Inspect payload mapping and business eligibility: Yes. 
- Repair configuration or approved access to Controlled change and recovery checks pass?. 
- Repair receiver and reconcile outage gap to Controlled change and recovery checks pass?. 
- Inspect payload mapping and business eligibility to Controlled change and recovery checks pass?. 
- Controlled change and recovery checks pass? to Keep affected actions on hold: No. 
- Controlled change and recovery checks pass? to Resume the verified process: Yes

## How do you stop a Pipedrive integration loop?

Write only the fields owned by the integration, compare the intended value before writing, and make repeated application of the same business update harmless.

A broad filter that ignores every API-originated event is unsafe: another legitimate integration may have made a change you need. Likewise, a single-use in-memory marker can disappear before a retry arrives.

Keep the source event, desired state, destination reference and writer decision in a durable record. If the receiver updates a derived property, ensure that update cannot continually trigger the same outbound action without a changed business condition.

For a hypothetical won-deal handoff, store the approved handoff version and destination project reference. Updating a phone number or receiving the webhook again should not create a second project. Reopening and approving a genuinely new commercial episode requires an explicit policy.

Use the [martech integration contract](https://www.martechdevs.com/blog/martech-data-integration) to define that ownership and recovery path across both systems. A webhook transports a change; it does not decide whether repeating the requested action is appropriate.

## Which checks establish that the receiver is ready?

Approve the receiver when access, payload interpretation, delivery recovery and final business effects pass together.

| Controlled test | Expected result | Evidence to retain |
| --- | --- | --- |
| Visible versus restricted deal | Only the intended authorized population enters the route | Subscription owner and source record IDs |
| Same delivery repeated | One intended processing outcome and business episode | Receipt and action records |
| V1 payload sent to the v2 parser | Observable rejection or quarantine | Parser error and original envelope |
| Missing field versus explicit null | Different handling under the field contract | Before/after destination values |
| Merge deletion and survivor update | Crosswalk reconciles to the surviving record | Both source IDs and merge references |
| Receiver outage | Subscription and missing population are recovered | Outage window, API coverage and reconciliation |

## Checklist

- [ ] General, app-specific and Automation routes are distinguished.
- [ ] Payload version and exact event object are recorded.
- [ ] The webhook owner can see the required records.
- [ ] Endpoint credentials, HTTPS and company routing are enforced.
- [ ] V2 partial data and typed custom fields are handled correctly.
- [ ] Receipts are durable before success responses.
- [ ] Repeat deliveries and uncertain destination writes cannot silently duplicate actions.
- [ ] Ban, subscription deletion and outage recovery have alerts and an owner.
- [ ] Integration writes cannot bounce indefinitely between systems.

When deal changes must create reliable downstream work, [Martechdevs' integration service](https://www.martechdevs.com/martech-integration) can connect the subscription, receiver and business-action contract. The [Pipedrive alternatives guide](https://www.martechdevs.com/blog/pipedrive-alternatives) is useful only if the required workflow remains a product-fit problem after the integration is correctly scoped.

## Frequently asked questions

### Why is a v2 webhook created through an API path containing v1?

The management endpoint version and the delivered payload version are separate. Pipedrive's webhook-creation endpoint uses the v1 API path while its `version` field selects the webhook contract. Set that field explicitly and validate the returned subscription and a controlled delivery. An endpoint path alone is insufficient evidence that the receiver will see the old or new envelope.

### Can a missing webhook be caused by an employee's access change?

Yes, record visibility is part of the subscription's authorization boundary. Compare the owning user's current permissions with the missing record before treating the issue as an endpoint outage. Keep an integration-owner inventory and a planned handover when roles change. Approve any broader access deliberately, then test both included and excluded records under the replacement configuration.

### Should the receiver ignore a merge-related delete event?

Handle a merge-related delete as reconciliation work rather than blindly ignoring it or deleting the whole customer relationship. Preserve the old record and surviving-record references, update the crosswalk under the agreed policy and verify downstream associations. The accompanying survivor update may arrive through a separate processing path, so the migration state must remain understandable until both sides reconcile.

### Can two webhook subscriptions safely share one endpoint?

They can when the endpoint identifies the expected company, subscription purpose and payload contract before routing work. Keep authentication and tenant configuration explicit, and decide whether both subscriptions feed one consumer or different business processes. Duplicate protection must reflect that choice. Sharing a URL should not merge customer credentials or collapse two distinct operational actions into one status.

### Does recreating a deleted subscription replay the outage automatically?

Do not assume recreation restores the missed period. Recreating the intended subscription restores future delivery; recovery needs its own bounded source query and reconciliation. Identify the objects, history and permissions required, paginate the chosen API and inspect merged or deleted records separately. Only release held downstream actions when their source population and business-effect checks pass.

## Sources

1. [Pipedrive: general webhooks v2](https://pipedrive.readme.io/docs/guide-for-webhooks-v2).

2. [Pipedrive: webhook management API](https://developers.pipedrive.com/docs/api/v1/Webhooks).

3. [Pipedrive: v2 migration and payloads](https://pipedrive.readme.io/docs/webhooks-v2-migration-guide).

4. [Pipedrive: app-specific webhooks](https://pipedrive.readme.io/docs/webhooks-for-apps).

5. [Pipedrive: Automation webhook requests](https://support.pipedrive.com/en/article/automations-webhook-requests).

6. [Pipedrive: current plan features](https://support.pipedrive.com/en/article/what-features-do-the-pipedrive-plans-have).

7. [Pipedrive: Recents API](https://developers.pipedrive.com/docs/api/v1/Recents).

8. [Pipedrive: deal retrieval and history](https://developers.pipedrive.com/docs/api/v1/Deals).
