What a campaign is made of
A campaign is a parent record with three logical children. None of them are useful in isolation — the campaign only sends when all three are present and validated.- Audiences — one or more contact groups attached to the campaign. These are the recipients. A campaign with no audiences cannot be launched.
- Content — the message body or template for the campaign, one row per channel. SMS, voice, and WhatsApp each have their own content row. You cannot attach two content rows for the same channel to the same campaign.
- Runs — the scheduled executions of the campaign. A run can be single-shot (fire once at a specific time) or recurring (a cron-style schedule). A campaign with no run will never send anything, no matter how complete its audience and content are.
Dashboard vs API — when to use which
The dashboard is the default surface for campaigns. Reach for the API only when you genuinely need automation — most teams ship every campaign they will ever run from the dashboard alone.
If you are not sure which one you need, use the dashboard. Everything described on the API subpages is available there with no code.
Lifecycle at a glance
Every campaign moves through a fixed set of states. The dashboard surfaces them in the campaign header; the API returns them onGET /v1/campaign/{id}/status.
Two rules are worth memorizing:
- Editing a
readyorscheduledcampaign drops it back toconfigured. Any change to audiences, content, or runs invalidates the pre-flight check. You must call/validateagain (dashboard does this automatically when you re-open the launch panel) before you can launch. cancelledis sticky. There is no un-cancel. Cancelling refunds unsent message reservations and closes the campaign permanently. If you need to send again, clone the campaign.
Run status
Each individual run inside a campaign has its own status, separate from the campaign-level status. This is what powers per-run analytics and retry decisions.Internally the engine uses a
claimed state when a worker picks up a run. The API never exposes this — claimed is always translated to running in responses. Treat running as the only “in-flight” state you need to handle.The dashboard walkthrough (high level)
If you are using the dashboard — which is the recommended path — the flow is five steps:- Open your workspace at briq.tz/login and switch to the workspace that owns the campaign.
- Click “New Campaign” and give it a name and description.
- Add audiences by selecting one or more existing contact groups.
- Add content for each channel you intend to use (SMS, voice, WhatsApp). The dashboard enforces the one-row-per-channel rule.
- Schedule a run and click Launch. The dashboard runs validation behind the Launch button — if anything is missing or inconsistent it tells you exactly which field to fix — and then moves the campaign through the same lifecycle states described above.
The API walkthrough (high level)
If you do need to automate, the seven calls below are the canonical sequence. Each subpage walks through the payloads, error cases, and idempotency rules in detail.- Building a campaign — creating the campaign record and attaching audiences, content, and runs.
- Launch control — validating, launching, pausing, resuming, cancelling, and retrying.
- Observability — status polling, analytics, and run-level detail.
Authentication snapshot
Every campaign API call is authenticated the same way:X-API-Key(required) — your developer API key. The key must be inACTIVEstate; revoked or expired keys return401 UNAUTHORIZED.X-App-ID(optional but recommended) — the UUID of the developer app to attribute the call to. Send this when your API key is linked to multiple developer apps so Briq can disambiguate which one is calling.
403 FORBIDDEN.
The developer host is https://karibu.briq.tz. See Developer Apps for how keys and app IDs are issued, and Workspaces for how scoping works.
Response envelope
Every campaign endpoint returns the same JSON envelope:successmirrors HTTP status.trueon 2xx,falseon 4xx and 5xx. Branch onsuccessrather than re-parsing the status code.- On error,
dataisnullanderrorsis an array of{ code, message, field }objects.fieldis populated for validation errors so you can map the failure back to the specific input. - Always log
request_id. It is how Briq support correlates your call to internal traces. Include it in any support ticket.
Error codes at a glance
Best practices
- Use the dashboard for one-off sends. The API is for automation — every dashboard action has an API equivalent, but not every API workflow is worth the engineering cost when a human will only do it once.
- Always validate before launching. The dashboard does this automatically; via the API, call
/validatebefore/launchso failures surface as actionable field errors instead of a launch-timeCONFLICT. - Treat
cancelledas permanent. It refunds unsent message reservations and cannot be undone. Clone the campaign if you need to send again. - Log every
request_id. Support cannot trace a call without it. Persist it alongside whichever business object you correlate to the campaign. - Poll
/statusno faster than every 5–15 seconds, and back off entirely once the campaign reaches a terminal state (completed,failed,cancelled). For real-time progress, prefer Webhooks over polling.