Skip to content

How to verify emails with Zapier using a webhook step

· 4 min read · Tutorials

To verify emails with Zapier, add a Webhooks by Zapier action after your trigger, send a POST with the address to a verification API, and then use a Filter or Paths step on the returned status. With pingutil that's one request to https://pingutil.com/v1/verify with your API key in a header. The response comes back as fields you can map into later steps, so you can drop invalid addresses, tag risky ones, and pass valid ones on to your CRM or sequencing tool.

This tutorial uses only documented Zapier features. You need a Zapier plan that includes Webhooks by Zapier: their help article Send webhooks in Zap workflows lists it for Professional, Team and Enterprise, not Free.

What you'll build

  1. Trigger: a new lead arrives (form submission, new CRM contact, new row in a sheet).
  2. Action: Webhooks by Zapier, POST, to /v1/verify.
  3. Paths: one branch per verification outcome.
  4. Actions per branch: create the contact, tag it, or skip it.

Step 1: the trigger

Use whatever already produces your leads. The only requirement is that the trigger output contains the email address as a field. Test the trigger so Zapier has a sample record to map from.

Step 2: the webhook POST

Add an action step, pick Webhooks by Zapier, and choose the POST event. Configure it like this:

Field Value
URL https://pingutil.com/v1/verify
Payload Type json
Data key email, value: map the email field from the trigger
Headers Authorization → Bearer pk_live_... (your pingutil key)

Zapier's docs advise against putting parameters in the URL field; keep the address in Data. Leave nothing else in Data. If the Data section is empty, Zapier sends every field from the previous step, which isn't what you want.

Test the step. A successful response looks like this (trimmed):

{
  "email": "jane@acme.com",
  "status": "risky",
  "reason": "accept_all",
  "score": 50,
  "did_you_mean": null,
  "checks": {
    "syntax": true,
    "disposable": false,
    "free_provider": false,
    "role_based": false,
    "mailbox": "accept_all",
    "catch_all": true
  }
}

The score shown is illustrative. After the test, the response fields are available to later steps through Zapier's normal field mapping, so Status, Reason, Score and Did You Mean become values you can pick from the dropdown.

Most checks take one to five seconds. A slow mail server can take up to about 25, so expect the occasional slow run.

Step 3: branch with Paths

Add a Paths step. Zapier's article on branching with Paths explains that each branch has its own rules and that branches can be set to run only when no other branch did (a fallback). Build four:

Path Rule Suggested action
Valid Status (Text) exactly matches valid Create or update the contact, start the sequence
Risky Status (Text) exactly matches risky Create the contact with a tag like email-risky and the Reason in a field
Invalid Status (Text) exactly matches invalid Skip, or log to a sheet for review
Fallback (fallback) Covers unknown and any error: tag email-unverified, re-check later

Keep the rules mutually exclusive so only one branch runs per lead. Zapier runs matching branches left to right, and more than one can run if their rules overlap.

If you only need a gate, a single Filter step with Status exactly matches valid works. Zapier's filter article explains that a failed filter stops the Zap with no further actions. That drops risky and unknown leads silently, so we prefer Paths for anything sales will look at.

Handle typos

If Did You Mean is not empty, the domain looks like a typo of a major provider (gmial.com). Don't auto-correct it. Write the suggestion to a note on the contact so a person can confirm it, or, if the trigger is your own signup form, show it to the user instead. Our post on React signup form feedback covers that side.

What the statuses mean for routing

  • valid / mailbox_exists: the mail server confirmed the mailbox.
  • risky: it might exist, but sending is a gamble. accept_all (catch-all domain), role_based (info@), mailbox_full, or randomized_local_part. See catch-all email domains.
  • invalid: mail won't reach anyone, for example mailbox_not_found, no_mx or disposable_domain.
  • unknown: the server didn't answer clearly (greylisted, blocked, timeout). Retry later.

The status reference lists every reason.

Limits to plan around

pingutil allows 60 requests a minute per account and 300 verifications a day, across all your keys and dashboard CSV uploads. Over the daily budget the API returns 429 with quota_exceeded, and over the per-minute limit 429 with rate_limited. The webhook step will error on a 429, so if your trigger can fire in bursts (a bulk import into your CRM), put a Zapier delay or a queue in front, or verify the batch first with the dashboard CSV upload.

Each call counts against the daily budget even if the address was checked recently, because results are cached on our side for 30 days but the request is still a verification. Don't re-verify the same contact on every update; trigger on new records only.

Test it

Before turning the Zap on, run a few known addresses through the email verification demo so you know what each branch should receive. Then test the Zap with a real lead from your own team, a made-up address on your company domain, and a typo like @gmial.com.

Questions people ask

Do I need a paid Zapier plan to call a verification API?
Yes. Zapier's help center says Webhooks by Zapier actions are available on Professional, Team and Enterprise plans, not on the Free plan. Filters and Paths are also listed as paid-plan features.
What should the Zap do with unknown results?
Don't treat them as valid or invalid. Unknown means the mail server didn't give a clear answer, often because of greylisting or a temporary block. Route them to a holding step or tag them, and re-check later rather than dropping the lead.