TL;DR
Clay's enrichment is the easy part. The part that quietly wrecks campaigns is the handoff: a lead lands in Smartlead before Claygent finished writing the first line, the send goes out with a blank where the company name should be, and the prospect receives an email that reads like a broken mail merge. One bad push does more damage to a domain's reputation than a week of good copy repairs.
This is the handoff done properly — what the integration actually does, the gate that prevents half-enriched sends, a field map with per-field rules, and the places where Clay's and Smartlead's own documentation contradict each other so you can set those options deliberately instead of by accident.
Sourcing note: the actions, API mechanics, limits, dedupe rules and variable syntax here are VERIFIED against Clay's and Smartlead's own documentation as of July 2026. Where the two vendors' docs disagree — or where a behaviour genuinely isn't documented — we say so explicitly rather than picking the version that reads better. We have not invented credit costs, plan gates or rate figures for anything the docs leave blank. GenFlows is both a Clay and a Smartlead partner, which is why we know where the sharp edges are.
Build the Smartlead campaign first, inventory every variable your copy uses, then in Clay add the native Smartlead "Add lead to campaign" action and gate it with a single conditional-run formula that is true only when the email is verified and every one of those variables is non-empty. Map your personalisation into custom fields whose keys match the template variables exactly, case for case. Add a Lookup column before the push to catch duplicates and a Lookup-status column after it to confirm the lead actually entered the sequence. That gate and those two lookups are the whole difference between a clean handoff and a mail-merge disaster.
Connect it in Clay with Add enrichment → search "Smartlead" → Integrations → Select Smartlead account → + Add account, pasting the API key from your Smartlead profile settings. What you get is six separate actions, each of which you add as its own column:
| Action | What it does |
|---|---|
| Add lead to campaign | Adds a new lead to an existing campaign. Returns no output fields — you cannot see what happened |
| Lookup lead in campaign | Fetches by email. Returns Smartlead's internal Id, custom fields, Is Unsubscribed, and Lead Campaign Data — every campaign the lead is currently in |
| Lookup lead status in campaign | Returns campaign steps, emails sent, and status such as IN_PROGRESS |
| Update lead in campaign | Updates an existing lead. Requires Lead ID |
| Update lead category | Sets a category label. Requires Campaign ID, Lead ID and Category ID |
| Remove lead from campaign | Deletes the lead from the campaign |
Three constraints follow from that list, and all three catch people out:
Lead ID those actions want is Smartlead's internal identifier, not your Clay row ID. Run Lookup lead in campaign and map its Id output across.One myth to kill: this handoff is not "a webhook," whatever third-party guides tell you. Clay's webhooks are inbound only — they receive data into Clay. Pushing out is either the native Smartlead action or Clay's HTTP API action with method POST. Smartlead's own webhooks are event notifications coming out of Smartlead (replies, bounces), not a lead-ingest endpoint.
If you're new to Clay's enrichment side, start with waterfall enrichment setup and the Clay workflow playbook. This post assumes the enrichment already works and only the handoff is at stake.
This is the single most important paragraph here. Smartlead's documentation states plainly that if a row has a blank cell for a variable, that value will not populate in the email — and there is no documented setting anywhere that holds back a send because a variable is missing. Your "Hi {{first_name}}, saw the {{company_name}} launch" becomes "Hi , saw the launch" and it goes out at scale.
You have exactly two defences, and you want both:
Smartlead calls its conditional feature "Liquid Syntax," but every documented example is Handlebars-shaped:
{{#if first_name}} Hey {{first_name}}, {{else}} Hey there, {{/if}}{{#if position '==' "founder"}} As the founder of the business... {{/if}}{{#if google_review 'gte' 4}} Congrats on the reviews... {{/if}}Three syntax traps that silently break personalisation:
'==', not ==. Smartlead documents this explicitly.| default: filter. Despite the "Liquid" label, real Liquid's {{ var | default: "there" }} appears nowhere in Smartlead's docs. Use #if / else instead.%signature%, %sender-name%, %sender-firstname%, %sender-domain%, %sender-mailbox%. Writing {{signature}} produces nothing.Variable names are case-sensitive, and Smartlead also generates a few at send time that you should never push from Clay: {{sl_time_of_day}}, {{sl_day_of_week}} and {{sl_date}} for relative dates. One more genuine gap worth knowing: only first_name, company_name and phone_number have template variable names confirmed in Smartlead's docs. For location, website, linkedin_profile and company_url, no doc we could find confirms the variable name — so if you intend to use those in copy, push them as explicitly named custom fields you control rather than trusting an undocumented standard name.
Clay's table-level auto-run is the master switch and it is enabled by default — the product is designed to enrich as soon as data arrives. Wire a table to a live campaign without gating and rows will push while enrichment is still running. That is the mechanism behind almost every "why did my lead get an empty first line" report.
Clay's own best practices for this integration say the same three things: qualify before adding, use conditional runs, and look up before updating. Concretely:
Two more Clay-side levers worth knowing: filtered views only enrich the rows you're viewing, which is a crude but effective conditional; and on scheduled sources, Update Existing Rows set to "Net New" only runs enrichments on newly added records, which Clay describes as the more cost-efficient setting. On credits generally, Clay's docs do not state whether re-running a column charges again or whether a null result is billed — the only nearby signal is that re-running all rows is described as higher credit usage. We're not going to invent a rule; see our honest Clay pricing review for what is actually knowable about credits.
| # | Step | Rule that makes it safe |
|---|---|---|
| 1 | Build the campaign in Smartlead — sequence, senders, schedule, daily cap, stop-on-reply | Non-negotiable: Clay cannot create campaigns |
| 2 | Write the copy, then list every variable it uses | This list is the contract. Nothing gets pushed that isn't on it |
| 3 | Wrap every non-guaranteed variable in an #if / else block |
Blank renders as nothing and still sends — this is your in-platform net |
| 4 | Connect Smartlead in Clay with an API key | Agencies: use a per-client key, not one master key |
| 5 | Turn table auto-run OFF; keep "Keep existing results" on | Stops pushes firing mid-enrichment while you build |
| 6 | Enable auto-dedupe on the email column | It ignores blank cells and cells over 200 characters — dedupe the raw email, never a concatenated key |
| 7 | Add the "ready to send" gate column | Verified email AND all copy variables present |
| 8 | Add Lookup lead in campaign; read Lead Campaign Data and Is Unsubscribed |
The only way to see a cross-campaign collision before pushing |
| 9 | Add Add lead to campaign; map standard fields and custom fields | Custom-field keys must match template variables exactly, case included |
| 10 | Set that column's "Only run if" to the gate | Without this, flipping auto-run back on fires everything |
| 11 | Decide the duplicate and bounce-list settings explicitly | See the contradictions section — do not leave these to defaults you haven't read |
| 12 | Test 5–10 rows, then send a real test email and read every variable slot | Catches blanks before volume does |
| 13 | Add Lookup lead status in campaign as a reconciliation column | Rows whose sent-count never moves were silently skipped |
| 14 | Turn auto-run ON; enable auto-update on the push column if you want trigger-based sending | Go-live switch, once the gate is proven |
| Clay column | Smartlead field | Rule / when empty |
|---|---|---|
| Verified work email | email |
Required. Gate on it — and note blank emails are invisible to Clay's auto-dedupe |
| First name, normalised | first_name |
Use an #if / else fallback in copy. Never push a placeholder like "there" — you lose the ability to tell missing from real |
| Company name, cleaned | company_name |
Strip Inc/Ltd/LLC first. Gate on it if the subject line uses it — legal suffixes are the most visible automation tell |
| Job title | custom_fields.job_title |
Key must match the template variable exactly, case-sensitive |
| First line / hook (Claygent) | custom_fields.<your key> |
Highest-risk field. Gate on non-empty AND a minimum length, and wrap it in #if with a generic else branch |
| Trigger / signal | custom_fields.<your key> |
Wrap the whole sentence in #if so it disappears cleanly rather than half-rendering |
| Personal website | website |
Docs disagree: Clay calls this the lead's personal website, Smartlead's API calls it the company website. Pick a meaning, document it, don't use it in copy |
| ICP score / qualification flag | Not pushed | Use as the gate only — internal scores don't belong in a lead record |
Smartlead Id from Lookup |
lead_id |
Required for Update and Remove. Not your Clay row ID |
Clean inputs matter more than clever gating: see email verification tools for the verified-email step and AI cold email personalisation for writing hooks that survive a fallback.
Smartlead applies four checks on import, and understanding them stops you double-emailing prospects:
Two things to know about that. First, re-pushing the same lead to the same campaign does not create a duplicate — it is skipped — but Smartlead's docs do not state whether the skipped push updates the lead's custom fields or discards them. So when you want to refresh data, use Lookup then Update rather than re-Add. (Smartlead does promise a clean merge for CSV re-uploads into an active campaign, but nothing equivalent is documented for the API path — don't assume it transfers.)
Second, the "global" block list is client-scopable for agencies, which is both a feature and a hazard: scope it per client deliberately, or you risk one client's suppression list leaking into another's targeting. Keep the block list fed from opt-outs, competitors and bounces — the same discipline as CRM data hygiene.
Four places where we could not give you a single confident answer, because the vendors themselves don't:
The native action is right for most teams. Swap it for Clay's HTTP API action when you need what the native path hides:
POST /api/v1/campaigns/{campaign_id}/leads returns added_count, skipped_count and skipped_leads[] with a reason per lead — the diagnostic the native action simply doesn't give you.settings flags for block list, unsubscribes, cross-campaign duplicates and community bounces all default to off, and Smartlead advises keeping them that way unless you have a specific reason.Mind the rate limits, which are per API key across all endpoints combined: 60 requests a minute and 1,000 an hour on Standard, 120 and 3,000 on Pro, with burst allowances of 10 and 20 per second. Throttle client-side at around 80% of your ceiling, and back off on a 429 using the retry_after value. Clay's HTTP API action has its own request-limit control for exactly this. One security note: Clay warns that credentials typed into the Headers field are visible in plain text to anyone with table access — so scope keys per client and treat table access as credential access.
If your pipework is getting elaborate, Clay + n8n covers routing this through an orchestration layer instead, and Clay + HubSpot covers the CRM side of the same handoff.
Native. Clay ships six Smartlead actions — Add lead to campaign, Lookup lead in campaign, Lookup lead status in campaign, Update lead in campaign, Update lead category, and Remove lead from campaign — authenticated with your Smartlead API key. You only drop to Clay's HTTP API action when you need something the native action doesn't expose, such as per-lead skip reasons or batched uploads of up to 400 leads.
No. Within a single campaign, duplicate emails are always skipped and that rule cannot be overridden. Across campaigns it is controlled by the setting Clay labels "Allow Duplicate Leads Across Campaigns?", which defaults to blocking duplicates. What Smartlead's documentation does not say is whether a skipped re-push updates the lead's custom fields, so use Lookup lead in campaign followed by Update lead in campaign when you want to refresh data.
It renders as nothing and the email still goes out — Smartlead's docs state that a blank value will not populate in the email, and there is no documented setting that holds back a send on a missing variable. Your two defences are a Clay conditional run that refuses to push incomplete rows, and conditional if/else blocks in the copy so a missing value degrades into generic wording instead of a gap.
Clay's table-level auto-run is on by default, so rows push as they arrive. Turn it off while building, test on five to ten rows, then gate the Smartlead column with a single "Only run if" condition that is true only when the email is verified and every variable your copy uses is non-empty. Clay's own best practice for this integration says the same: qualify before adding and use conditional runs.
A maximum of 400 leads per request to the add-leads endpoint. Rate limits are per API key across all endpoints combined: 60 requests per minute and 1,000 per hour on Standard, 120 per minute and 3,000 per hour on Pro, with burst allowances of 10 and 20 requests per second respectively, and custom limits on Enterprise. A 429 response returns a retry_after value, and Smartlead recommends exponential backoff plus throttling at about 80% of your ceiling.
It depends which Smartlead page you read, which is worth knowing before you design around it. The API reference states a maximum of 200 key-value pairs per lead, the CSV mapping help article says up to 40 per lead, and the core concepts page says unlimited. Those three official pages are mutually inconsistent, so design for well under 40 and you are safe under all of them.
Wiring Clay into a sending stack that has to work every day? Pair this with waterfall enrichment and deliverability monitoring — or talk to our team and we'll build the Clay-to-Smartlead pipeline with the gating already in place.
By the GenFlows GTM engineering team. We are a Clay Artisan Solutions Partner and a Smartlead Certified Partner, and we run this pipeline daily for client campaigns. Actions, limits, dedupe rules and variable syntax are verified against Clay's and Smartlead's documentation as of July 2026; where their docs contradict each other we have said so rather than guessing. Last updated July 2026.