API
Templates
List and send approved WhatsApp message templates
# Templates > List and send approved WhatsApp message templates - Page: https://tbit.app/docs/api/templates - Base URL: `https://rest-api.tbit.app/v1` - Authentication: `X-API-Key` header with your key on every request (the examples read it from the `TBIT_API_KEY` environment variable) ## Overview Templates are pre-approved WhatsApp message formats required for initiating conversations outside the 24-hour messaging window. Only templates with an approved status from Meta can be sent. ## Endpoints | Method | Path | Description | | --- | --- | --- | | `GET` | `/v1/templates` | List approved WhatsApp templates | | `GET` | `/v1/templates/:id` | Get template detail | | `POST` | `/v1/templates/:id/send` | Send template to a contact | | `GET` | `/v1/channels/:channel_id/templates` | Approved templates of one WhatsApp line | | `GET` | `/v1/campaigns/:key/executions` | Delivery status per recipient (sends made with a campaign key) | ## List Templates `GET /v1/templates` ```bash curl "https://rest-api.tbit.app/v1/templates" \ -H "X-API-Key: $TBIT_API_KEY" ``` ## Get Template Detail `GET /v1/templates/tpl_abc123` ```bash curl "https://rest-api.tbit.app/v1/templates/tpl_abc123" \ -H "X-API-Key: $TBIT_API_KEY" ``` ## Templates by WhatsApp line A template is approved in a single WhatsApp Business Account, so an agent with several lines has a template set per line. GET /v1/templates mixes every line (each item carries its channel_id); use this endpoint to list only what a given line can send. The channel id is the one shown in Platform → Channels. `GET /v1/channels/6a7268abec6ecaf999a6c0ba/templates` ```bash curl "https://rest-api.tbit.app/v1/channels/6a7268abec6ecaf999a6c0ba/templates" \ -H "X-API-Key: $TBIT_API_KEY" ``` ## Send Template Send Note The components array follows the WhatsApp Business API format. Include header, body, and button components as needed by your template. `POST /v1/templates/tpl_abc123/send` ```bash curl -X POST "https://rest-api.tbit.app/v1/templates/tpl_abc123/send" \ -H "X-API-Key: $TBIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "to": "573001234567", "components": [ { "type": "body", "parameters": [ { "type": "text", "text": "John" }, { "type": "text", "text": "your order #1234" } ] } ] }' ``` ## Delivery status The send response only means Meta ACCEPTED the message; delivered / read / failed arrive minutes later through Meta webhooks. To read them, pass a `campaign` {key, name} in the send body (the send is then recorded under that key, also visible in Platform → Campaigns) and poll this endpoint. `status` is one of sent, delivered, read, failed; `message_id` is the wamid returned by the send (also in the send response). `GET /v1/campaigns/my-app/executions` ```bash curl "https://rest-api.tbit.app/v1/campaigns/my-app/executions?since=2026-08-27T00:00:00Z&limit=100" \ -H "X-API-Key: $TBIT_API_KEY" ``` Response: ```json { "data": [ { "id": "6a90ea1f...", "to": "573001234567", "template_id": "tpl_abc123", "message_id": "wamid.HBgLNTcz...", "status": "failed", "error_message": "This message was not delivered to maintain healthy ecosystem engagement.", "sent_at": "2026-08-28T02:17:59.494Z", "delivered_at": null, "read_at": null } ] } ``` ## Response Format A template object: ```json { "data": [ { "id": "tpl_abc123", "name": "order_confirmation", "language": "es", "status": "APPROVED", "category": "UTILITY", "channel_id": "6a7268abec6ecaf999a6c0ba", "components": [ { "type": "BODY", "text": "Hola {{1}}, {{2}} ha sido confirmado." } ], "created_at": "2024-08-15T10:00:00Z" } ] } ``` ## Send Response A successful send returns the message ID: ```json { "data": { "message_sent": true, "message_id": "wamid.HBgLNTczMDAxMjM0NTY3FQIAERgSMUY2RUZGM0Y3RTJCRTQ5AA==", "parsed_message": "Hola John, your order #1234 ha sido confirmado." } } ```Templates are pre-approved WhatsApp message formats required for initiating conversations outside the 24-hour messaging window. Only templates with an approved status from Meta can be sent.
| Method | Path | Description |
|---|---|---|
| GET | /v1/templates | List approved WhatsApp templates |
| GET | /v1/templates/:id | Get template detail |
| POST | /v1/templates/:id/send | Send template to a contact |
| GET | /v1/channels/:channel_id/templates | Approved templates of one WhatsApp line |
| GET | /v1/campaigns/:key/executions | Delivery status per recipient (sends made with a campaign key) |
/v1/templatescurl "https://rest-api.tbit.app/v1/templates" \
-H "X-API-Key: $TBIT_API_KEY"const response = await fetch('https://rest-api.tbit.app/v1/templates', {
headers: {
'X-API-Key': process.env.TBIT_API_KEY,
},
});
const data = await response.json();import axios from 'axios';
const { data } = await axios.get(
'https://rest-api.tbit.app/v1/templates',
{
headers: {
'X-API-Key': process.env.TBIT_API_KEY,
},
},
);import os
import requests
response = requests.get(
'https://rest-api.tbit.app/v1/templates',
headers={'X-API-Key': os.environ['TBIT_API_KEY']},
)
data = response.json()<?php
$ch = curl_init('https://rest-api.tbit.app/v1/templates');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'X-API-Key: ' . getenv('TBIT_API_KEY'),
],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);/v1/templates/tpl_abc123curl "https://rest-api.tbit.app/v1/templates/tpl_abc123" \
-H "X-API-Key: $TBIT_API_KEY"const response = await fetch('https://rest-api.tbit.app/v1/templates/tpl_abc123', {
headers: {
'X-API-Key': process.env.TBIT_API_KEY,
},
});
const data = await response.json();import axios from 'axios';
const { data } = await axios.get(
'https://rest-api.tbit.app/v1/templates/tpl_abc123',
{
headers: {
'X-API-Key': process.env.TBIT_API_KEY,
},
},
);import os
import requests
response = requests.get(
'https://rest-api.tbit.app/v1/templates/tpl_abc123',
headers={'X-API-Key': os.environ['TBIT_API_KEY']},
)
data = response.json()<?php
$ch = curl_init('https://rest-api.tbit.app/v1/templates/tpl_abc123');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'X-API-Key: ' . getenv('TBIT_API_KEY'),
],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);A template is approved in a single WhatsApp Business Account, so an agent with several lines has a template set per line. GET /v1/templates mixes every line (each item carries its channel_id); use this endpoint to list only what a given line can send. The channel id is the one shown in Platform → Channels.
/v1/channels/6a7268abec6ecaf999a6c0ba/templatescurl "https://rest-api.tbit.app/v1/channels/6a7268abec6ecaf999a6c0ba/templates" \
-H "X-API-Key: $TBIT_API_KEY"const response = await fetch('https://rest-api.tbit.app/v1/channels/6a7268abec6ecaf999a6c0ba/templates', {
headers: {
'X-API-Key': process.env.TBIT_API_KEY,
},
});
const data = await response.json();import axios from 'axios';
const { data } = await axios.get(
'https://rest-api.tbit.app/v1/channels/6a7268abec6ecaf999a6c0ba/templates',
{
headers: {
'X-API-Key': process.env.TBIT_API_KEY,
},
},
);import os
import requests
response = requests.get(
'https://rest-api.tbit.app/v1/channels/6a7268abec6ecaf999a6c0ba/templates',
headers={'X-API-Key': os.environ['TBIT_API_KEY']},
)
data = response.json()<?php
$ch = curl_init('https://rest-api.tbit.app/v1/channels/6a7268abec6ecaf999a6c0ba/templates');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'X-API-Key: ' . getenv('TBIT_API_KEY'),
],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);Send Note
The components array follows the WhatsApp Business API format. Include header, body, and button components as needed by your template.
/v1/templates/tpl_abc123/sendcurl -X POST "https://rest-api.tbit.app/v1/templates/tpl_abc123/send" \
-H "X-API-Key: $TBIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "573001234567",
"components": [
{
"type": "body",
"parameters": [
{
"type": "text",
"text": "John"
},
{
"type": "text",
"text": "your order #1234"
}
]
}
]
}'const response = await fetch('https://rest-api.tbit.app/v1/templates/tpl_abc123/send', {
method: 'POST',
headers: {
'X-API-Key': process.env.TBIT_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
to: '573001234567',
components: [
{
type: 'body',
parameters: [
{
type: 'text',
text: 'John',
},
{
type: 'text',
text: 'your order #1234',
},
],
},
],
}),
});
const data = await response.json();import axios from 'axios';
const { data } = await axios.post(
'https://rest-api.tbit.app/v1/templates/tpl_abc123/send',
{
to: '573001234567',
components: [
{
type: 'body',
parameters: [
{
type: 'text',
text: 'John',
},
{
type: 'text',
text: 'your order #1234',
},
],
},
],
},
{
headers: {
'X-API-Key': process.env.TBIT_API_KEY,
},
},
);import os
import requests
response = requests.post(
'https://rest-api.tbit.app/v1/templates/tpl_abc123/send',
headers={'X-API-Key': os.environ['TBIT_API_KEY']},
json={
'to': '573001234567',
'components': [
{
'type': 'body',
'parameters': [
{
'type': 'text',
'text': 'John',
},
{
'type': 'text',
'text': 'your order #1234',
},
],
},
],
},
)
data = response.json()<?php
$ch = curl_init('https://rest-api.tbit.app/v1/templates/tpl_abc123/send');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'X-API-Key: ' . getenv('TBIT_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'to' => '573001234567',
'components' => [
[
'type' => 'body',
'parameters' => [
[
'type' => 'text',
'text' => 'John',
],
[
'type' => 'text',
'text' => 'your order #1234',
],
],
],
],
]),
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);The send response only means Meta ACCEPTED the message; delivered / read / failed arrive minutes later through Meta webhooks. To read them, pass a `campaign` {key, name} in the send body (the send is then recorded under that key, also visible in Platform → Campaigns) and poll this endpoint. `status` is one of sent, delivered, read, failed; `message_id` is the wamid returned by the send (also in the send response).
/v1/campaigns/my-app/executionscurl "https://rest-api.tbit.app/v1/campaigns/my-app/executions?since=2026-08-27T00:00:00Z&limit=100" \
-H "X-API-Key: $TBIT_API_KEY"const response = await fetch('https://rest-api.tbit.app/v1/campaigns/my-app/executions?since=2026-08-27T00:00:00Z&limit=100', {
headers: {
'X-API-Key': process.env.TBIT_API_KEY,
},
});
const data = await response.json();import axios from 'axios';
const { data } = await axios.get(
'https://rest-api.tbit.app/v1/campaigns/my-app/executions?since=2026-08-27T00:00:00Z&limit=100',
{
headers: {
'X-API-Key': process.env.TBIT_API_KEY,
},
},
);import os
import requests
response = requests.get(
'https://rest-api.tbit.app/v1/campaigns/my-app/executions?since=2026-08-27T00:00:00Z&limit=100',
headers={'X-API-Key': os.environ['TBIT_API_KEY']},
)
data = response.json()<?php
$ch = curl_init('https://rest-api.tbit.app/v1/campaigns/my-app/executions?since=2026-08-27T00:00:00Z&limit=100');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'X-API-Key: ' . getenv('TBIT_API_KEY'),
],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);{
"data": [
{
"id": "6a90ea1f...",
"to": "573001234567",
"template_id": "tpl_abc123",
"message_id": "wamid.HBgLNTcz...",
"status": "failed",
"error_message": "This message was not delivered to maintain healthy ecosystem engagement.",
"sent_at": "2026-08-28T02:17:59.494Z",
"delivered_at": null,
"read_at": null
}
]
}A template object:
{
"data": [
{
"id": "tpl_abc123",
"name": "order_confirmation",
"language": "es",
"status": "APPROVED",
"category": "UTILITY",
"channel_id": "6a7268abec6ecaf999a6c0ba",
"components": [
{
"type": "BODY",
"text": "Hola {{1}}, {{2}} ha sido confirmado."
}
],
"created_at": "2024-08-15T10:00:00Z"
}
]
}A successful send returns the message ID:
{
"data": {
"message_sent": true,
"message_id": "wamid.HBgLNTczMDAxMjM0NTY3FQIAERgSMUY2RUZGM0Y3RTJCRTQ5AA==",
"parsed_message": "Hola John, your order #1234 ha sido confirmado."
}
}