API reference
Campaigns
Create, target, and send broadcast campaigns to your whole list or a segment.
A campaign is a one-off broadcast built from a template. Create it as a draft, then send it. Campaign sends require a live key.
The campaign object#
{
"id": "camp_x1y2z3",
"name": "March newsletter",
"subject": "What's new this month",
"preview_text": "A quick roundup",
"from_name": "Acme",
"from_email": "news@acme.com",
"target": "all",
"template": "tmpl_123",
"segment": null,
"status": "draft",
"stats": null,
"variants": [{ "id": "B", "subject": "You missed a lot" }],
"scheduled_at": null,
"sent_at": null,
"created_at": "2026-07-10T10:30:00.000Z",
"updated_at": "2026-07-10T10:30:00.000Z"
}status moves through draft → queued → sending → sent. target is all or segment.
Create a campaign#
/v1/campaignsCreates a draft. The from_email domain must be verified.
Body parameters
namestringRequiredsubjectstringRequiredfrom_namestringRequiredfrom_emailstringRequiredpreview_textstringOptionaltemplatestringOptionaltarget"all" | "segment"Optionalall.segmentstringOptionaltarget is segment.variantsstring[]Optionalconst campaign = await deckle.campaigns.create({
name: "March newsletter",
subject: "What's new this month",
from_name: "Acme",
from_email: "news@acme.com",
template: "tmpl_123",
target: "all",
variants: ["You missed a lot"],
});List campaigns#
/v1/campaignsQuery parameters
limitintegerOptional50, max 100.cursorstringOptionalstatusstringOptionaldraft or sent.const { data } = await deckle.campaigns.list({ status: "sent" });Retrieve a campaign#
/v1/campaigns/:idconst campaign = await deckle.campaigns.get("camp_x1y2z3");Update a campaign#
/v1/campaigns/:idOnly a draft campaign can be edited — updating one that’s already sending or sent returns 409. Send any of name, subject, from_name, from_email, preview_text, template, target, or segment.
curl -X PATCH https://app.getdeckle.com/api/v1/campaigns/camp_x1y2z3 \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "subject": "A better subject" }'Send a campaign#
/v1/campaigns/:id/sendSends the campaign now. The campaign must have a template. When the background worker is configured the send is queued and returns 202 with queued: true; otherwise it runs inline (capped at 200 recipients) and returns the counts.
const result = await deckle.campaigns.send("camp_x1y2z3");
// queued: { ...campaign, queued: true }
// sync: { ...campaign, sent: 184, failed: 0 }Live key required
A test key can’t send campaigns and returns403. Sending a campaign with no template returns 422; re-sending one that’s already sending returns 409.