Get message activities
Retrieves the activity log for a specific message. Activities track the message lifecycle including acceptance, processing, sending, delivery, and any errors. A SCHEDULED entry carries scheduled_at, the release instant in UTC as it stood at that moment. Other entries have no scheduled_at key.
Response Body
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v3/messages/8ba7b830-9dad-11d1-80b4-00c04fd430c8/activities"{
"success": true,
"data": {
"message_id": "8ba7b830-9dad-11d1-80b4-00c04fd430c8",
"activities": [
{
"status": "DELIVERED",
"description": "Message delivered to recipient",
"from": "+15551234567",
"timestamp": "2026-10-20T13:17:48.7470157+00:00",
"scheduled_at": null,
"reason_code": null,
"reason": null,
"price": "0.0450",
"active_contact_price": "0.0050"
},
{
"status": "SENT",
"description": "Message sent via SMS",
"from": "+15551234567",
"timestamp": "2026-10-20T13:12:48.7470417+00:00",
"scheduled_at": null,
"reason_code": null,
"reason": null,
"price": "0.0450",
"active_contact_price": "0.0050"
},
{
"status": "PROCESSED",
"description": "Message processed and queued for sending",
"from": null,
"timestamp": "2026-10-20T13:11:48.7470419+00:00",
"scheduled_at": null,
"reason_code": null,
"reason": null,
"price": "0.0450",
"active_contact_price": "0.0050"
},
{
"status": "QUEUED",
"description": "Message accepted and queued for processing",
"from": null,
"timestamp": "2026-10-20T13:10:48.747042+00:00",
"scheduled_at": null,
"reason_code": null,
"reason": null,
"price": null,
"active_contact_price": null
}
],
"pagination": null
},
"error": null,
"meta": {
"request_id": "req_7X9zKp2jDw",
"timestamp": "2026-10-20T13:42:48.7470497+00:00",
"version": "v3"
}
}{
"success": true,
"error": {
"code": "string",
"message": "string",
"details": {
"property1": [
"string"
],
"property2": [
"string"
]
},
"doc_url": "string"
},
"meta": {
"request_id": "string",
"timestamp": "2019-08-24T14:15:22Z",
"version": "string"
}
}{
"success": false,
"data": null,
"error": {
"code": "RESOURCE_003",
"message": "Message not found",
"details": null,
"doc_url": "https://docs.sent.dm/reference/api/error-catalog"
},
"meta": {
"request_id": "req_7X9zKp2jDw",
"timestamp": "2026-10-20T13:42:48.7470521+00:00",
"version": "v3"
}
}{
"success": false,
"data": null,
"error": {
"code": "INTERNAL_001",
"message": "An unexpected error occurred while retrieving message activities.",
"details": null,
"doc_url": "https://docs.sent.dm/reference/api/error-catalog"
},
"meta": {
"request_id": "req_7X9zKp2jDw",
"timestamp": "2026-10-20T13:42:48.7470525+00:00",
"version": "v3"
}
}Get message status GET
Retrieves the current status and details of a message by ID. Includes delivery status, timestamps, and error information if applicable.
Cancel a scheduled message POST
Calls off a message you scheduled with `scheduled_at`, before it is released for sending. The message moves to `CANCELLED`, which is terminal, and it is never sent. **Only a SCHEDULED message can be cancelled.** A message that has already been released — queued, in flight, or finished — returns 409. The release sweeper runs continuously, so a cancellation sent within about a minute of the scheduled instant can lose that race and be refused; cancel with time to spare. **One message per call.** A send to many recipients, or on several channels, becomes one message per recipient × channel, each with its own id; cancel the ones you want stopped. There is no bulk cancellation. **Cancelling is free**, and nothing was charged for the hold in the first place — a scheduled message is only priced and billed at release. **A cancellation fires `message.cancelled`** on your webhook, exactly once, carrying the `scheduled_at` that was called off so a consumer can un-record the send it was expecting. Cancelling the same message again returns this same response and fires no second event. `Idempotency-Key` is honoured. A cancelled message cannot be resent — send a new one. The response is the message itself, in the same shape `GET /v3/messages/{id}` returns, so the `status` you read back is the one now stored on the row, and `scheduled_at` is the time it would have gone out. `GET /v3/messages/{id}` keeps reporting both afterwards. `events` is the message lifecycle as it stood immediately before the cancellation: the CANCELLED entry is written asynchronously and lands a moment later, so read `status` for the outcome. If you need the entry itself, re-fetch the message after a few seconds — `GET /v3/messages/{id}` is cached briefly, so an immediate re-fetch can still show the pre-cancellation state.