Editing and Spam-Checking a Campaign Sequence with the Clay CLI
Editing and Spam-Checking a Campaign Sequence with the Clay CLI
Add a step to a campaign's sequence, then score its real copy against Clay's spam checker before ever activating the campaign, using campaigns sequence edit and campaigns sequence spam-check, two commands built to be chained.
What you will build
An edit that appends a new email step to a variant, followed by a spam-check that scores the persisted copy and flags concrete issues.
clay campaigns sequence edit <campaign-id> --input '{"ops":[...]}'
↓
clay campaigns sequence spam-check <campaign-id> --variant-id <id>
↓
{ score, grade: "good"|"fair"|"poor", issues[] }
AI Prompt
Using the Clay CLI, add a step to a campaign sequence and spam-check it.
Requirements:
- `clay campaigns sequence edit <campaign-id> --input '{"ops":[...]}'` applies
ordered operations: addStep, updateStep, deleteStep, reorder. Each op
carries its own "variantId", so one batch can touch multiple variants.
- addStep on a NEW_EMAIL_THREAD step requires "subject". A REPLY_TO_THREAD
step must omit "subject" -- it inherits the nearest thread's subject.
- Status gates what's editable: draft supports every op; paused supports
only updateStep; active and completed reject every listed operation.
- `campaigns sequence spam-check <campaign-id> --variant-id <id>` analyzes
PERSISTED copy only -- it does not generate AI snippets or resolve lead/
sender variables. It returns a 0-100 "score", a "grade" (good/fair/poor),
and an "issues" array, each issue carrying a severity (high/medium/low)
and, for pattern-based issues, the literal "matches" found.
- Spam-check categories include trigger words, excessive punctuation, no
spintax (identical wording at volume becomes a fingerprint), no sender
variables, and low variance density for the copy's length.
- Run the verification step below before finishing.
Prerequisites
- The
clayCLI on PATH, authenticated viaclay login(an OAuth session, not a Public API key) jq- A draft campaign with at least one variant (
clay campaigns get <campaign-id>to find itsvariants[].id)
Note: JSON samples below are trimmed to the fields relevant to each step. Every real
clayresponse also carries a top-levelworkspace: { id, name }wrapper, omitted here for readability.
1. Add a sequence step
clay campaigns sequence edit cam_0tl84os74M6XWkVnp2s --input '{
"ops": [{
"op": "addStep",
"variantId": "cvar_0tl84osg4SnpDFyhZZa",
"emailType": "NEW_EMAIL_THREAD",
"delayDays": 0,
"subject": "Quick question about {{lead:company|your company}}",
"body": "Hi {{lead:first_name|there}}, act now and click here for a FREE guaranteed discount, no cost, 100% risk-free!!!"
}]
}'
2. Spam-check the persisted copy
clay campaigns sequence spam-check cam_0tl84os74M6XWkVnp2s --variant-id cvar_0tl84osg4SnpDFyhZZa
Real output against the deliberately spammy copy above:
{
"variant": { "id": "cvar_0tl84osg4SnpDFyhZZa", "name": "Variant A" },
"score": 32,
"grade": "poor",
"issues": [
{
"id": "trigger-words",
"severity": "high",
"title": "Spam trigger words",
"matches": ["act now", "click here", "discount", "free", "no cost", "100%", "guaranteed", "risk-free"]
},
{ "id": "excessive-punctuation", "severity": "medium", "matches": ["!!!"] },
{ "id": "no-spintax", "severity": "medium" },
{ "id": "no-sender-variables", "severity": "low" },
{ "id": "low-variance-density", "severity": "low" }
]
}
A score of 32 and grade "poor" for copy stacked with classic spam patterns. This ran against real persisted sequence content, not a lint-style static check on the input string.
3. Rewrite and re-check
clay campaigns sequence edit cam_0tl84os74M6XWkVnp2s --input '{
"ops": [{
"op": "updateStep",
"variantId": "cvar_0tl84osg4SnpDFyhZZa",
"stepId": "50fbf989-ac42-4201-abc4-79e5abee45eb",
"subject": "Question about {{lead:company|your company}}",
"body": "Hi {{lead:first_name|there}}, saw your team is hiring for {{lead:title|the role}}, worth a quick chat?"
}]}'
clay campaigns sequence spam-check cam_0tl84os74M6XWkVnp2s --variant-id cvar_0tl84osg4SnpDFyhZZa | jq '{score, grade}'
Verify the result
Confirm the behavior above holds by re-running the key command and checking the result:
clay campaigns sequence spam-check cam_0tl84os74M6XWkVnp2s --variant-id cvar_0tl84osg4SnpDFyhZZa
Expected: Deliberately spammy persisted copy (trigger words, excessive punctuation, no spintax) scores 32/100, grade poor, with each issue's real matched phrases listed.
How it works
The two commands are designed to be chained in a review loop: sequence edit persists content, sequence spam-check scores exactly what's persisted; never draft text you haven't saved, and never AI-generated snippets or resolved variables, since those vary per lead and per send. That scoping is deliberate: it's checking the author's own copy for patterns that hurt deliverability regardless of which lead or sender ends up filling the placeholders.
Common issues
Spam-check score looks unaffected by an AI snippet placeholder
Cause: expecting the checker to evaluate what a snippet or variable will resolve to.
Fix: it explicitly does not generate AI snippets or resolve lead/sender variables: it scores the literal persisted copy, tokens and all.
addStep/updateStep rejected on an active campaign
Cause: assuming sequence edits are always allowed.
Fix: status gates apply: active and completed campaigns reject every sequence operation; paused allows only updateStep. Pause or keep the campaign in draft to make structural changes.
Next steps
- Once a variant scores well, start a real A/B test on it with
clay campaigns variants start-test. - Re-run
campaigns audienceafter adding a step that references a new field, to confirm that field is reliably populated.
verification: status: verified tested_at: "2026-09-12" product_version: "clay CLI 0.19.0" command: "clay campaigns sequence spam-check cam_0tl84os74M6XWkVnp2s --variant-id cvar_0tl84osg4SnpDFyhZZa" expected_result: "Deliberately spammy persisted copy (trigger words, excessive punctuation, no spintax) scores 32/100, grade poor, with each issue's real matched phrases listed."