How Pipedrive Webhooks Work
A Pipedrive webhook sends an HTTP POST to a URL you choose whenever a record changes: a deal moves stages, a person is created, an activity is deleted. Unlike HubSpot or Zoho, Pipedrive has a straightforward webhook system. You register a URL, pick an object and an action, and Pipedrive starts sending JSON.
Two things to know up front:
- New webhooks are version 2.0. Since March 17, 2025, webhooks created through the API default to v2, and Pipedrive has said v1 will be fully deprecated in 2026. If you have older integrations built on v1 payloads, plan the migration now. (Pipedrive changelog)
- Webhooks follow user permissions. A regular user’s webhook only covers what that user can see. Admins can create webhooks covering everyone in the company.
In This Post
Step-by-Step Setup
Option A: In the Pipedrive UI
- Go to Settings > Tools and apps > Webhooks
- Click to create a new webhook
- Choose the event object (deal, person, organization, activity, etc.) and event action (create, change, delete, or all)
- Paste the endpoint URL we provide. It must be a public HTTPS address; self-signed certificates aren’t supported
- Optionally add an HTTP Basic auth username and password. Pipedrive sends them with every request, and we use them to reject anything that didn’t come from your account
- Save
Regular webhooks are available on every Pipedrive plan. Webhook actions inside Pipedrive Automations are a different feature and need the Advanced plan or higher.
Option B: Through the API
This is how we usually do it: faster, repeatable, and it lets us create exactly the subscriptions the integration needs.
curl -X POST "https://api.pipedrive.com/v1/webhooks?api_token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"subscription_url": "https://hooks.example.com/pipedrive",
"event_action": "change",
"event_object": "deal",
"name": "Deal changes to integration",
"http_auth_user": "pipedrive",
"http_auth_password": "a-long-random-secret"
}'
version defaults to "2.0". A successful call returns 201. GET /v1/webhooks lists your webhooks and DELETE /v1/webhooks/{id} removes one. (API reference)
Events You Can Subscribe To
Every webhook is one object plus one action.
| Action | Fires when |
|---|---|
create | A record is added |
change | Any field on a record changes |
delete | A record is deleted |
* | Any of the above |
Objects include deal, person, organization, activity, lead, note, product, pipeline, stage and user, plus newer ones such as deal products and deal installments. * subscribes to every object.
| Integration need | Subscribe to |
|---|---|
| New lead sync | create + person (or lead) |
| Deal stage tracking | change + deal |
| Activity logging | create + activity |
| Contact updates | change + person |
| Organization sync | create and change + organization |
One edit triggers one change webhook in v2, so you no longer get the duplicate deliveries v1 sometimes produced.
What the Payload Looks Like (v2)
Here’s a trimmed example of a v2 change event for a deal. The meta block describes the event, data is the record’s current state, and previous holds only the fields that changed.
{
"meta": {
"action": "change",
"entity": "deal",
"entity_id": "4821",
"id": "8c1f1b2e-…",
"correlation_id": "f3a0c9d4-…",
"company_id": "1234567",
"user_id": "987654",
"timestamp": "2026-10-01T15:04:22.000Z",
"change_source": "app",
"is_bulk_edit": false,
"attempt": 1,
"version": "2.0",
"webhook_id": "512"
},
"data": {
"id": 4821,
"title": "Northside HVAC – service agreement",
"value": 12000,
"currency": "USD",
"stage_id": 3,
"status": "open",
"person_id": 1192,
"org_id": 377,
"custom_fields": { "…": "…" }
},
"previous": {
"stage_id": 2
}
}
What that tells you without any extra API calls: deal 4821 moved from stage 2 to stage 3, someone made the change in the app (not a bulk edit), and this is the first delivery attempt.
Details that matter when you build on it:
previousisnulloncreateand contains the last state ondelete.- Custom fields arrive inside
data.custom_fields, keyed by Pipedrive’s field keys rather than the labels you see in the app. - Merges arrive as two events: a
delete(withmerged_to_id) and achange(withmerged_from_id). meta.attemptcounts from 1 to 4, so you can tell a retry from a first delivery.
Migrating from v1? current became data, object became entity, retry became attempt, timestamps changed from Unix seconds to ISO 8601, previous now only lists changed fields, and the added/updated/deleted actions are now create/change/delete. (Migration guide)
Delivery Rules: Timeouts, Retries and Bans
This is where most Pipedrive webhook problems come from, so it’s worth knowing exactly how delivery works. (Webhooks v2 guide)
- 10-second timeout. Your endpoint has to answer with a 2xx within 10 seconds.
- Three retries. If the first attempt fails or times out, Pipedrive retries after 3 seconds, 30 seconds and 150 seconds.
- Temporary ban. Ten failed first attempts get the webhook banned for 30 minutes. Events that happen during a ban are not delivered.
- Deletion. A webhook with no successful deliveries for 3 consecutive days is deleted.
- Limit. Each user can have up to 40 webhooks.
The practical rule: acknowledge fast, process later. Your endpoint should check the credentials, store the payload, return 200, and do the real work (CRM updates, lookups, notifications) in the background. An endpoint that calls three other APIs before responding will eventually hit the 10-second limit.
# Minimal receiver: authenticate, queue, acknowledge. The work happens in a background worker.
@app.post("/pipedrive")
def pipedrive_webhook(request):
if not basic_auth_ok(request, user="pipedrive", password=SECRET):
return Response(status=401)
queue.enqueue(process_pipedrive_event, request.json()) # retries, logging, dedup live in the worker
return Response(status=200)
Testing Your Webhooks
- Point a temporary webhook at a request inspector (webhook.site or similar) before you build anything. Trigger the event and look at the real payload, especially your custom field keys.
- Trigger each event type you subscribed to. A
changewebhook won’t fire when you create a record, and vice versa. - Test a bulk edit. Update several deals at once and confirm your endpoint handles the burst.
- Test a failure. Make your endpoint return a 500 once and watch for the retry (
meta.attempt: 2). - Use a sandbox for anything destructive. A Pipedrive developer sandbox lets you delete and merge test records safely.
- Switch to the production URL only after the payloads look right.
Troubleshooting
Webhook Not Firing
- Check Settings > Tools and apps > Webhooks: is the webhook still there? It’s deleted after 3 days without a successful delivery.
- Check the object and action match what you did.
change+dealwon’t fire for a new deal. - Check permissions: a regular user’s webhook doesn’t cover records that user can’t see.
Events Missing for 30 Minutes at a Time
That’s the ban. Ten failed first attempts trigger a 30-minute pause, and events in that window are not resent. Fix the endpoint’s errors or timeouts first, then backfill the gap through the API (for example, deals updated since the last event you received).
Payload Doesn’t Have the Field You Need
In v2, previous only lists changed fields, and custom fields use field keys. Look up the key once through the API’s field endpoints and map it in your integration instead of matching on labels.
Getting 401s or Unexpected Requests
If you set Basic auth, reject anything without the right credentials. Pipedrive doesn’t sign webhook requests, so Basic auth over HTTPS is the main protection. Use a long random password.
Integration Broke After Recreating a Webhook
A webhook created through the API after March 2025 is v2 unless you asked for v1. If your code expects current and event, that’s the cause. Update the parser to the v2 shape.
Next Steps
- Set up a safe place to test: Pipedrive Sandbox Setup
- Get your API token: Pipedrive API Token
- Webhooks failing for other reasons? Common Webhook Issues
- Rather we handle it? Pipedrive Integration Services