removedInput schema / properties / action / description
Removed value: -"'list' returns user's campaigns. 'get' returns one by id. 'create' makes a draft (requires name + channel). 'update' patches a draft. 'delete' soft-deletes. 'duplicate' clones as a draft. 'test_send' fires one message to `to` without queuing recipients. 'send_now' resolves the audience and queues all recipients for dispatch. 'schedule' sets scheduled_at. 'pause' freezes. 'resume' un-pauses. 'stop' ends an ONGOING campaign (queued people dropped, sent ones kept). 'add_recipients' names contacts on a campaign by id: on a draft, scheduled or paused one they join the audience; on an ongoing campaign that is sending they are queued now, at the first message, under the campaign's rules."
changedInput schema / properties / action / enum
Previous value: -[
- "list",
- "get",
- "create",
- "update",
- "delete",
- "duplicate",
- "test_send",
- "send_now",
- "schedule",
- "pause",
- "resume",
- "stop",
- "add_recipients"
-]New value: +[
+ "list",
+ "get",
+ "create",
+ "update",
+ "delete",
+ "duplicate",
+ "test_send",
+ "send_now",
+ "schedule",
+ "pause",
+ "resume",
+ "stop",
+ "add_recipients",
+ "preview_audience"
+]
changedInput schema / properties / audience_filter / description
Previous value: -"For create/update. `audience_filter` shape: { all: [rules], any?: [rules] }. Rules are {type, ...}. Supported in v1: { type: \"all_contacts\" } — every contact with a valid channel address; { type: \"tag\", op: \"has\" | \"has_not\", value: \"<tag_name>\" } — tag membership filter. Multiple all[] rules AND together; any[] rules OR together. Behavior queries (opened campaign X / clicked X) and custom-field queries arrive in a follow-up."New value: +"{ all: [rules], any?: [rules] }. Rules: { type: \"all_contacts\" } or { type: \"tag\", op: \"has\"|\"has_not\", value: \"<tag name>\" }. all[] ANDs, any[] ORs."
changedInput schema / properties / contact_ids / description
Previous value: -"For add_recipients: contact ids, at most 500."New value: +"add_recipients: up to 500."
changedInput schema / properties / content / description
Previous value: -"For create/update, single-send. `content` for email = { subject, preheader?, from_name?, from_email?, reply_to?, blocks: [...] }. `from_email` may be any address on ANY domain verified in the connected Resend account — call resend_manage(action='domains') first to see which are verified. An unverified domain is not rejected here; it fails later, at send time, per recipient. `reply_to` sets where replies land — use it when replies should go somewhere other than from_email. IMPORTANT for drip campaigns: exit_on:{reply} can only fire for replies Groundbase can SEE, which means an address on a mailbox connected under Settings -> Email. Point reply_to at an unconnected address and the user still gets their replies, but reply-exit stays blind and the drip keeps sending to people who answered. Settable per step as well as per campaign. Each block is { type, props }. Block types: text (props.html: HTML), header (props.html: text, props.level: 1|2|3), image (props.src: url, props.alt, props.width), button (props.text, props.url, props.bgColor?), divider (props.color?), spacer (props.height: px). `content` for SMS = { body: text, media_urls?: [urls] }. Merge tags inside any string field: {{first_name}}, {{last_name}}, {{full_name}}, {{email}}, {{phone}}, {{company_name}}, {{cf.<custom_field_key>}}. Unknown tags render empty."New value: +"Single send. Email: { subject, preheader?, from_name?, from_email?, reply_to?, blocks: [{ type, props }] }; block types text {html}, header {html, level 1-3}, image {src, alt, width}, button {text, url, bgColor?}, divider {color?}, spacer {height}. from_email must be on a domain verified in Resend (resend_manage domains) or it fails per recipient at send time. reply_to should be a mailbox connected in Groundbase, or drip reply-exit cannot see replies. SMS: { body, media_urls? }. Merge tags like {{first_name}}, {{cf.<key>}} work in any string."
changedInput schema / properties / enrolment_mode / description
Previous value: -"For create/update. 'once' (default) settles its audience when it starts and finishes when the last message goes. 'ongoing' stays sending until action='stop' and takes new entrants at any time: the audience filter is re-run every five minutes, add_recipients works while it sends, and a workflow add_to_campaign step can enrol someone. Cannot be changed to 'once' while sending — stop it instead."New value: +"'once' (default) fixes its audience at start. 'ongoing' keeps sending until stop and takes new entrants (filter re-run every 5 min, add_recipients, workflow add_to_campaign)."
changedInput schema / properties / id / description
Previous value: -"Campaign UUID — required for everything except list+create."New value: +"Campaign id; needed for all but list, create, preview_audience."
changedInput schema / properties / q / description
Previous value: -"Free-text name search for action=list."New value: +"list: name search."
changedInput schema / properties / scheduled_at / description
Previous value: -"Unix seconds for schedule/create."New value: +"Unix seconds."
changedInput schema / properties / sending_window / description
Previous value: -"For create/update. `sending_window` restricts when this campaign may send: { days: [0-6, 0=Sunday], start_hour: 0-23, end_hour: 1-24, timezone?: IANA or 'auto' }. end_hour is exclusive and must exceed start_hour. 'auto' (the default) means the account owner's timezone. A step falling due outside the window WAITS — the recipient stays queued and sends at the next open hour. Nothing fails or is skipped. Omit or pass null for no restriction."New value: +"{ days: [0-6, 0=Sunday], start_hour: 0-23, end_hour: 1-24 (exclusive), timezone?: IANA or 'auto' (account tz) }. Sends due outside the window wait for the next open hour. null = no restriction."
changedInput schema / properties / status / description
Previous value: -"Filter for action=list."New value: +"list filter."
changedInput schema / properties / steps / description
Previous value: -"For create/update when send_mode='drip'. `steps` authors a DRIP campaign (requires send_mode='drip'). Array of { delay_seconds, content_json, exit_on?, channel? } in order. `content_json` is the canonical key; `content` is accepted as an alias. Until 2026-08-30 this doc said `content` while the dispatcher read only `content_json`, so steps authored from this description silently sent step 0 every time. Step 0 fires when the campaign starts; every later step fires delay_seconds after THAT recipient's actual previous send, so a step held back by a sending window or the daily cap still spaces correctly. Each step's `content` uses the same block format as the single-send `content` param. `exit_on` is { reply?, open?, click?, meeting? } — when true and the contact has done that since the previous step, the rest of the drip is skipped for them. `channel` overrides the campaign channel for that step alone (mixed email/SMS drips); it also decides whether the step counts against the daily EMAIL cap."New value: +"Drip steps (send_mode 'drip'): [{ delay_seconds, content_json, exit_on?, channel? }]. Step 0 sends at start; each later step sends delay_seconds after that recipient's previous actual send. exit_on { reply?, open?, click?, meeting? } skips the rest for a contact who did that. channel overrides the campaign channel for the step."
removedInput schema / properties / steps / items / properties / channel / description
Removed value: -"Overrides the campaign channel for this step only."
changedInput schema / properties / steps / items / properties / content / description
Previous value: -"Alias for content_json, accepted for compatibility."New value: +"Alias of content_json."
changedInput schema / properties / steps / items / properties / content_json / description
Previous value: -"Message for this step. Same shape as the top-level content param. Canonical key."New value: +"Same shape as content."
removedInput schema / properties / steps / items / properties / delay_seconds / description
Removed value: -"Seconds after the previous step's actual send. Step 0 should be 0."
removedInput schema / properties / steps / items / properties / exit_on / description
Removed value: -"Skip the rest of the drip for a contact who has replied/opened/clicked, or booked a meeting."
changedInput schema / properties / to / description
Previous value: -"For action='test_send' — recipient email or phone."New value: +"test_send recipient."