Blog | GenFlows

Clay + Smartlead Integration: Push Leads In Cleanly

Written by GenFlows Team | Aug 5, 2026, 7:46:50 PM

TL;DR

  • It's six discrete actions, not a sync. Clay ships Add, Lookup lead, Lookup status, Update, Update category and Remove — and every one of them requires a campaign that already exists in Smartlead. Clay cannot create campaigns.
  • An empty variable does not stop the send. Smartlead documents that a blank value simply doesn't populate — the email goes out with a hole in it. Gating in Clay is the only real defence.
  • Clay's table-level auto-run is ON by default, so rows push the moment they land — before enrichment settles. Turn it off while building, then gate the push column with one "ready to send" condition.
  • The Add action tells you nothing. Clay's docs state it returns no output fields, so cross-campaign duplicates are skipped silently. Add a Lookup status column or you are flying blind.
  • Four dedupe layers protect you — same-campaign (never overridable), cross-campaign, global block list and unsubscribes. Leave the override settings alone unless you mean it.

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.

The Short Answer

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.

What the Integration Actually Is (And Isn't)

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:

  • Campaigns must pre-exist. Clay's docs are explicit: all Smartlead actions require a campaign set up in Smartlead, and campaigns cannot be created from Clay. If a push fails, check that the campaign exists and is active before you debug anything else.
  • Writes are one-way. There is no bidirectional sync object. The lookup actions read data back into Clay, which is how you build a verification loop — but nothing reconciles automatically.
  • Update requires a lookup first. The 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.

The Failure That Costs Real Money: Blank Variables Still Send

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:

  1. In Clay: a conditional run that refuses to push an incomplete row (next section).
  2. In Smartlead: conditional blocks in the copy, so a missing value degrades gracefully instead of leaving a hole.

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:

  • Operators must be single-quoted. Use '==', not ==. Smartlead documents this explicitly.
  • There is no | default: filter. Despite the "Liquid" label, real Liquid's {{ var | default: "there" }} appears nowhere in Smartlead's docs. Use #if / else instead.
  • Two delimiter styles coexist. Lead and custom variables use braces. Sender variables use percent signs — %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.

The Gate: Stop Clay Pushing Half-Enriched Rows

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:

  1. While building, turn table-level auto-run OFF and test on 5–10 rows. Clay recommends exactly this to avoid burning credits on accidental runs.
  2. Leave "Keep existing results" checked so only errored, empty or new cells run automatically — cells with data won't re-run and overwrite themselves.
  3. Build one "ready to send" column — a formula that is TRUE only when the email is verified and every variable from your copy inventory is non-empty. One boolean you can reason about beats ten scattered conditions.
  4. Set the push column's "Only run if" to that column. Clay's conditional runs support AND/OR/NOT and a plain-language "Use AI" builder if you'd rather describe the rule than write it.

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.

The Workflow, Step by Step

# 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

Field Map, With Write Rules

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.

Deduplication: Four Layers

Smartlead applies four checks on import, and understanding them stops you double-emailing prospects:

  1. Within the same campaign — duplicate emails are always skipped. Not overridable.
  2. Across campaigns — controlled by the setting Clay surfaces as "Allow Duplicate Leads Across Campaigns?", which by default blocks them.
  3. Global block list — blocks an address or an entire domain, applies across all campaigns in the account, and is automatically excluded from future imports. It can be activated mid-campaign.
  4. Unsubscribes — previously unsubscribed leads are skipped.

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.

Where the Docs Disagree — Set These Explicitly

Four places where we could not give you a single confident answer, because the vendors themselves don't:

  • Community bounce list defaults are opposite. Clay's UI says leads will be added even if they're on Smartlead's community bounce list by default; Smartlead's API says the equivalent flag defaults to checking that list, and advises leaving all such overrides off. Set it deliberately in whichever interface you're using and verify with a test lead.
  • Custom-field limits are documented three ways — the API reference says a maximum of 200 key-value pairs per lead, the CSV help article says up to 40, and the core concepts page says unlimited. Design for well under 40 and you satisfy all three.
  • Clay's plan gate for this integration is unclear. The integration and HTTP API doc pages leave the plan field blank while the marketplace listing shows a higher-tier badge. Check the badge in-app rather than trusting any blog, including this one.
  • Send timezone is campaign-level, not per lead. The schedule carries the timezone, days and hours; no per-lead timezone field is documented. Sending in each prospect's local morning means splitting into per-timezone campaigns.

When to Drop to the Raw API

The native action is right for most teams. Swap it for Clay's HTTP API action when you need what the native path hides:

  • Error detail. 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.
  • Batching. Up to 400 leads per request, versus one API call per row.
  • Explicit suppression control. The 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.

Frequently Asked Questions

Does Clay have a native Smartlead integration, or do I need the API?

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.

If I push the same lead twice, does Smartlead send two emails?

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.

What happens if a personalisation variable is empty when the email sends?

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.

How do I stop Clay pushing half-enriched leads?

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.

What are Smartlead's API limits for adding leads?

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.

How many custom fields can I push per lead?

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.