- Validation (pre-flight check)
- Launch (go live)
- Runtime controls — pause, resume, cancel
- Retry (rerun a failed or cancelled run on the still-pending recipients)
1. Validate (pre-flight)
Dashboard: sign in at https://briq.tz/login, open the campaign, and click Validate in the action bar. The UI shows green for a clean validation, or a list of issues to fix. The Launch button runs the same checks automatically, so most teams only invoke Validate explicitly while iterating on content or audience filters. Developer API:POST /v1/campaign/{campaign_id}/validate
The endpoint is read-only — it does not mutate campaign state, so it is safe to call repeatedly (for example, from a “Looks good?” preview screen in your own admin tool).
Success response (valid)
Response when invalid
Same envelope, withdata.valid: false and human-readable strings in data.issues[]:
estimated_cost is in service units, not currency. The map is keyed by channel and reports SMS parts, voice minutes, or push notifications — never a money amount. Do not render these numbers with a currency symbol. To show a monetary estimate, multiply by your account’s per-unit rates client-side.Errors
No 400 or 409 originates from
/validate itself — surface-level rejections (auth, scope, existence) only.
Code samples
2. Launch
Dashboard: on the campaign view at https://briq.tz/login, click Launch. The dashboard auto-validates the campaign, marks it ready, and triggers the earliest pending run. If validation fails, you see the same issue list as the Validate panel — fix the issues and click Launch again. Developer API:POST /v1/campaign/{campaign_id}/launch
Launch is a composite operation: it validates the campaign, marks it ready, and triggers a run in one call.
Request body
When
run_id is omitted, the server selects the earliest run whose status is "ready", ordered by scheduled_at ascending with nulls last.
Success response
Carries the triggered run withstatus: "scheduled". The parent campaign flips to scheduled.
Recurring template runs. For a recurring template run (one where
recurrence_index is null), launch materialises the child occurrences and retires the template. From that point on, each occurrence has its own run_id and lifecycle.Errors
Code samples
3. Pause and resume
Dashboard: on the running campaign view at https://briq.tz/login, use the Pause and Resume buttons. Pause halts in-flight runs after the current batch; Resume flips them back to scheduled and reschedules them for immediate pickup.Pause
POST /v1/campaign/{campaign_id}/pause
Stops in-flight runs mid-flight. Internally, the server sets a Redis flag and flips active runs — those in running or the internal claimed state — to paused. The endpoint is idempotent: calling pause on an already-paused campaign returns 200 OK.
Runs that were scheduled or ready at pause time are not touched — they remain dormant on their own schedule and will pick up normally unless you also cancel.
Pause is not instantaneous. The worker finishes the current 1000-recipient batch before halting. After the pause call returns, you may still see a few hundred additional
sent_count reach recipients. Do not rely on pause as a “stop sending now” guarantee — for that, use cancel.Success response
Errors
No 400 or 409 from this endpoint — pause is always accepted on a non-terminal campaign.
Code samples
Resume
POST /v1/campaign/{campaign_id}/resume
Clears the pause flag and flips paused runs back to scheduled. The endpoint is idempotent: calling resume on a campaign that was never paused is a no-op (the Redis pause key is deleted whether it existed or not).
Success response
Errors
Code samples
4. Cancel
Dashboard: on the campaign view at https://briq.tz/login, click Cancel campaign. A confirmation dialog warns that cancellation is permanent before the action commits. Developer API:POST /v1/campaign/{campaign_id}/cancel
What happens internally
- Sets the Redis cancel flag so the worker stops claiming new batches.
- Flips every non-terminal run (
ready,scheduled,claimed,running,paused) tocancelled. - Marks the parent campaign
cancelled. - Refunds unsent reservations synchronously. Failures here are logged and retried by an out-of-band reconciler cron — the campaign stays
cancelledeither way.
Success response
Errors
Code samples
5. Retry a failed or cancelled run
Dashboard: at https://briq.tz/login, open the run’s detail view (any run infailed or cancelled state) and click Retry run. The dashboard skips recipients whose messages already reached SENT or DELIVERED and reruns the rest.
Developer API: POST /v1/campaign/{campaign_id}/runs/{run_id}/retry
Retry creates a new run row with a new id, the same content, and a filtered recipient list. The new run is created in scheduled state with scheduled_at = now(), so the worker’s next pickup tick claims it.
The returned
run_id is new — not the original. Keep both for audit. The new run’s snapshot includes a retry_of_run_id field pointing back at the source run.Filter mechanism
The retry recipient list is built by joiningcampaign_recipients.provider_message_id to messages.message_id. Any recipient whose latest message status is SENT or DELIVERED is excluded from the retry. Everything else — PENDING, FAILED, never-dispatched — is included.
Success response
Same shape as/launch:
Errors
Code samples
Quick reference
Next
- Track in-flight progress, per-run counters, and webhook signals in Campaign observability.