Templates let you define a message body once, with {{.variable}} placeholders, and render it server-side on every send. Benefits: shorter requests, consistent copy, and a single place to edit when the copy changes.
Create a template
curl -X POST https://api.robase.dev/v1/sms-templates \
-H "Authorization: Bearer rb_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Ride arriving",
"body": "Hi {{.driver_name}}, your ride arrives in {{.eta}} min."
}'
Response:
{
"id": "tpl_01H8XKQJ3Z...",
"name": "Ride arriving",
"slug": "ride-arriving",
"body": "Hi {{.driver_name}}, your ride arrives in {{.eta}} min.",
"variables": ["driver_name", "eta"]
}
The slug is derived from name and doubles as a stable identifier — use it (instead of the UUID) in sends so renaming a template doesn’t break callers.
Send using the template
await pm.sms.send({
to: '+2348012345678',
from: 'SHUTTLERS',
template: 'ride-arriving', // slug or UUID both work
variables: { driver_name: 'Chidi', eta: 3 },
});
The server renders the body, re-computes segments and cost, and proceeds normally.
Variable syntax
We use Go’s text/template engine:
| Syntax | Renders |
|---|
{{.name}} | The value of variables.name |
{{.user.email}} | Nested lookup — requires a map |
{{printf "%d" .count}} | Formatters via pipe |
{{if .is_first}}Welcome!{{end}} | Conditionals |
Missing variables render as <no value> — not an error. This is deliberate so a typo doesn’t block a send; but test your templates with the render endpoint (below) to catch them in dev.
Preview before sending
POST /v1/sms-templates/:id/render renders the template with variables and returns the body + segment count without sending anything. Great for previews in your admin UI:
const preview = await pm.smsTemplates.render('tpl_01H8...', {
driver_name: 'Chidi',
eta: 3,
});
// → { body: "Hi Chidi, your ride arrives in 3 min.", encoding: "GSM7", segments: 1 }
List, update, delete
await pm.smsTemplates.list();
await pm.smsTemplates.get('tpl_01H8...');
await pm.smsTemplates.update('tpl_01H8...', { body: 'Updated: ...' });
await pm.smsTemplates.remove('tpl_01H8...');
Keeping segment count predictable
Variables change the final length. A good pattern: cap user-supplied variables to a max length before passing them, so your template never balloons past one segment:
const eta = Math.min(Number(rawEta), 99); // cap at 99 → 2 chars max
const driver = String(driverName).slice(0, 20);
await pm.sms.send({
to, from, template: 'ride-arriving',
variables: { eta, driver_name: driver },
});
The render endpoint is useful here too — check segments before batch-sending to estimate cost.