Skip to main content
The message.* events follow a message from the moment iSnap accepts or receives it. For each of the nine event types, this page says when it is sent and when it is not, lists the fields of data, and shows a full event. You need it to track a send to its final status and to receive inbound messages. A send through the API produces message.queued, or message.scheduled when the message is held and then message.queued when it is released. message.sent or message.failed follows, then message.delivered and message.read if the line’s device reports them, and message.fallback_triggered when the device sent, or tried to send, the message over SMS or RCS. Delivery order is not guaranteed. Order events by the timestamps inside data, not by arrival: message.delivered can reach you before message.sent. See Sending messages for the statuses of a message.

Common fields

Every message.* event carries these fields in data. The sections below list the fields each event type adds. The message object has no chat_id. Three events carry the chat id beside message: message.received, message.sent with origin: "device", and the message.read that follows your own mark-read call. The message events of a trial are tied to the trial’s pool line. A subscription with a line filter receives them only if it lists that line id. On a line that another account owned before you, you receive the device reports about the messages of that account: see Lines that change owner. Personal data. data.message carries the message text, the handles of the contact and of the line (phone numbers or email addresses), attachment file names and the handles of the senders of reactions. message.received can add contact_name. Subscribe to message events only when you need them. Do not copy this data into logs, tickets or other tools. Refer to a contact by an id of your own.

message.queued

Sent when: data holds the common fields only.
Personal data: data.message.

message.scheduled

Sent when a message is accepted but held, and again each time its planned send time moves by more than 15 minutes. A smaller move sends nothing, and so does the move of a held message that enters the reply lane because its contact wrote. message.queued follows when the message is released. See Held messages.
Personal data: data.message.

message.sent

Sent in two cases, told apart by data.origin. Common fields:

A message created through the API

origin is api: the line’s device confirms that it sent a message created through the API. data holds the three common fields. message.status is sent, and message.service is the service the device used, when the device reports one.

A message typed on the device

origin is device: someone typed a message on the line’s own device. The message is recorded with direction: outbound and status: delivered, and message.sent_at and message.delivered_at both hold the device’s time. data adds one field: This case exists only for a line that has a device of its own: a rented line or a BYOD line. It is not sent for a shared line or for a line that runs trials, nor for the device’s own copy of a message created through the API.
Personal data: data.message.

message.delivered

Sent the first time the line’s device reports that an outbound message was delivered. iSnap learns of a delivery only from the device: no report means no event. A report for a status the message already has, or for a message that iSnap has deleted, sends nothing. A message can reach read with no message.delivered and with delivered_at still null.
Personal data: data.message.

message.read

Sent in two cases. Every case carries message and read_at: rely on these two fields, and treat the others as present only in their case. The first case concerns a message you sent, whose message.status is read. The second concerns an inbound message: message.direction is inbound, and message.status stays delivered.

The recipient read your message

The line’s device reports that the recipient read an outbound message. data holds the two common fields and can add message_id, line_id and status (always read); on an iMessage line it always adds them.

Your own mark-read call

POST /v1/chats/{chat_id}/read sends one event per inbound message it newly marks read. On a line that another account owned before you, that includes the inbound messages that account had not marked read: see Lines that change owner. data adds:
A report of a read for a message that iSnap has deleted sends nothing. Personal data: data.message.

message.failed

Sent in three cases. Every case carries message and failed_at. For the cause, read message.error_code and message.error_message: they have one meaning in every case, while the fields beside message differ. iSnap never resends a failed message: send a new message to retry. See Sending messages.

The device refuses the send

The line’s device reports that it could not send the message. data adds:

The device reports a failure after the send

The line’s device reports the status failed for a message it had sent. data adds:

iSnap fails a message that was still waiting

iSnap fails the message itself: the line was terminated, the message waited too long, or the device took it and never reported an outcome. data adds:
Personal data: data.message.

message.received

Sent when an inbound message is stored. An inbound message has status: delivered. The event is not sent:
  • on a shared line, for a message from a contact the line has no active binding with;
  • on a line that runs trials, for the text that carries a pairing code, and for a message from a sender who is not the paired prospect of a trial;
  • for a second copy of a message the device reports twice;
  • for history that a device reports from before iSnap was watching the line.
Personal data: data.message and contact_name.

message.cancelled

Sent when you cancel a queued or held message with DELETE /v1/messages/{id}. It is not sent for a message of a trial. data holds the common fields only. message.status is cancelled and message.cancelled_at is set.
Personal data: data.message.

message.fallback_triggered

Sent when the line’s device reports that a message went out, or was attempted, over SMS or RCS instead of iMessage, whether that attempt succeeded or failed. It does not prove that an iMessage attempt was made first: the device also reports it for a message it sent directly as SMS or RCS because it already knew the recipient is not on iMessage. The same report also produces message.sent or message.failed.
Personal data: data.message.