MessagingCampaigns

Campaigns

Trigger dashboard-created messaging campaigns via the API

Overview

Campaigns are automated messaging workflows that send push notifications to your users based on triggers. Campaigns are created and managed in the Flameup dashboard — including their trigger type, audience, templates, and schedule. The API's role is to trigger a campaign so it runs for its configured audience.

Required Permission: campaigns:trigger to trigger a campaign via the API.

Trigger Types

When you build a campaign in the dashboard, you choose one of four trigger types:

  • Event — starts when a user performs any of the trigger's listed events (for example, one purchase campaign listening on both a PhonePe and a QR payment event). An optional first occurrence mode fires only the first time Flameup has ever seen the event for that person — useful for treating a first login as a signup.
  • Webhook — started by calling the trigger endpoint below. Ideal for backend-initiated notifications and third-party integrations.
  • Schedule — runs at defined times (for example, a weekly digest).
  • Dynamic Schedule — sends relative to a per-user date (for example, a trial-expiration reminder).

The trigger type and its configuration are set in the dashboard. Only webhook campaigns can be triggered from the API. Calling the trigger endpoint on an event, schedule, or dynamic-schedule campaign returns 400 telling you so — those run from their own triggers only. To start something on demand, build it as a webhook campaign.

Trigger a Campaign

Start a campaign so it runs for its configured audience.

Endpoint: POST /api/v1/campaigns/{campaign_id}/trigger

Headers

HeaderRequiredDescription
AuthorizationYesBearer <your_api_key>
Content-TypeYesapplication/json
Idempotency-KeyNoA key you choose that makes this trigger safe to retry. Max 255 bytes, printable ASCII only. Remembered for 24 hours, scoped to this workspace and campaign.
Send an Idempotency-Key on any trigger you might retry. This endpoint fans out to the campaign's entire audience inside the request. Without a key, a retry after a timeout or a partial failure sends to everyone again — including the people the first attempt already reached — because the endpoint has no record of which people it got to. With a key, a retry inside the 24-hour window replays the first result instead of sending again.

Idempotency is opt-in: omit the header and the endpoint behaves exactly as it always has (it sends, and a retry sends again). When a key is honoured, the response echoes it back as idempotency_key, so you can tell an honoured key from an ignored one without guessing.

Request Body

FieldTypeRequiredDescription
workspace_idstringYesThe workspace that owns the campaign. Must match your API key's workspace.
trigger_dataobjectNoCustom context data passed to the campaign workflow for personalization.
// Generate once per logical trigger, then reuse it for every retry
const idempotencyKey = crypto.randomUUID();

