Endpoint
POST https://app.octopods.io/api/v1/vbm/templates/:template_id/messages
The template’s ID is part of the URL path — not a body field. Find it on the template’s detail page in Octopods or via the list templates endpoint.
Only templates in Accepted state are eligible for sending through this endpoint.
Authentication
Include your Channel API Key in the request header:
X-Octopods-Auth: YOUR_CHANNEL_API_KEY
The key must belong to the Viber channel connection the template was registered against.
See API Key Authentication for how to find this key.
Required parameters
Send the request body as JSON with Content-Type: application/json.
destination_phone— the recipient’s phone number in E.164 format (for example,+15551234567). Numbers that fail validation are rejected with error code5(PHONE_INVALID).message_variables— substitution values for any{{N}}placeholders the template contains. Structure depends on which sections of the template have variables.
If the template has no variables, message_variables can be omitted.
Optional parameters
header_image_url— required only if the template’s header is an image header. Must be a publicly reachable URL returning a supported image type. Missing it when the header requires it returns error code1(ARGUMENT_MISSING); an invalid or unreachable URL returns error code8(INVALID_HEADER).open_intercom_conversation—trueto open a new conversation in Intercom or HubSpot alongside the send,false(default) to send without opening a conversation. Acceptstrue,false,1,0,yes,no,on,off.intercom_teammate_id— the ID of the Intercom teammate who should appear as the sender. Defaults to the workspace’s configured default sender.
Variable structure
Viber templates can have variables in multiple sections. The shape of message_variables depends on where the template’s variables live.
Body-only variables — array shape
When the template has variables only in the body, you may pass message_variables as a flat array whose order matches {{1}}, {{2}}, {{3}}, and so on:
{
"destination_phone": "+15551234567",
"message_variables": ["Jane", "ORD-9876", "April 28"]
}
Any other case — object shape
When the template has variables in the header, footer, or a mix of sections, message_variables must be an object with one array per section:
{
"destination_phone": "+15551234567",
"message_variables": {
"header": ["Jane"],
"body": ["ORD-9876", "April 28"],
"footer": []
}
}
Every array must contain exactly the number of values the template expects for that section. Mismatched counts return error code 4 (VARIABLES_SIZE) with the expected total count in the error message.
Example request
POST https://app.octopods.io/api/v1/vbm/templates/60214/messages
X-Octopods-Auth: YOUR_CHANNEL_API_KEY
Content-Type: application/json{
"destination_phone": "+15551234567",
"message_variables": {
"header": ["Jane"],
"body": ["ORD-9876", "April 28"],
"footer": []
},
"header_image_url": "https://example.com/order-banner.png",
"open_intercom_conversation": true
}
Success response
On success the API returns HTTP 201 Created with no body. The send is enqueued for delivery to Viber.
To follow the send’s delivery, open the corresponding conversation in your Intercom or HubSpot inbox.
Error response
On failure the API returns HTTP 400 Bad Request with a JSON body that includes the error code and a human-readable message:
{
"request_id": "e23080fd-8b63-460e-83bd-cf5d2c1497b6",
"error_code": 3,
"error": "Message Template does not exist."
}
Error codes
Code | Name | When it happens |
1 |
| A required parameter ( |
2 |
|
|
3 |
| No accepted template exists at |
4 |
| The count of supplied variables does not match the template’s placeholders. |
5 |
|
|
6 |
| The API key has been rotated or revoked. Fetch the current key from Octopods. |
7 |
| Viber rejected the send. The |
8 |
|
|
A full catalog of error codes across all endpoints is in the API Error Reference.
Fallback to SMS
Viber templates registered with an SMS fallback automatically deliver as SMS when the recipient is not a Viber user or is unreachable. Fallback is configured on the template itself, not per send — your backend does not need to detect the failure or retry.
What’s next
