Outbound templates
A template is a saved message body you write once and reuse in campaigns, one-off sends, and drip sequences. Instead of re-typing the same confirmation or promo for every send, you author it in Outbound → Templates, let it clear any channel approval it needs, and pick it from the message step of the campaign-create wizard. Templates live side by side with campaigns under the Outbound hub (an entry point under Messages → Templates reaches the same library — same rows, either door).Voice is not a template channel. The template library covers text channels: SMS, WhatsApp, RCS, email, Viber, Telegram, LINE, Messenger, Instagram, push, fax, and Apple Messages for Business. A voice call flow (Jambonz/speech IVR) is authored in Agents/Studio instead. (Template authoring itself is feature-free and does not interact with outbound routing invariants.)
What a template is
A template record carries a channel, a name, a language, and the message content — the body text (or, for rich channels, a body plus optional media). Two placeholder systems personalize that content at send time:- Variables — merge tokens written in the body as double-curly placeholders, for example
{{first_name}}or{{order_id}}. At send time the campaign (or the single-message composer) substitutes per-recipient data from the contact record or the send payload. - Conditional blocks — depending on the channel, richer structures such as WhatsApp’s header/footer/buttons or RCS rich cards are built in a dedicated editor, but the body itself stays a single text block (plus media for MMS-style messages).
Channel-specific rules
What you can author, and what happens after you save it, depends on the channel:- WhatsApp — templates must clear Meta’s model approval. Until the
approvedstatus is in, the template can’t be used from a campaign or a test send. Author the copy, pick a category (marketing, utility, or authentication — a WhatsApp-only taxonomy), submit it, and wait for Meta’s review. A rejection reason (if any) is visible in the template row. - RCS — rich cards and carousels are reviewed per carrier; editing a template re-enters the
pendingstate and old sends keep using the prior approved version. - SMS / email / Viber / Telegram / LINE / Messenger / Instagram / push / fax / Apple Messages — no carrier approval queue; a saved template becomes
activeimmediately and is sendable. Email bodies fit MJML-style HTML in thecontentbody if you paste rendered HTML, but plain text works too (the composer handles raw bodies). - SMS unresolved variables — SMS has no server-side merge on the composer send path: if a template body still contains
{{name}}tokens when you open the composer, the UI flags the unresolved variables so you replace them before sending, instead of shipping literal{{...}}to the customer.
Create a template
- Open Outbound → Templates.
- Click Create template and pick the channel.
- For WhatsApp: pick the WABA (the picker appears only when your tenant has more than one connected) and choose a category.
- Fill the body with your copy; insert
{{variable}}placeholders where personalization is needed. - Save. Approval-required channels (WhatsApp, RCS) move to
pending; platform-only channels land directly atactive.
owner, admin, and developer roles.
Worked examples over the API
Every step below is a copy-pasteable call againsthttps://api.orbit.devotel.io/api/v1. Sign with a test key (dv_test_sk_…) to run in sandbox, or a live key (dv_live_sk_…) for production. Template mutations require the templates:write scope (plus an owner/admin/developer dashboard role); reads accept templates:read or templates:write. Keep it simple — a full key listing every scope works for all of these.
List templates
GET /api/v1/messages/templates returns a cursor-paginated page, newest first, with optional channel, status, search, waba_id, and purpose filters:
Create a template
POST /api/v1/messages/templates with a channel, name, language, and the body. Placeholders go in as double-curly tokens you fill at send time:
active and sendable immediately. Approval-required channels (whatsapp, rcs, kakao, zalo) come back draft — move them to pending with a PATCH .../templates/:id of { "status": "pending" }, or hand them to the carrier-submit dialog in the hub. For WhatsApp you can also pass a category (marketing | utility | authentication) and, for the rich component shape (header/footer/buttons), a components array instead of a plain body.
Send with the template
Reference the template by name at send time and pass the per-recipient merge values intemplate_params. The example sends one SMS and substitutes {{first_name}}:
body (the composer does this automatically) so the send is still well-formed if the lookup misses a template. For WhatsApp the shape is channel-specific: pass template: { "name": "order_shipped", "language": { "code": "en" } } plus the same template_params map on POST /messages/whatsapp.
Track the approval status
Channel lifecycle states:draft → pending → approved / rejected for WhatsApp and RCS; active right away for platform-only channels; paused and archived are operator-set at any stage. Editing a WhatsApp or RCS template re-submits it, so a previously approved row drops back to pending while the old approved version keeps serving sends.
Patch an approved WhatsApp body and the response shows the re-review state:
GET /api/v1/messages/templates/:id for approval state, or use the hub’s Sync from Meta button to pull WhatsApp status for every row at once.
Group channels with Content Templates
The second tab, Content Templates, is the cross-channel layer (Twilio Content API parity): one logical content id grouping per-channel variants with a fallback order. Author once, and the same copy serves WhatsApp with an SMS fallback under one definition:Test send in sandbox
Anything signed with adv_test_sk_… key runs in sandbox — simulated delivery, no credits burned, no real message dispatched. That makes the send above a test send as-is. To test-deliver a template to yourself, send it to your own number with the test key and confirm the simulated receipt marked "test_mode": true in meta. On WhatsApp, only approved templates test-send (the hub enforces the same rule); on SMS the composer flags unresolved {{...}} tokens so you replace them before the send goes out — the same check applies to API sends.
Governance: scopes and roles
Writes require thetemplates:write scope; a key holding only messages:write gets a 403:
owner, admin, and developer roles, so viewers and members can pick templates into campaigns without being able to mutate the library.
Manage versions and lifecycle
Opening the library shows a row per template with status, category (WhatsApp only), language, and a two-line body preview.- Edit — patch the body/name/category/language. Editing a WhatsApp or RCS template re-submits for review; an old approved version stays usable while the new one is pending.
- Clone — duplicates the row with a
_copyname as a new variant. This is the canonical A/B mechanism, because per-template metrics live on the template id — two clones are two measurable variants. - Localize — the Languages action opens a per-locale tracker listing every language variant and its approval status, and can auto-translate into more locales.
- Archive — soft-delete; the row leaves compose pickers and test-send lists, and stays restorable from the archive view.
- Delete — permanent, after a confirmation dialog.
- Test send — fire one to yourself (WhatsApp only after approval; SMS opens the in-place composer; other channels deep-link to the channel’s compose dialog with the template pre-selected, and the recipient is marked as a test contact so one-off test sessions do not pollute your contacts list).
Use a template in a campaign
- Open Outbound → Campaigns → Create.
- In the message step, pick Use a template and select the template from your library. The wizard pre-fills the body for you to review and adjust (for WhatsApp, only
approvedtemplates show; for SMS/email/etc., any active template shows). - Drip sequences treat the campaign’s
message_templateas the step-0 welcome message; every step can carry its own template or inline body. - A/B testing across template versions: create two clones (as above), then run both variants against the same audience — each variant accumulates its own metrics.
Read template analytics
After a campaign sends, Outbound → Templates → row Analytics action opens the cross-campaign rollup: sent → delivered → opened → clicked, consolidated across every campaign that reused that template. See Template analytics for the rollup’s exact semantics — the terminal-as-denominator convention, thedegraded flag on transient fallbacks, and the per-channel breakdown.
Governance: naming and edit roles
Keep the library trustworthy with two conventions:- Naming: adopt a
<purpose>_<variant>_<locale>convention (e.g.order_confirm_v2_en,promo_blast_a_es) so the body preview plus the name together identify what a row is without opening it. - Who can edit: restrict template create/edit/delete/archive to the
owner/admin/developerroles (enforced by the hub’s role guard). A larger team can view and pick templates in campaigns without being able to mutate the library.