Pick a surface
Two public paths reach the same campaign engine with the same checks, the same errors and the same results.
Reading needs
campaigns:read. Creating, launching, pausing, resuming,
stopping and deleting need campaigns:manage. The examples below use the
Messaging API; the Platform API takes the campaign id in the path. On the
Platform API a team API key names the project with projectId on every campaign
request, and a project token is bound to its own project and omits it.
Create the campaign with its recipients
Use the console
In the campaign builder, choose an audience, import a CSV, or paste phone numbers. The import summary shows the recipients kept, duplicates, and invalid rows. For pasted numbers, the summary stays visible after import so you can correct the source numbers before continuing. Wait for Draft saved before launching. If saving fails, the builder shows the reason and marks the changes as unsaved. A plan or sending restriction also appears in the review step; resolve it before launching. The review step checks the selected audience again. If its recipient count changed since the draft was saved, review the new count and confirm it before launching. The builder checks once more when you launch; if the count changes during review, it stops and asks you to confirm the updated audience. Write any opt-out instruction in your message. The builder does not append a footer or send a separate consent prompt. Review your team’s keyword settings before sending. Scheduling uses your browser’s local time zone. Check the zone beside the date and time and again in the review step before scheduling.Use the API
Send recipients inline, point at an audience withrecipientListId, or do
both.
recipients accepts at most 1,000 entries and is all or nothing: one
invalid entry refuses the request and names it, so a campaign is never created
with someone silently missing. A number repeated inside the request is kept
once. The same number and variable rules apply as for audience members.
senderConfig.sessionIds pins the numbers the campaign sends from. A campaign
that pins none draws from every number in its project that is connected, not
banned, and on a plan that includes Campaigns.
Add more recipients while the campaign is still a draft, 1,000 per request:
added, recipientCount, duplicateCount, invalidCount
and up to 20 invalidRows, and skips a number already on the campaign. Once the
campaign has been launched, appending returns 409.
To send to a different audience, update the draft with another
recipientListId. After the campaign launches, the audience is fixed and the
update returns 409. Changing a draft’s audience replaces its existing
recipients; add any individual recipients you still want after the change.
Launch
scheduledAt, or right away when no start time is set. At
launch, Polymorfa copies the audience into the campaign, skips numbers on the
team’s opt-out list, and sets
recipientCount from the recipients that exist.
For a scheduled campaign, this snapshot happens when the launch request is
accepted. Later additions, removals or changes to the source audience do not
change that campaign’s recipients. Opt-outs are checked again before sending.
Launch re-runs the create checks against the campaign’s stored settings, so a
campaign drafted while its numbers were entitled is refused if they moved to
another plan in between:
Create, launch, pause, resume and stop accept an
Idempotency-Key header on the
Messaging API; the Platform API accepts it on launch, pause, resume and stop. A
repeated key is never a second launch. See
Errors.
Follow the send
List recipients in queue order with cursor pagination.limit is 1 to 100 and
defaults to 25.
page.nextCursor until page.hasMore is false. Filter with status:
queued, sending, sent, delivered, read, failed or skipped.
lastError gives the stable reason a recipient failed or was skipped, such as
opted_out. It never contains message content.
Campaign analytics report the funnel and the reply timing:
A reply counts once per recipient. It is attributed to the most recent recipient
that the replying number was sent to, on the same sending number, within 7 days
of that send.
The Platform API also lists the campaign’s lifecycle history, most recent first:
kind — launched, paused, resumed, cancelled,
completed or failed — and the time it happened. A failed entry has
payload.reason: "all_recipients_failed". The campaign fails when every recipient
settles as failed. If any recipient was sent or skipped, the
campaign completes and its counts show those outcomes.
Pause, resume and stop
skipped with lastError campaign_cancelled and is counted once in
skippedCount. The campaign moves to
cancelling, then to cancelled once sends already in progress finish. A
campaign with no active delivery run is cancelled at once and operationId is
null. Stopping is never blocked by suspension or by a lost plan entitlement,
so a restricted campaign can always be stopped.
In the console, Stop requested confirms that your request was accepted.
The detail page refreshes until the campaign reaches Cancelled and shows
the final recipient results. Sends already in progress can finish during this
transition.
A campaign that has no active delivery run cannot be paused or resumed. Stop it,
duplicate it, and launch the copy.
Archive or delete
Archive acompleted, failed or cancelled campaign when you want to keep
its history while marking it archived. A campaign that is still starting,
running, paused or stopping cannot be archived.
Delete removes a draft, completed, failed, cancelled or archived campaign. Any
other campaign, and a draft that still has a scheduled launch, is refused with
409: stop it first, then delete it.
If a completed or failed campaign still has a final event to deliver, delete or
archive returns 409. Archive and delete also wait for the delivery run
to finish. Retry after the event and run have finished.
Retry what failed
POST .../requeue moves failed recipients back to queued. Set
includeSkippedError to true to re-queue skipped recipients as well. A number
on the team’s opt-out list is never claimed for sending, whatever its recipient
status is.