BetaThe V4 API is in beta — endpoints and functionality may change.

Message fields reference (v4)

Every field on a v4 multi-channel message object, plus the full status lifecycle and protocol (transport) states across iMessage, SMS, RCS, and WhatsApp

This is the field-by-field reference for the v4 message object (api.blooio.com/v4). v4 is a multi-channel API — the same message shape covers iMessage, SMS, RCS, and WhatsApp — so it adds a few transport values that don't exist in v2. For the single-channel iMessage API, see the v2 message fields reference.

Note

The v4 API is currently in beta. Field shapes are stable, but new status / protocol values may be added as channels evolve — always handle unknown values defensively.

The message object

{
  "id": "msg_018f7b2a1c3d7e4f9a2b0c1d2e3f4a5b",
  "chat_id": "chat_abc123",
  "channel_id": "ch_abc123",
  "channel_type": "blooio",
  "protocol": "imessage",
  "direction": "outbound",
  "type": "text",
  "text": "Hello!",
  "status": "delivered",
  "provider_message_id": "p_9f8e...",
  "reply_to_message_id": null,
  "error": null,
  "created_at": 1720992000000,
  "updated_at": 1720992003000
}
Field Type Description
id string Unique message id, prefixed msg_.
chat_id string The chat this message belongs to (chat_).
channel_id string The sending/receiving channel (ch_).
channel_type enum blooio (iMessage), twilio, whatsapp_business, or rcs_business.
protocol enum Transport that carried the message — see Protocol states.
direction enum inbound or outbound.
type string Content type, e.g. text, media, poll.
text string | null Message body. null for media-only messages.
status string Delivery lifecycle state — see Status lifecycle.
provider_message_id string | null The upstream provider/device id, once assigned.
reply_to_message_id string | null The msg_ this message replies to, when it's an inline reply.
error object | null Structured error ({ code, message, ... }) when status is failed or protocol resolution failed.
created_at int64 Epoch milliseconds when the message was created.
updated_at int64 Epoch milliseconds of the last status/protocol update.

The send endpoints return the message at the top level (not wrapped in data) as a MessageSendResult, which adds routing hints like group_id, hybrid, and fallback.

Status lifecycle

status describes where a message is in its delivery lifecycle, independent of which channel or transport carried it.

Status Description
queued Accepted and waiting to be handed to the channel.
sent Handed off to the channel/provider. Protocol resolves around here.
delivered A delivery receipt was received.
read A read receipt was received (where the channel supports it).
failed The message could not be delivered — see error.
superseded The row was replaced (an idempotency-key retry loser, or a poll-vote supersession) and is not an independently deliverable message.

Typical happy path:

queued → sent → delivered → read

Note

Inbound messages surface through the unified event feed and webhooks with status received. Lifecycle transitions are emitted as message.* events (message.sent, message.delivered, message.read, message.failed).

Protocol states

protocol records the transport that carried (or will carry) the message. For blooio (iMessage) channels, Blooio picks the transport at send time and resolves it shortly after; other channel types have a fixed transport.

Warning

protocol is never null. A freshly-accepted message starts at pending and resolves to a concrete transport within seconds.

Protocol Meaning
pending Accepted and dispatched; the wire service is not resolved yet. Transient — settles within seconds of sent.
imessage Delivered over iMessage (blue bubble).
rcs Delivered over RCS.
sms Delivered over SMS/MMS (green bubble).
whatsapp Sent over WhatsApp.
unknown Accepted, but the transport could not be resolved before the tracking window closed (see error).

How protocol relates to channel_type

For fixed-transport channels the protocol is known immediately; only blooio (iMessage) sends start at pending while the device resolves the wire service.

channel_type Initial protocol Resolves to
blooio pending imessage / rcs / sms (or unknown)
twilio sms sms
rcs_business rcs rcs
whatsapp_business whatsapp whatsapp

Reading protocol safely

Treat pending as "not yet known" and unknown as a terminal "accepted but unconfirmed" state. Because v4 is multi-channel and evolving, always keep a default branch for values you don't recognize.

switch (message.protocol) {
  case "pending":
    // Not resolved yet — re-read or wait for a message.* event.
    break;
  case "imessage":
  case "rcs":
  case "whatsapp":
    // Rich transport confirmed.
    break;
  case "sms":
    // SMS/MMS.
    break;
  case "unknown":
    // Accepted, but transport never confirmed. Inspect `error`.
    break;
  default:
    // Forward-compatible: handle new transports gracefully.
    break;
}

Next steps