Goals, approvals, and direct send
The Outbound section of the dashboard exposes three controls that decide how sends leave your tenant, not just what you send:- Goals — a conversion you care about (a reply, a purchase, a booking) defined once and attributed back to the messages, campaigns, and agents that touched the contact before they converted.
- Approvals — a supervisor gate in front of the launch button, so a campaign one operator drafts cannot go out until someone with approval rights reviews it.
- Direct send — the path for one-off sends that should never have been a campaign: one message to one contact, or a one-time CSV batch, with the same suppression and consent enforcement as a campaign.
When to use which
Goals: define what counts as a conversion
A goal is a named conversion definition: when event X happens for a contact, count it as a conversion, and attribute it to the messages and campaigns that touched the contact first. Create goals in the dashboard under Outbound → Goals, or over the API:
Goal events join the same event stream as everything else — the CDP event model is the umbrella that makes a purchase event, a message delivery, and a tag change comparable enough to attribute. If you want conversions to arrive from your own backend, post them to the CDP ingest endpoint with a matching
event_type; the goal does the rest.
A campaign also carries a lighter-weight goal concept of its own: drips accept exit_goals (pull a contact out of the sequence when they convert) and journeys have a per-campaign conversion-goal definition with its own analytics rollup. Use a tenant-level goal when you want cross-campaign attribution; use the campaign-level goal when the question is “did this journey work.”
Approvals: put a gate in front of launch
The approval gate inserts a review step between “an operator clicks send” and “messages leave the platform.” It is aimed at teams where one person drafts campaigns and a different person is accountable for what goes out — the dual-control pattern regulated teams run on email platforms. How the gate engages. Launching a campaign (POST /campaigns/:id/send) checks two org-level settings, readable via GET /campaigns/approvals/settings:
require_approval_default— whentrue, every launch by a non-admin member is gated.min_recipients_for_approval— an optional audience threshold; only launches at or above this resolved audience size are gated.
pending_approval, the launcher gets a 202 back with an approval id, and the request lands in the supervisors’ queue. An owner or admin reviews it — Outbound → Approvals in the dashboard, or GET /campaigns/approvals/pending over the API — then either:
- Approves (
POST /campaigns/:id/approve) — the campaign re-enters the normal launch path and sends exactly as if the supervisor had launched it themselves. - Rejects (
POST /campaigns/:id/reject, optionalreason) — the campaign returns todraftfor edits. Nothing was sent.
Direct send: one-off messages without a campaign
Campaigns are the right shape for audiences — lists, segments, schedules, analytics. Direct send is the right shape when none of that applies: a transactional one-off, a follow-up to a single conversation, or a one-time CSV run that will not repeat. Three entry points, all under Outbound → Direct send:- One contact. Pick a contact in the picker; Orbit shows every reachable channel for them (SMS, WhatsApp, email) and the exact identifier it will address. You confirm the channel and land in that channel’s composer with the recipient prefilled.
- A CSV list. Upload a CSV of phone numbers or emails, map a template with per-row variables, and send the batch. It behaves like a batch send: parse, render, idempotent submit — without creating a campaign object.
- Straight to a channel composer. If you already know the channel, jump directly to the SMS, WhatsApp, or email composer and address it yourself.
- Suppression lists and channel-level opt-outs are checked — a suppressed or opted-out recipient is held back, same as in a campaign.
- Frequency caps still count a direct send toward the recipient’s budget.
- Quiet hours and send gating still defer or block sends that fall inside a recipient-local quiet window (see the send gating and quiet hours concept).
Worked example: gated launch with a goal attached
A complete pass through all three controls: define a goal, gate the launch behind a supervisor, send, and read attainment. 1. Define the goal (once per tenant) — count everybooking.completed event as a conversion worth whatever the event carries, attributing over a 14-day lookback:
require_approval_default on and the audience above the threshold, the launch parks instead of sending:
pending_approval — live but parked, as the campaign lifecycle status table puts it.
3. A supervisor reviews and approves. They list the queue, check the audience snapshot, body, and schedule, then approve:
sending, then running, then completed as the audience drains.
4. Conversions land against the goal. As recipients book demos, your backend posts booking.completed events to CDP ingest with the contact id attached. Read attainment back on the goal — total conversions, attributed revenue, and which campaigns carried the credited touches:
Related pages
- Campaign lifecycle — the status machine approvals park a campaign in, and what terminal outcomes feed analytics.
- Send a campaign end-to-end — the full launch workflow these controls attach to.
- CDP event model — the event stream goal attribution reads.
- Consent and suppression model — the enforcement direct send does not bypass.