Messaging
Message types
Every content type you can send, with its fields, an example request and the channels that support it.
How content is structured#
A message has a type and a content object under the key named by that type. To send a location, set "type": "location" and provide a location object. Exactly one content object is allowed per message.
The message object you get back stores the same content under content, again keyed by type: "content": { "location": { ... } }.
Channel support#
Which types a channel accepts is listed in its capabilities. Sending a type the channel does not support fails with 400 unsupported_message_type and nothing is charged.
| Type | Telegram | SMS | SMS OTP | Messenger | TikTok | ||
|---|---|---|---|---|---|---|---|
text | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
attachments | Yes | Yes | Yes | – | Yes | Yes | Yes |
template | Yes | – | – | – | – | – | – |
button | Yes | Yes | – | – | Yes | Yes | Yes |
list | Yes | – | – | – | – | – | – |
cta_url | Yes | – | – | – | – | – | – |
location | Yes | Yes | – | – | – | – | – |
contacts | Yes | Yes | – | – | – | – | – |
poll | – | Yes | – | – | – | – | – |
The nine types on this page are validated by OmniMessage before the message is accepted. Some channels accept further types that are passed through without validation: see Channel-specific types.
text#
Plain text of 1 to 4096 characters. The only type every channel supports, and the only one for SMS OTP.
Channels: WhatsApp Business, Telegram, SMS, SMS OTP, Messenger, Instagram, TikTok.
| Field | Type | Required | Description |
|---|---|---|---|
body | string | Required | Message text, 1 to 4096 characters. |
preview_url | boolean | Optional | Ask the channel to render a preview for the first URL in body, where the channel supports it. |
curl https://api.omnimessage.co/v1/messages \
-H "Authorization: Bearer om_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"channel": "ch_7Hq2mN5vB8cX1zL0pK3j",
"to": "+971501234567",
"type": "text",
"text": {
"body": "Your code is 482910"
},
"reference": "order-1042",
"metadata": {
"user_id": "u_17"
}
}'Individual channels may enforce a shorter limit or split long text. An SMS longer than one segment is split by the carrier, for example.
attachments#
One media file: an image, video, document, audio file, voice note or sticker. attachments is an array that must contain exactly one item; to send several files, send several messages.
Channels: WhatsApp Business, Telegram, SMS, Messenger, Instagram, TikTok.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Required | Kind of media. One of image, video, document, audio, voice, sticker. |
url | string | Required | Publicly reachable HTTPS URL of the file. It is fetched at send time. |
caption | string | Optional | Text shown with the media, where the channel supports captions. |
filename | string | Optional | File name shown to the recipient for documents. |
curl https://api.omnimessage.co/v1/messages \
-H "Authorization: Bearer om_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"channel": "ch_7Hq2mN5vB8cX1zL0pK3j",
"to": "+971501234567",
"type": "attachments",
"attachments": [
{
"type": "document",
"url": "https://example.com/invoices/1042.pdf",
"filename": "invoice-1042.pdf",
"caption": "Invoice for order #1042"
}
]
}'The file is fetched from url when the message is sent, so the URL must be public HTTPS and stay valid until then. Accepted formats and size limits are those of the channel provider. A file the provider rejects produces a failed message with provider_error.
On SMS, an attachment is sent as MMS and depends on the sending number and the destination supporting it.
template#
A WhatsApp message template that was approved in WhatsApp Manager. Templates are the only way to message a WhatsApp user outside the 24-hour customer service window.
Channels: WhatsApp Business.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Required | Template name as approved in WhatsApp Manager. |
language | object | Required | Template language. |
language.code | string | Required | Language or locale code of the approved translation, for example en or en_US. |
components | array of objects | Optional | Values for the template variables, in the WhatsApp Cloud API component format. Omit for templates without variables. |
components[].type | string | Required | Which part of the template the parameters fill. One of header, body, button. |
components[].sub_type | string | Optional | Button kind, for button components (for example url or quick_reply). |
components[].index | string | Optional | Zero-based button position, for button components. |
components[].parameters | array of objects | Optional | Parameter values in template order. |
curl https://api.omnimessage.co/v1/messages \
-H "Authorization: Bearer om_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"channel": "ch_7Hq2mN5vB8cX1zL0pK3j",
"to": "+971501234567",
"type": "template",
"template": {
"name": "order_shipped",
"language": {
"code": "en"
},
"components": [
{
"type": "body",
"parameters": [
{
"type": "text",
"text": "Layla"
},
{
"type": "text",
"text": "#1042"
}
]
}
]
}
}'components follows the WhatsApp Cloud API format and is forwarded as is. List the templates of a channel, with their languages and variables, through GET /v1/channels/{id}/templates. The WhatsApp guide covers approval and the messaging window.
button#
Text with one to three quick-reply buttons. When the recipient taps a button you receive an inbound message that carries the id you assigned.
Channels: WhatsApp Business, Telegram, Messenger, Instagram, TikTok.
| Field | Type | Required | Description |
|---|---|---|---|
header | object | Optional | Optional header shown above the body. |
header.type | string | Required | Header kind. One of text. |
header.text | string | Required | Header text, up to 60 characters. |
body | object | Required | Main message text. |
body.text | string | Required | Body text. |
footer | object | Optional | Optional small print below the body. |
footer.text | string | Required | Footer text, up to 60 characters. |
action | object | Required | The buttons. |
action.buttons | array of objects | Required | One to three reply buttons. |
action.buttons[].reply | object | Required | A reply button. |
action.buttons[].reply.id | string | Required | Your identifier for the button. Returned when the recipient taps it. |
action.buttons[].reply.title | string | Required | Button label, up to 20 characters. |
curl https://api.omnimessage.co/v1/messages \
-H "Authorization: Bearer om_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"channel": "ch_7Hq2mN5vB8cX1zL0pK3j",
"to": "+971501234567",
"type": "button",
"button": {
"body": {
"text": "Your delivery is scheduled for tomorrow, 10:00-12:00. Does that work?"
},
"footer": {
"text": "Order #1042"
},
"action": {
"buttons": [
{
"reply": {
"id": "confirm",
"title": "Confirm"
}
},
{
"reply": {
"id": "reschedule",
"title": "Reschedule"
}
}
]
}
}
}'Button titles are limited to 20 characters. Keep id values stable: they are what your code branches on when the reply arrives.
list#
A WhatsApp list picker: a single button that opens a menu of rows grouped into sections. Use it when there are more than three choices.
Channels: WhatsApp Business.
| Field | Type | Required | Description |
|---|---|---|---|
header | object | Optional | Optional header shown above the body. |
header.type | string | Required | Header kind. One of text. |
header.text | string | Required | Header text, up to 60 characters. |
body | object | Required | Main message text. |
body.text | string | Required | Body text. |
footer | object | Optional | Optional small print below the body. |
footer.text | string | Required | Footer text, up to 60 characters. |
action | object | Required | The menu. |
action.button | string | Required | Label of the button that opens the list, up to 20 characters. |
action.sections | array of objects | Required | Groups of rows. |
action.sections[].title | string | Required | Section heading, up to 24 characters. |
action.sections[].rows | array of objects | Required | Selectable rows. |
action.sections[].rows[].id | string | Required | Your identifier for the row. Returned when the recipient selects it. |
action.sections[].rows[].title | string | Required | Row label, up to 24 characters. |
action.sections[].rows[].description | string | Optional | Optional second line, up to 72 characters. |
curl https://api.omnimessage.co/v1/messages \
-H "Authorization: Bearer om_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"channel": "ch_7Hq2mN5vB8cX1zL0pK3j",
"to": "+971501234567",
"type": "list",
"list": {
"body": {
"text": "Pick a delivery window for order #1042."
},
"action": {
"button": "Choose a slot",
"sections": [
{
"title": "Tomorrow",
"rows": [
{
"id": "slot_am",
"title": "10:00-12:00",
"description": "Morning"
},
{
"id": "slot_pm",
"title": "16:00-18:00",
"description": "Afternoon"
}
]
}
]
}
}
}'The label of the opening button is limited to 20 characters. The selected row arrives as an inbound message carrying its id.
cta_url#
A WhatsApp message with a single call-to-action button that opens a URL in the browser.
Channels: WhatsApp Business.
| Field | Type | Required | Description |
|---|---|---|---|
header | object | Optional | Optional header shown above the body. |
header.type | string | Required | Header kind. One of text. |
header.text | string | Required | Header text, up to 60 characters. |
body | object | Required | Main message text. |
body.text | string | Required | Body text. |
footer | object | Optional | Optional small print below the body. |
footer.text | string | Required | Footer text, up to 60 characters. |
action | object | Required | The link button. |
action.parameters | object | Required | |
action.parameters.display_text | string | Required | Button label, up to 20 characters. |
action.parameters.url | string | Required | URL opened when the button is tapped. |
curl https://api.omnimessage.co/v1/messages \
-H "Authorization: Bearer om_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"channel": "ch_7Hq2mN5vB8cX1zL0pK3j",
"to": "+971501234567",
"type": "cta_url",
"cta_url": {
"body": {
"text": "Your order is on its way."
},
"action": {
"parameters": {
"display_text": "Track order",
"url": "https://example.com/track/1042"
}
}
}
}'location#
A map pin with a name and an address.
Channels: WhatsApp Business, Telegram.
| Field | Type | Required | Description |
|---|---|---|---|
latitude | number | Required | Latitude in decimal degrees. |
longitude | number | Required | Longitude in decimal degrees. |
name | string | Required | Name of the place. |
address | string | Required | Address of the place. |
curl https://api.omnimessage.co/v1/messages \
-H "Authorization: Bearer om_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"channel": "ch_7Hq2mN5vB8cX1zL0pK3j",
"to": "+971501234567",
"type": "location",
"location": {
"latitude": 25.197197,
"longitude": 55.274376,
"name": "Pickup point",
"address": "Sheikh Mohammed bin Rashid Blvd, Dubai"
}
}'contacts#
One or more contact cards. The array uses the contact format of the provider and is forwarded without further validation; the fields below are the commonly used ones.
Channels: WhatsApp Business, Telegram.
| Field | Type | Required | Description |
|---|---|---|---|
name | object | Optional | Contact name. |
name.formatted_name | string | Required | Full display name. |
name.first_name | string | Optional | Given name. |
name.last_name | string | Optional | Family name. |
phones | array of objects | Optional | Phone numbers. |
phones[].phone | string | Optional | Phone number in E.164 format. |
phones[].type | string | Optional | Label such as CELL, WORK or HOME. |
curl https://api.omnimessage.co/v1/messages \
-H "Authorization: Bearer om_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"channel": "ch_7Hq2mN5vB8cX1zL0pK3j",
"to": "+971501234567",
"type": "contacts",
"contacts": [
{
"name": {
"formatted_name": "Acme Support",
"first_name": "Acme",
"last_name": "Support"
},
"phones": [
{
"phone": "+971800123456",
"type": "WORK"
}
]
}
]
}'poll#
A Telegram poll with a question and a list of answer options.
Channels: Telegram.
| Field | Type | Required | Description |
|---|---|---|---|
question | string | Required | Poll question, up to 300 characters. |
options | array of strings | Required | Two to ten answer options of up to 100 characters each. |
curl https://api.omnimessage.co/v1/messages \
-H "Authorization: Bearer om_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"channel": "ch_2pT5gB8nM1kL4jH7fD0s",
"to": "482910375",
"type": "poll",
"poll": {
"question": "Which delivery window suits you?",
"options": [
"Morning",
"Afternoon",
"Evening"
]
}
}'Channel-specific types#
Besides the common types, a channel may list further types in its capabilities. For these, OmniMessage checks only that the content object is present under the key named by type, then forwards it to the channel unchanged, in the format of the channel provider.
| Channel | Additional types |
|---|---|
| WhatsApp Business | flow, product, product_list, catalog, carousel, location_request |
| Telegram | None |
| SMS | None |
| SMS OTP | None |
| Messenger | carousel, product_list, receipt |
carousel, product_list | |
| TikTok | None |