const response = await fetch(
  `https://api.flameup.ai/api/v1/campaigns/${campaignId}/trigger`,
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${API_KEY}`,
      // Reuse this exact key when retrying, so the retry replays
      // the first result instead of re-sending to the whole audience
      'Idempotency-Key': idempotencyKey
    },
    body: JSON.stringify({
      workspace_id: WORKSPACE_ID,
      // Optional custom data for personalization
      trigger_data: {
        promo_code: 'SAVE20',
        expires: '2024-02-01'
      }
    })
  }
);

const result = await response.json();
console.log(`Triggered for ${result.people_queued} people`);
if (result.audience_truncated) {
  console.warn('Audience truncated at the safety ceiling — matching people were NOT triggered');
}

Response

A successful trigger returns HTTP 202 Accepted:

{
  "success": true,
  "campaign_id": "550e8400e29b41d4a716446655440000",
  "status": "processing",
  "triggered_at": "2024-01-15T10:30:00Z",
  "people_queued": 42,
  "idempotency_key": "3f1c9a52-7f2e-4a1b-9c33-2b7e5d0a8e41",
  "message": "Campaign 'Welcome Back' triggered for 42 people"
}
FieldTypeDescription
successbooleanWhether the trigger was accepted
campaign_idstringThe campaign that was triggered
statusstringprocessing on a fresh trigger — the audience is queued asynchronously. completed on an idempotent replay, where duplicate is true and the result describes the earlier trigger
triggered_atstringTimestamp when the trigger was accepted. On a replay, the timestamp of the original trigger
people_queuedintegerNumber of people the fan-out reached. Can be 0 when nobody matched — still a 202. When audience_truncated is true this is the safety ceiling, not the size of the audience
audience_truncatedbooleantrue when the fan-out stopped at the endpoint's safety ceiling instead of at the end of the audience — people matching the campaign were not triggered. Omitted when false
duplicatebooleantrue when this response replays an earlier trigger carrying the same Idempotency-Key instead of sending again. Omitted when false
idempotency_keystringEchoes the key this trigger was recorded under. Omitted when you sent no key
messagestringHuman-readable status message. A truncation warning is appended to it whenever audience_truncated is true
Audiences are truncated at a safety ceiling, not queued in full. This endpoint fans out synchronously inside the request, so it stops at WEBHOOK_MAX_AUDIENCE (default 10,000 people) and the people beyond it are never triggered. It still answers 202, and people_queued still looks like a complete send — audience_truncated is the only field that distinguishes a full fan-out from a capped one, so check it. To reach a larger audience, run the campaign on a schedule (that path is not request-scoped and carries a far higher ceiling — 250,000 by default) or ask your operator to raise WEBHOOK_MAX_AUDIENCE.

An idempotent replay — the same Idempotency-Key sent again inside the 24-hour window, after the first trigger finished — returns 202 with the original result and no second send:

{
  "success": true,
  "campaign_id": "550e8400e29b41d4a716446655440000",
  "status": "completed",
  "triggered_at": "2024-01-15T10:30:00Z",
  "people_queued": 42,
  "duplicate": true,
  "idempotency_key": "3f1c9a52-7f2e-4a1b-9c33-2b7e5d0a8e41",
  "message": "Campaign 'Welcome Back' was already triggered with this Idempotency-Key for 42 people; it was not sent again"
}

Errors

All flat-shape ({"error": "..."}):

StatusWhenerror
400The campaign is not a webhook campaigncampaign with trigger type '<type>' cannot be triggered via API (only webhook trigger type supports API triggering)
400The campaign is not Activecampaign is not active (status: <status>)
400Idempotency-Key is longer than 255 bytes — an over-long key is rejected, never truncatedIdempotency-Key must be at most 255 bytes (it is stored whole, never truncated, so two keys sharing a prefix cannot collapse into one)
400Idempotency-Key contains a byte outside printable ASCIIIdempotency-Key must contain printable ASCII only
403Body workspace_id is not your key's workspaceAPI key does not have access to this workspace
404Unknown campaign id — or a campaign in another workspace, deliberately indistinguishablecampaign not found
409A trigger with this Idempotency-Key is still running (possibly on another replica). Nothing was sent again — retry once it finishesa trigger with this Idempotency-Key is already in progress for this campaign; the campaign was NOT triggered again
422This Idempotency-Key was already used on this campaign with different trigger_data. Use a new keyIdempotency-Key was already used for a different trigger request on this campaign; use a new key (the campaign was NOT triggered)
503You sent an Idempotency-Key but the idempotency store is unavailable, so exactly-once cannot be honoured. Nothing was sentidempotency store unavailable; the campaign was NOT triggered. Retry, or omit the Idempotency-Key header to trigger without duplicate protection
The key is only claimed after the campaign passes the checks above, so a request rejected for a bad body, the wrong workspace, a missing permission or an inactive campaign does not consume your key — the corrected retry can reuse it.

Campaign Status

Campaigns move through the following statuses, all managed from the dashboard:

Draft

Initial state. Campaign is not active and won't trigger.

Scheduled

Campaign is scheduled to activate at a future time.

Active

Campaign is live and will trigger based on its configuration.

Paused

Campaign is temporarily stopped. Can be resumed.

Completed

Campaign has finished (for one-time campaigns).

Archived

Campaign has been archived and is no longer active.

Failed

Campaign failed due to an error.

A campaign must be Active to run when triggered. Activate, pause, and archive campaigns from the dashboard.