Response stream

Delivery events

Apple Delivered and Read as a stored projection on the stream. The live ask is still send-status.

event: delivery is a fan-out of delivery truth the service has already stored for one of your sends. It is not a live read of the Mac, and it is not a second event: command. Command status does not change when this frame arrives.

For message.send, succeeded still means the Mac ingested the outbound echo — the bubble exists in chat.db. It is not Apple's Delivered stamp.

event: delivery
data: {"commandId":"cmd-1","conversationId":"a0000000-0000-4000-8000-000000000001","deliveryState":"delivered","deliveryService":"iMessage","deliveryError":null,"deliveredAt":"2026-08-24T18:03:14.000Z","readAt":null,"occurredAt":"2026-08-24T18:03:14.000Z"}

The frame

Prop

Type

When a frame is emitted

A frame is emitted when deliveryState changes, or when deliveredAt or readAt first appears or moves forward. A check that only restamps the last time the projection was looked at is silent.

deliveryState stays delivered when a later readAt lands. The new timestamp is the change, so you can see a second frame whose state is still delivered.

An SMS send is not part of this sweep and does not emit event: delivery.

Do not mark the message delivered from event: command with status: "succeeded". That frame is the echo. Apple's stamp is deliveryState, deliveredAt and readAt here — or the live read below, which can disagree with a projection that has not been updated yet.

Live read, not this frame

GET /v1/send-status/:commandId asks the Mac now. Use it when you need the current Apple stamp rather than the last projection the stream fanned out. The two are different objects. This frame does not replace that GET, and that GET does not arrive on the stream.

Catch-up

includeDelivery: true on POST /v1/replay returns deliveries[]: one current projection per requested command that has been checked, in the same shape as this frame. It requires commandIds. It is not a reconstruction of every poll.

Sort is occurredAt, then commandId. limit caps the array (default 50, max 200). Unchecked commands and another account's commands are omitted. Apply by commandId. A Read that landed after delivered is on this object even when deliveryState stayed delivered. Live and replay can overlap.

On this page