Skip to main content

Create Campaign

Create a new campaign. Campaigns always start as a draft with the email channel.

Endpointโ€‹

POST /v1/campaigns

Authenticationโ€‹

Requires an API key with the campaigns:write scope.

Request Bodyโ€‹

FieldTypeRequiredDescription
namestringYesCampaign name (max 255 chars)
descriptionstringNoInternal description (max 500 chars)
email_subjectstringNoEmail subject line (max 255 chars, supports merge tags)
email_bodystringNoEmail body HTML (supports merge tags)
audience_typestringNoall_customers, selected_customers, or filter. Defaults to filter when audience_filter is sent, otherwise all_customers
audience_filterobjectNoFilter criteria when audience_type is filter โ€” see Audience Filter
template_keystringNoplain, announcement, promo_blast, season_opener, or win_back
cta_textstringNoButton label (max 255 chars)
cta_urlstringNoButton link (valid URL, max 2048 chars)

Example Request - Season Opener with a Preset Audienceโ€‹

curl -X POST "https://app.equipdash.com/api/v1/campaigns" \
-H "Authorization: Bearer eqd_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Summer Kayak Promo",
"description": "Promote summer kayak rentals",
"email_subject": "Summer is here, {customer_name}!",
"email_body": "<p>Hi {customer_name}, book your kayak now.</p>",
"audience_type": "filter",
"audience_filter": {
"v": 2,
"preset": "recent"
},
"template_key": "promo_blast",
"cta_text": "Book now",
"cta_url": "https://example.com/book"
}'

Example Request - Win-Back with a Custom Filterโ€‹

curl -X POST "https://app.equipdash.com/api/v1/campaigns" \
-H "Authorization: Bearer eqd_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Win-Back - Last Season",
"email_subject": "We miss you, {customer_name}!",
"email_body": "<p>It has been a while โ€” here is 25% off your next trip: {promo_code}</p>",
"audience_type": "filter",
"audience_filter": {
"v": 2,
"experience_ids": [10, 15],
"not_booked_since": "2025-06-01"
},
"template_key": "win_back",
"cta_text": "Book again",
"cta_url": "https://example.com/book-again"
}'

Response (201 Created)โ€‹

{
"data": {
"id": 42,
"name": "Summer Kayak Promo",
"description": "Promote summer kayak rentals",
"kind": "one_off",
"channel": "email",
"status": "draft",
"audience_type": "filter",
"audience_filter": {
"v": 2,
"preset": "recent"
},
"email_subject": "Summer is here, {customer_name}!",
"email_body": "<p>Hi {customer_name}, book your kayak now.</p>",
"template_key": "promo_blast",
"cta_text": "Book now",
"cta_url": "https://example.com/book",
"scheduled_at": null,
"sent_at": null,
"total_recipients": 0,
"total_sent": 0,
"promo_codes": [],
"created_at": "2026-07-20T09:00:00+00:00",
"updated_at": "2026-07-20T09:00:00+00:00"
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-07-20T09:00:00+00:00"
}
}

Errorsโ€‹

StatusCodeDescription
401authentication_requiredNo API key provided
401invalid_api_keyInvalid API key
403insufficient_scopeAPI key lacks campaigns:write scope
422validation_errorInvalid request data (e.g., missing name)

Notesโ€‹

  • email_subject and email_body can be set now or later โ€” but both are required before sending or scheduling
  • Attach promo codes and surveys in the EquipDash UI to populate the {promo_code}, {promo_discount}, and {survey_link} merge tags
  • Recipients are resolved when the campaign is sent or scheduled, not at creation time