- Regular messages - the actual conversation: incoming and outgoing texts, media, buttons, lists, and template sends.
- System messages (
systemMessage: true) - routing records describing assignment and status changes. They carry only the fields in the System messages section and have nodirection,status, content or reactions.
Returned by: Get Messages of a Chat · Send a Message to Chat · Webhook message events
Example message object
Identity & routing
| Field | Type | Description |
|---|---|---|
_id | string | Unique message ID in Texter |
parent_chat | string | The chat this message belongs to |
chatChannelInfo | object | Which channel account / contact this message belongs to: {name, id, accountId} |
channelInfo.id | string | Provider-side message ID (e.g. WhatsApp wamid...). Use to correlate with provider logs and as context when replying. On system messages this is an internal placeholder with no provider meaning |
timestamp | number | When the message was created (epoch ms) |
updatedAt | string | Last update (ISO date-time) - changes e.g. when delivery status advances |
Content
type selects which content fields are present.
| Field | Type | Description | |
|---|---|---|---|
type | string | text, media, contacts, location, buttons, list, postback, special | |
text | string | Body text. Present on most text, buttons, list and special messages | |
media | object[] | Media items - see Media items below. Only when type: "media" | |
buttons | object[] | Reply buttons sent to the contact: {title, payload}. Only when type: "buttons" | |
list | object | List picker sent to the contact: {button, sections: [{title, rows: [{title, payload, description?}]}]}. Only when type: "list" | |
postback | object | Which button/list row the contact chose: {payload, title?, description?}. Incoming, only when type: "postback" | |
contacts | object[] | Shared vCard contact cards: name {formatted_name...}, phones[], emails[], urls[], addresses[], org, birthday. Only when type: "contacts" | |
location | object | Shared location: {latitude, longitude, name?, address?, url?}. Only when type: "location" | |
special | object | Channel-specific/structured content (e.g. template sends). Known flags: redacted: true (sensitive contents redacted), deleted: {previousType, timestamp} (contents removed by retention - explains “empty” messages), isEchoMessage: true (sent from another client, not Texter), isHistoryMessage, isStatusMessage, unsupportedByProvider | |
context | object | The message this one replies to. In API responses it is populated into a full Message object; in raw webhook payloads it may be only the provider reference {id} | |
forwarded | boolean | Whether WhatsApp marked the message as forwarded | |
sensitive | boolean | Whether the content is marked sensitive and should be redacted in some views | |
tmpSendId | `string | number` | Client-generated ID to match a send request to the stored message |
Media items
Each entry of themedia[] array:
| Field | Type | Description |
|---|---|---|
mediaType | string | image, video, document, audio, sticker |
fileId | string | Internal file ID in Texter storage. Download via Generate Public Media URL |
previewId | string | Internal preview/thumbnail file ID |
filename | string | Original filename from the sender device |
contentType | string | MIME type Example: application/pdf |
caption | string | Caption text. Relevant for image and video |
scanned | boolean | Whether the file has been scanned for threats |
metadata | object | Channel / provider metadata Example: {"frequentlyForwarded":false} |
deleted | object | {timestamp} - present when the file was removed by scheduled deletion; the fileId no longer resolves |
url | string | Deprecated - Use the fileId download flow instead |
Delivery & status
| Field | Type | Description |
|---|---|---|
direction | string | incoming or outgoing. Regular messages only |
status | number | 0 Sent, 1 Accepted, 2 Delivered, 3 Seen, 4 Failed, 5 Channel Failed, 6 Deleted |
statusHistory | object[] | Timeline of {status, timestamp} delivery/read states |
errorReason | string | Why the send failed (provider error, throttling, 24h window…). Only present if delivery failed Example: reengagement window closed |
reactions | string[] | Current emoji reactions on the message |
reactionsHistory | object[] | Reaction timeline: {timestamp, reaction?, removed?} |
Bot & automation
| Field | Type | Description |
|---|---|---|
agent | string | Who sent the message: "Bot" or an agent UID |
botSessionId | string | Bot session this message belongs to - filter messages by it in Get Messages of a Chat |
metadata.botMsgInfo | object | Which bot node generated this outgoing message: {identifier, version, nodeName, hideSummary} |
metadata.triggeredBot | boolean | Whether this incoming message triggered automation/bot logic |
hideSummary | boolean | Whether this message should be hidden from summaries |
Templates & campaigns
| Field | Type | Description |
|---|---|---|
metadata.whatsappTemplate | object | Structured template send data for outgoing template messages: {name, localization, contents} |
metadata.bulkSendId | string | Bulk / campaign batch ID for this message |
Retention & deletion
| Field | Type | Description | ||
|---|---|---|---|---|
scheduledDeletion | object | Planned deletion by retention rules: `timestamp (ms), type: “full" | "contents" | "media”, setManuallyByUid?` |
special.deleted | object | {previousType, timestamp} - set after contents were removed (the message shell remains) |
System messages
Present only whensystemMessage: true. System messages additionally carry _id, chatChannelInfo, parent_chat, timestamp, botSessionId and a placeholder channelInfo. They appear in Get Messages of a Chat history, but do not trigger message webhook events.
| Field | Type | Description |
|---|---|---|
systemMessage | boolean | true marks a routing/status record instead of a chat bubble |
newChatStatus | number | New chat status after this routing event (same values as chat status) |
agent | string | Who performed the action - "Bot" or an agent UID |
assignedToAgent | string | Which agent the chat was assigned to at this moment |
assignedToDepartment | string | Which department the chat was assigned to |
Deprecated fields
These may still appear in responses but should not be used in new code.Show deprecated fields
Show deprecated fields
| Field | Type | Description |
|---|---|---|
incoming | boolean | Deprecated - Use direction instead |
outgoing | boolean | Deprecated - Use direction instead |
received | number | Deprecated - Epoch ms. Use timestamp instead |
botMsgInfo | object | Deprecated - Top-level copy. Use metadata.botMsgInfo instead |
bulkSendId | string | Deprecated - Top-level copy. Use metadata.bulkSendId instead |
providerMessageId | string | Deprecated - Use channelInfo.id instead |
messageId | string | Deprecated - Use _id instead |
templateId | string | Deprecated - Use metadata.whatsappTemplate instead |
templateMessage | boolean | Deprecated - Use metadata.whatsappTemplate instead |
templateMessageData | object | Deprecated - Use metadata.whatsappTemplate instead |
parameters / templateParameters | string[] | Deprecated - Flat parameter arrays. Use metadata.whatsappTemplate instead |
Message status values
Used bystatus, statusHistory[].status and the messageStatus webhook field.
| Value | Meaning |
|---|---|
0 | Sent - sent from the platform |
1 | Accepted - accepted by the provider (e.g. Meta received it) |
2 | Delivered - delivered to the recipient’s device |
3 | Seen - read/opened by the recipient (blue ticks) |
4 | Failed - failed to deliver (e.g. invalid number) |
5 | Channel Failed - system/channel level failure |
6 | Deleted - message was deleted |
Content type values
| Type | Direction | Content field |
|---|---|---|
text | both | text |
media | both | media[] (types: image, video, document, audio, sticker) |
contacts | both | contacts[] |
location | both | location |
buttons | outgoing | text + buttons[] |
list | outgoing | text + list |
postback | incoming | postback |
special | both | special |