How to Verify Emails in Clay With an HTTP API Column
To verify emails in Clay, add an HTTP API enrichment column that sends each row's email to a verification API and returns the status. Store the API key in a saved header account, reference the email column with a forward slash, set the rate limit under the API's limit, and add a run condition so empty rows are skipped. Then push only rows with status = valid to your sequencer and handle risky rows separately.
This guide builds that column step by step with SimpleVerifier's API, then shows how to route results and how to verify phone numbers in the same table.
Why verify inside Clay at all
Clay tables usually find emails through one or more providers. A found email is not a verified one. Our page on verifying B2B lead lists explains the gap:
- Some providers return a pattern guess such as
first.last@company.comwhen they have no record. - A vendor's "verified" flag was set on its own schedule, sometimes months ago.
- Catch-all domains accept mail for any address, so a provider may call an address found when no mailbox was confirmed.
- The same person can arrive twice from two providers with two different addresses.
Verifying in the table, right before export or push, gives you one consistent result from one check, on the day you use it.
Where the column goes in the table
A typical outbound table runs left to right:
- Company and person columns (name, domain, title).
- Email finding, often a waterfall of providers.
- Verification (the column you are adding).
- Personalisation columns.
- Push to sequencer, conditioned on the verification result.
Put verification after finding and before anything that costs money per row or sends data out. That way you never personalise or push an address that will bounce.
Step 1: Save the API key as a header account
Clay's HTTP API documentation says you can save auth credentials in an HTTP API (Headers) account, which Clay encrypts and stores at the workspace level. Every HTTP API column in the workspace can then use it, and editing the account updates them all.
Create the account with one header:
| Key | Value |
|---|---|
Authorization |
Bearer sv_live_... |
On SimpleVerifier, create the key on the API keys page. It starts with sv_live_ and is shown once. The API docs explain authentication in full. API access comes with a subscription. Pay-as-you-go packs cover CSV uploads only.
Step 2: Add the HTTP API enrichment
In the table, click Add enrichment, search for HTTP API, and open the Configure tab for manual setup. Fill it in:
| Field | Value |
|---|---|
| Method | GET |
| Endpoint | https://simpleverifier.com/api/v1/verify |
| Query parameters | key email, value /Email (your email column) |
| Headers | Select the saved header account from Step 1 |
Clay's docs say column references use a forward slash, so /Email inserts that row's value. Rename it to match your column, for example /Work Email.
The API returns JSON like this:
{
"email": "jane@company.com",
"status": "valid",
"reason": "Mailbox exists",
"mailbox_checked": true
}
Return the fields you need
Clay's HTTP API settings include field paths, which let you choose which parts of the response to keep. Return at least status and reason. status is valid, risky or invalid. reason explains it, for example "Accepts all addresses" for a catch-all domain or "Mailbox not found" for a dead address. The full list is in the API docs.
Step 3: Set the rate limit
Clay's docs describe two rate limit settings: Request limit and Duration (ms). A request limit of 10 with a duration of 1,000 ms means 10 requests per second. The docs tell you to check the API provider's limits and configure them here, and list HTTP 429 as "Too many requests".
SimpleVerifier allows 120 calls a minute per key. Set:
| Request limit | Duration (ms) | Effective rate |
|---|---|---|
| 100 | 60,000 | 100 per minute |
That leaves headroom for retries and for anything else using the same key. If other tables or tools share the key, give each its own key or lower the limit further. If 429 errors still appear, lower the limit again or run the column on smaller selections of rows.
Step 4: Add a run condition and test one row
Clay's docs describe conditional run formulas, with the example "Only run if email column is not empty". Add that condition. Rows where every provider in the waterfall failed then cost no API call and show no error.
Before running the whole table, click Test to run the column on a single row. Clay's docs recommend this to save credits. Check that status and reason appear as you expect. Then run it on 10 rows, then on the table.
Timing
A live mailbox check talks to the recipient's mail server, and some servers are slow. Most rows finish in seconds. Our API docs recommend allowing about 30 seconds per call. A table of 2,000 rows at 100 a minute takes about 20 minutes. For tens of thousands of rows, exporting a CSV and uploading it is faster. See how long bulk verification takes.
Step 5: Route rows by result
Add the push-to-sequencer column after verification, with its own run condition: only run if status is valid. Then handle the other two results:
| Status | Common reasons | What to do in Clay |
|---|---|---|
| valid | Mailbox exists | Push to the main campaign |
| risky | Accepts all addresses; role-based address; provider hides mailbox status; server would not confirm | Push to a separate, smaller campaign, or to manual outreach |
| invalid | Mailbox not found; no mail server; disposable address; invalid format | Do not push. Try the next provider in the waterfall, or mark the lead |
For invalid rows, a common pattern is to run another finder only when the first email came back invalid, then verify the new result with a second HTTP API column. That keeps the waterfall honest: each found address is checked, not just the first.
For risky rows, read our guide on whether to email catch-all addresses. The short answer: yes, in a separate campaign with a volume cap, after a small test batch.
Worked example (illustrative numbers)
The numbers below are invented to show the flow. They are not benchmarks.
An agency builds a Clay table of 1,500 heads of marketing at SaaS companies.
| Stage | Rows | Note |
|---|---|---|
| People found | 1,500 | From a company list |
| Email found by waterfall | 1,180 | 320 with no email |
| Verification column run | 1,180 | Run condition skipped the 320 empty rows |
| valid | 760 | Pushed to the main campaign |
| risky | 330 | Mostly "Accepts all addresses"; pushed to a capped test campaign |
| invalid | 90 | Second finder tried; 25 new addresses found and re-verified |
The main campaign launches with only addresses whose mailbox was confirmed that day. The catch-all segment is tested separately, so a high bounce rate there cannot pause the main sending inboxes. Our cold email use case explains why sequencers pause on bounce rate and how to stay under each line.
Verify phone numbers in the same table
If your table also holds phone numbers for calling or SMS, add a second HTTP API column:
| Field | Value |
|---|---|
| Method | GET |
| Endpoint | https://simpleverifier.com/api/v1/phone |
| Query parameters | phone = /Phone, country = /Country Code (two letters, used for numbers written without +) |
The response includes phone_status, phone_e164, phone_country and phone_type. On the Email + Phone plan, valid numbers also get a live carrier lookup with phone_carrier and phone_line_type (mobile, landline or VoIP). That lets you send landlines to a calling sequence and keep them out of SMS. No lookup can confirm someone is using a number today. See our guide to mobile vs landline lookup.
Keep the evidence with the row
Two small additions make the table useful later, when someone asks why a lead was or was not contacted.
Record the date of the check. Add a column that stores the date the verification column ran. A result describes the mailbox on that day only. When you export the table, the date travels with it, and anyone re-using the list can see how old the result is.
Keep the reason, not just the status. "Risky" covers several different situations. "Accepts all addresses" means the domain is catch-all. "Role-based address" means the address reaches a team inbox such as sales@. "Provider hides mailbox status" means the mail provider does not reveal whether the mailbox exists. Each one calls for a different decision, and our guide to role addresses covers the second. If you only keep the status, that information is lost at export.
Both columns also help when a campaign bounces. You can match bounced addresses back to their verification date and reason, and see whether the problem was age, a catch-all segment, or something else.
Common problems
| Symptom | Likely cause | Fix |
|---|---|---|
| 401 on every row | Header value missing "Bearer " | Edit the saved header account |
| 402 on every row | Subscription not active | Check the plan; packs do not include API access |
400 "Pass the address as email" |
Column reference empty or misspelled | Check /Email matches the column name; add the run condition |
| Bursts of 429 | Rate limit too high, or key shared | Lower the request limit, split keys |
| Status column blank | Field path not returned | Add status and reason to the field paths |
Re-verify before re-using a table
A Clay table is a snapshot. If you push the same rows again weeks later, re-run the verification column first. Mailboxes close and people change jobs. Our guide on how often to re-verify gives cadences by list type. SimpleVerifier caches confirmed results by address for 14 days, so re-running a recently checked table returns quickly.
What it costs
API access is included in SimpleVerifier's Pro plan at $29.99 a month, with unlimited email verification and no per-call credits. The Email + Phone plan at $49.99 a month adds 5,000 live phone carrier lookups a month. If you would rather export from Clay and verify a CSV now and then, pay-as-you-go packs cost $9 for 2,500 or $19 for 10,000 verifications, and credits never expire. See pricing.
The short version
Add an HTTP API enrichment column after email finding. Save the key as a header account, GET the verify endpoint with /Email as the email parameter, return status and reason, and set the rate limit to 100 requests per 60,000 ms. Only run it when the email is not empty, and test one row first. Push valid rows to the campaign, send risky rows to a capped side campaign, and retry invalid rows with another finder.
Common questions
Can Clay verify emails?
Clay can call any verification API through its HTTP API enrichment. The important part is the order: find the email, verify it, and only then push it to your sequencer.
Why verify emails that Clay's providers already found?
Because finding and verifying are different checks, done at different times. Some providers return a likely address built from a name pattern, and some mark addresses at catch-all domains as found. A verification check just before sending tells you which ones the mail server will accept today.
How do I reference a column in a Clay HTTP API request?
Clay's docs say column references use a forward slash. In a query parameter, the value can be /Email. In a JSON body, string references need quotes, for example "email": "/Email".
How do I avoid 429 errors from the verification API in Clay?
Set the enrichment's rate limit below the provider's limit. Clay's HTTP API settings take a request limit and a duration in milliseconds. For an API that allows 120 calls a minute, 100 requests per 60,000 ms is a safe setting. Clay's docs list 429 as too many requests and point to the rate limit settings as the fix.
Should I delete risky emails in Clay?
No. Risky usually means a catch-all domain or a server that would not confirm the mailbox. Many of those are real people at real companies. Keep them, label them, and send them through a smaller campaign with its own volume cap.
Verify unlimited addresses for $29.99/month
Real SMTP mailbox checks. No credits, no per-email fees.
Get Started