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
- Trigger: a new lead arrives (form submission, new CRM contact, new row in a sheet).
- Action: Webhooks by Zapier, POST, to
/v1/verify. - Paths: one branch per verification outcome.
- 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, orrandomized_local_part. See catch-all email domains.invalid: mail won't reach anyone, for examplemailbox_not_found,no_mxordisposable_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.