Messages
Send, list, get, and cancel channel-native WhatsApp and Instagram messages.
Send a message
Request body
| Field | Type | Notes |
|---|---|---|
| No fields. | ||
Response
| Field | Type | Notes |
|---|---|---|
idrequired | string | |
objectrequired | "message" | |
statusrequired | string | |
channelrequired | "whatsapp" | "instagram" | "whatsapp_channel" | |
environmentrequired | "sandbox" | "production" | |
template_idrequired | string | null | |
template_version_idrequired | string | null | |
template_versionrequired | integer | null | |
created_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
trace_idrequired | string |
Template sends use message.type = "template". Set message.template.language to a string WhatsApp language code such as pt_BR; do not send a nested language object.
WhatsApp recipients accept the compatible recipient.id = "+E.164" form or the additive structured form with country_calling_code and national_number. Structured inputs are checked against the international numbering plan and can return invalid_phone_country_calling_code, invalid_phone_national_number, or invalid_phone_e164. Legacy id acceptance is unchanged.
{
"channel": "whatsapp",
"sender": { "type": "whatsapp_phone_number", "id": "pn_..." },
"recipient": {
"type": "phone_e164",
"country_calling_code": "55",
"national_number": "11903244174"
},
"message": { "type": "text", "text": { "body": "Olá" } }
}{
"channel": "whatsapp",
"sender": { "type": "whatsapp_phone_number", "id": "pn_..." },
"recipient": { "type": "phone_e164", "id": "+5511999999999" },
"message": {
"type": "template",
"template": {
"name": "order_update",
"language": "pt_BR",
"variables": { "first_name": "Ana" }
}
}
}WhatsApp media accepts image, document, audio,video, and sticker. Voice notes use the audio media path:media.kind = "audio". Provide exactly one of media.id,media.link, media.asset_id, media.inline, or media.source. Use media.asset_id for single-use or library uploads created through the Media API. A media.source with type = "tts"accepts immediately, renders caller-supplied text into an audio attachment on the media-render worker, and then delivers through the normal media path; it does not invoke an agent workflow or generate the reply text.
{
"channel": "whatsapp",
"sender": { "type": "whatsapp_phone_number", "id": "pn_..." },
"recipient": { "type": "phone_e164", "id": "+5511999999999" },
"message": {
"type": "media",
"media": {
"kind": "audio",
"link": "https://cdn.example.com/voice.ogg"
}
}
}{
"channel": "whatsapp",
"sender": { "type": "whatsapp_phone_number", "id": "pn_..." },
"recipient": { "type": "phone_e164", "id": "+5511999999999" },
"message": {
"type": "media",
"media": {
"kind": "image",
"asset_id": "mda_..."
}
}
}{
"channel": "whatsapp",
"sender": { "type": "whatsapp_phone_number", "id": "pn_..." },
"recipient": { "type": "phone_e164", "id": "+5511999999999" },
"message": {
"type": "media",
"media": {
"kind": "audio",
"source": {
"type": "tts",
"provider": "openai",
"text": "Your order is out for delivery.",
"voice": "marin",
"language": "en-US"
}
}
}
}Direct quick replies are WhatsApp interactive button messages. They require one to three reply buttons and must be sent inside the customer-service window.
{
"channel": "whatsapp",
"sender": { "type": "whatsapp_phone_number", "id": "pn_..." },
"recipient": { "type": "phone_e164", "id": "+5511999999999" },
"message": {
"type": "interactive",
"interactive": {
"type": "button",
"body": { "text": "Confirm delivery?" },
"action": {
"buttons": [
{ "type": "reply", "reply": { "id": "confirm", "title": "Confirm" } }
]
}
}
}
}Send a published WhatsApp Flow with message.type = "flow". Address the flow with flow.action.parameters.flow_id (the published flow's provider_flow_id, read from GET /v1/flows/{id}) or with flow.action.parameters.flow_name — provide exactly one. flow_token is your required opaque correlation token and comes back as submission.provider_token on the flow.completed webhook; flow_cta is the required button label (max 30 chars). See the Flows guide for the full create → publish → send → complete loop.
{
"channel": "whatsapp",
"sender": { "type": "whatsapp_phone_number", "id": "pn_..." },
"recipient": { "type": "phone_e164", "id": "+5511999999999" },
"message": {
"type": "flow",
"flow": {
"body": { "text": "Tap below to complete your booking." },
"action": {
"name": "flow",
"parameters": {
"flow_id": "1234567890",
"flow_token": "booking-7f3a",
"flow_cta": "Book now"
}
}
}
}
}Retrieve a message
Response
| Field | Type | Notes |
|---|---|---|
idrequired | string | |
objectrequired | "message" | |
channelrequired | "whatsapp" | "instagram" | "whatsapp_channel" | |
directionrequired | string | |
typerequired | string | |
statusrequired | string | |
environmentrequired | "sandbox" | "production" | |
senderrequired | object | |
recipientrequired | object | |
providerrequired | string | null | |
provider_message_idrequired | string | null | |
template_namerequired | string | null | |
template_idrequired | string | null | |
template_version_idrequired | string | null | |
template_versionrequired | integer | null | |
payloadrequired | unknown | null | |
metadatarequired | unknown | null | |
error_coderequired | string | null | |
error_messagerequired | string | null | |
provider_errorrequired | object | null | |
trace_idrequired | string | |
created_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
updated_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
eventsrequired | object[] |
List messages
Query params
| Field | Type | Notes |
|---|---|---|
limitrequired | integer | Maximum number of items to return. Defaults to 20; maximum 100. range 1..100 |
starting_after | string | Opaque cursor from the previous response next_cursor. |
status | string | |
batch_id | string | |
include | "payload" |
Response
| Field | Type | Notes |
|---|---|---|
objectrequired | "list" | |
datarequired | object[] | |
has_morerequired | boolean | |
next_cursorrequired | string | null |
List responses omit large message bodies by default: each item returns payload: null and metadata: null. Pass include=payload when an inspector or agent needs both fields.
Phone-like sender.id and recipient.id values are returned in strict +E.164 with every subscriber digit preserved. Tyxter may maintain a separate digits-only correlation key internally, but list and retrieve responses never substitute that key for the public identity. Opaque Meta phone-number ids remain unchanged.
const page = await tyxter.messages.list({
status: 'failed',
include: 'payload',
});
// page.data[0].payload and .metadata now contain the stored request data.Cancel a message
Response
| Field | Type | Notes |
|---|---|---|
idrequired | string | |
objectrequired | "message" | |
channelrequired | "whatsapp" | "instagram" | "whatsapp_channel" | |
directionrequired | string | |
typerequired | string | |
statusrequired | string | |
environmentrequired | "sandbox" | "production" | |
senderrequired | object | |
recipientrequired | object | |
providerrequired | string | null | |
provider_message_idrequired | string | null | |
template_namerequired | string | null | |
template_idrequired | string | null | |
template_version_idrequired | string | null | |
template_versionrequired | integer | null | |
payloadrequired | unknown | null | |
metadatarequired | unknown | null | |
error_coderequired | string | null | |
error_messagerequired | string | null | |
provider_errorrequired | object | null | |
trace_idrequired | string | |
created_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
updated_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
eventsrequired | object[] |