Fetching a Campaign's Full Config with the Clay CLI
Fetching a Campaign's Full Config with the Clay CLI
Pull a campaign's settings, AI context, audience reference, and every sequence variant's steps in a single call, using Clay's real campaigns get command, which returns the same editable shape campaigns update accepts back.
What you will build
A single read that returns everything needed to reason about a campaign programmatically: its settings, Claygent context, audience, and full sequence content across all variants.
clay campaigns get <campaign-id>
↓
{ settings, claygentContext, claygentSettings, audience, leadFields, variants[].sequence[] }
AI Prompt
Using the Clay CLI, fetch a campaign's complete editable configuration.
Requirements:
- `clay campaigns get <campaign-id>` returns { id, name, status, settings,
claygentContext, claygentSettings, audience: { baseSegment: { id }|null },
leadFields: [{ fieldId, label, required }], variants: [{ id, name,
weightBps, sequence: [...] }], createdAt, updatedAt }.
- Sequence steps come in two shapes distinguished by "emailType":
NEW_EMAIL_THREAD steps carry "subject"; REPLY_TO_THREAD steps carry
"threadSubject" instead and inherit the nearest thread's subject line.
- Sequence subjects and bodies use Clay's lossless campaign text grammar. A
document that cannot be represented losslessly comes back as
{ "raw": <object>, "conversionError": <string> } instead of a plain string,
and that sequence step is marked "readOnly": true.
- This is a read-only command: it returns the exact shape `campaigns update`
and `campaigns sequence edit` accept as input, so a working config can be
captured here and replayed elsewhere.
- Run the verification step below before finishing.
Prerequisites
- The
clayCLI on PATH, authenticated viaclay login(an OAuth session, not a Public API key;campaignsreturnsauth_forbiddenunder a Public API key, confirmed live) jq
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. Fetch the full config
clay campaigns get cam_0tl84os74M6XWkVnp2s
Real output, a draft campaign with an audience attached and one sequence step:
{
"id": "cam_0tl84os74M6XWkVnp2s",
"name": "TPC CLI Docs Test Campaign",
"status": "draft",
"settings": {
"scheduleSettings": {
"scheduleType": "prioritize_deliverability",
"timezone": "America/New_York",
"daysOfWeek": ["mon", "tue", "wed", "thu", "fri"],
"startHour": "09:00",
"endHour": "17:00"
},
"senderAccountIds": [],
"isHtmlEnabled": false,
"followUpPercentage": 100
},
"claygentContext": { "attachedContextItems": [] },
"claygentSettings": { "enabledSkills": [] },
"audience": { "baseSegment": { "id": "audseg_0tjs3u3yAgacWPpe926" } },
"leadFields": [
{ "fieldId": "company", "label": "your company", "required": true },
{ "fieldId": "first_name", "label": "there", "required": true }
],
"variants": [
{
"id": "cvar_0tl84osg4SnpDFyhZZa",
"name": "Variant A",
"weightBps": 10000,
"sequence": [
{
"id": "50fbf989-ac42-4201-abc4-79e5abee45eb",
"subject": "Quick question about {{lead:company|your company}}",
"body": "Hi {{lead:first_name|there}}, ...",
"delayDays": 0,
"order": 0,
"html": false,
"emailType": "NEW_EMAIL_THREAD"
}
]
}
]
}
2. Pull just the sequence content
clay campaigns get cam_0tl84os74M6XWkVnp2s | jq '.variants[].sequence'
3. Check which lead fields the sequence actually references
clay campaigns get cam_0tl84os74M6XWkVnp2s | jq '.leadFields'
leadFields lists every field the persisted sequence copy references (via {{lead:<fieldId>|<fallback>}}), each flagged required: this is derived from the sequence content itself, not a separate setting.
Verify the result
Confirm the behavior above holds by re-running the key command and checking the result:
clay campaigns get cam_0tl84os74M6XWkVnp2s
Expected: The campaign's full settings, Claygent context, audience reference, lead fields, and every variant's real sequence steps are returned in one response, in the same shape campaigns update accepts as input.
How it works
campaigns get is intentionally the mirror image of campaigns update: the same object shape flows both directions, so a script can read a campaign, patch a field locally, and write the whole settings/claygentContext block back without translating between a "read" shape and a "write" shape. The sequence's lossless campaign text grammar exists because sequence copy carries structured tokens (lead variables, spintax, links) that a plain string can't always round-trip: when it can't, the API tells you plainly via conversionError rather than silently corrupting the copy.
Common issues
Treating subject as always present on a sequence step
Cause: the first step in most sequences is NEW_EMAIL_THREAD, which does carry subject, so it's easy to assume every step does.
Fix: a REPLY_TO_THREAD step carries threadSubject instead (or nothing; it inherits the nearest thread's subject). Branch on emailType before reading either field.
auth_forbidden despite a valid CLAY_API_KEY
Cause: assuming a Public API key covers every clay command.
Fix: campaigns get requires an OAuth session (clay login), confirmed live: a scoped Public API key returns auth_forbidden here.
Next steps
- Feed a captured
settings/claygentContextobject intoclay campaigns update <campaign-id> --input -to replay it on a new campaign. - Feed
variants[].sequenceintoclay campaigns sequence editto make targeted step-level edits instead of rewriting the whole sequence.
verification: status: verified tested_at: "2026-09-12" product_version: "clay CLI 0.19.0" command: "clay campaigns get cam_0tl84os74M6XWkVnp2s" expected_result: "The campaign's full settings, Claygent context, audience reference, lead fields, and every variant's real sequence steps are returned in one response, in the same shape campaigns update accepts as input."