# Validate Emails in Pipedrive

URL: https://email-validation.org/docs/guides/pipedrive/
Updated: 2026-11-06

> Documentation index: https://email-validation.org/llms.txt

Check the email address of each Pipedrive person and save the result in custom person fields that you pick, so your
filters and automations can use it. Two small pieces do the work, and you can use either or both:

- **A webhook relay** checks a person within seconds when it is added, or when its primary address changes.
- **A clean-up command** checks every person of a Pipedrive filter that has no result yet.

Both run in your own accounts with your own keys: the relay as a Cloudflare Worker, the command with Node. Nothing
needs to be installed from the Pipedrive Marketplace.

## Before you start

- **An API key.** Create one on the [API keys page](https://email-validation.org/app/api-keys/) with the permission "Validate addresses". To clean
  a filter of more than 50 persons, also turn on **"Bulk lists"**. A
  [daily credit cap](https://email-validation.org/docs/authentication/#limits) limits what a busy webhook can spend.
- **Your Pipedrive API token.** In Pipedrive: **Settings → Personal preferences → API**. The token acts as you, so the
  relay sees only the persons you can see. Keep it secret.
- **Your company domain**, the address you open Pipedrive at: `acme` for `https://acme.pipedrive.com`.
- **Node 22.18 or later** for the clean-up command, and a **Cloudflare account** for the relay.
- **The files**, which are built from our tested code:
  - [relay.js](https://email-validation.org/downloads/pipedrive/relay.js): the webhook relay, one Cloudflare Worker module;
  - [clean.mjs](https://email-validation.org/downloads/pipedrive/clean.mjs): the clean-up command and the field setup, one Node module;
  - [webhook.json](https://email-validation.org/downloads/pipedrive/webhook.json): the webhook's settings, for Pipedrive's API.

## Create the result fields

The result goes into three custom person fields:

| Field | Value |
|---|---|
| Email status | one of the five [result statuses](https://email-validation.org/docs/statuses/): `valid`, `invalid`, `catch_all`, `unknown` or `disposable` |
| Email status reason | why, such as `accepted` or `no_mailbox` (optional) |
| Email checked at | when the check ran, as an ISO 8601 date and time in UTC |

Create them once with the command:

```bash
export PIPEDRIVE_API_TOKEN=…  PIPEDRIVE_DOMAIN=acme
node clean.mjs --setup
```

It creates whichever of the three fields are missing, as Text fields, and prints their keys. To use fields of your
own instead, set `PIPEDRIVE_STATUS_FIELD`, `PIPEDRIVE_CHECKED_AT_FIELD` and, if you want it,
`PIPEDRIVE_REASON_FIELD` to each field's name or key, for both pieces. They must be custom person fields of type
Text or Large text.

## Check new and changed persons

1. Deploy the relay to your Cloudflare account and give it its secrets:

   ```bash
   npx wrangler deploy relay.js --name ev-pipedrive-relay --compatibility-date 2026-10-01 --var PIPEDRIVE_DOMAIN:acme
   npx wrangler secret put EV_API_KEY --name ev-pipedrive-relay
   npx wrangler secret put PIPEDRIVE_API_TOKEN --name ev-pipedrive-relay
   npx wrangler secret put WEBHOOK_USER --name ev-pipedrive-relay
   npx wrangler secret put WEBHOOK_PASSWORD --name ev-pipedrive-relay
   ```

   `WEBHOOK_USER` is any name, such as `pipedrive`. `WEBHOOK_PASSWORD` needs at least 32 random letters and digits,
   for example from `openssl rand -hex 32`. Your keys stay in the Worker's secret store. For
   [EU data residency](https://email-validation.org/docs/eu-data-residency/), add `--var EV_REGION:eu` to the deploy command.
2. In Pipedrive, open **Settings → Tools and apps → Webhooks → Create new webhook**:
   - **Event action** `*` (or one webhook for `create` and one for `change`), **event object** `person`;
   - **Endpoint URL** the relay's address, such as `https://ev-pipedrive-relay.<your-subdomain>.workers.dev/`;
   - **HTTP Auth** the `WEBHOOK_USER` and `WEBHOOK_PASSWORD` you set on the relay.

   To create the webhook with Pipedrive's API instead, send `webhook.json`, with your values filled in, to
   `POST /api/v1/webhooks`.
3. Add a test person with the address `no_mailbox@sandbox.email-validation.org`, a [test address](https://email-validation.org/docs/test-addresses/) that
   costs nothing. Within a few seconds its Email status is `invalid`. Then delete the test person.

The relay checks a person when it is created, and when its primary address changes. It ignores every other change,
including its own write to the result fields, so a result never starts a second check. Before it checks, it reads
the person, so it always checks the address as it is now. A repeated delivery of an event it already checked is
skipped, and the relay refuses any request without the webhook's credentials.

## Clean a filter

Create a person filter in Pipedrive with the persons to check. Its id is the number at the end of the address while
the filter is open, such as `12` in `…/persons/list/filter/12`.

```bash
export EV_API_KEY=…  PIPEDRIVE_API_TOKEN=…  PIPEDRIVE_DOMAIN=acme
node clean.mjs --filter 12 --dry-run    # counts what it would check
node clean.mjs --filter 12              # checks and writes the results
```

The command skips persons without an address and persons that already have a status other than `unknown` (add
`--revalidate` to check them again). Up to 50 persons are checked one by one. More go into one
[bulk job](https://email-validation.org/docs/bulk/): the command uploads the list, starts it, waits for it, and writes each result to its
person.

If a run stops for any reason, such as no credits or a closed laptop, run the same command again. It keeps the bulk
job's id in a small state file (ids only, no addresses) and resumes that job, so a list is never paid for twice.
Exit code `75` means the job was still running when the command stopped waiting: run it again later.

Other options: `--region eu` for [EU data residency](https://email-validation.org/docs/eu-data-residency/), `--status-field`, `--reason-field` and
`--checked-at-field` for your own fields, `--rate` for Pipedrive requests per second (default 8), and
`--wait-minutes` for how long to wait for a bulk job (default 240).

## Answers and retries

Pipedrive treats any answer other than 2xx as a failure: it delivers again up to three times, and it can pause or
remove a webhook that keeps failing. So the relay answers with an error only when trying again can work.

| The relay answers | When | What to do |
|---|---|---|
| `200` `saved` | The person was checked and the result written | Nothing |
| `200` `ignored` or `skipped` | No new address, the person is gone, or the event was already checked | Nothing |
| `200` `not_checked` | The key was refused, there are no credits, the key reached its daily cap, or a result field is missing | Fix the cause, then clean the filter to catch up |
| `200` `not_saved` | The check ran but Pipedrive did not take the result | Clean the filter to catch up |
| `503` | A rate limit or an outage before the check | Nothing: Pipedrive delivers again |
| `401` | Wrong or missing webhook credentials | Check HTTP Auth on the webhook |

Nothing is charged for a delivery that answers `503` or `not_checked`.

## Costs and limits

- Each checked person is one check. Results with the status `unknown` are free, and so are the
  [test addresses](https://email-validation.org/docs/test-addresses/).
- The relay answers within Pipedrive's 10-second limit, so it gives a check at most 5 seconds.
- Each read and write uses Pipedrive API tokens from your company's daily budget. The clean-up command spaces its
  requests to stay under Pipedrive's rate limits and waits when Pipedrive asks it to.
- Our own [rate limits](https://email-validation.org/docs/rate-limits/) apply to the relay as to any other client.
