GET /v1/messages/{messageId}/receipts
Ask what one message's delivery and read receipts say, now — the transport's answer, unknowns included, never stored.
GET /v1/messages/{messageId}/receiptsAsks the transport behind a message's line what it can prove about that message
now, and answers with what it said. Nothing is stored and nothing moves the
message's status: this is a question, not evidence. For receipts as they
happen, open the stream with ?events=receipts.
curl https://api.mapier.ai/v1/messages/0192a7c4-5a31-7bd2-8e6f-1d0c9b8a7f65/receipts \
-H "Authorization: Bearer $MAPIER_API_KEY"{
"messageId": "0192a7c4-5a31-7bd2-8e6f-1d0c9b8a7f65",
"upstreamMessageId": "guid-1",
"delivered": true,
"read": null,
"checkedAt": "2026-08-24T18:09:40.000Z",
"upstreamStatus": "delivered"
}messageId in the path is Mapier's id for a message this key can read — the
messageId a receipt or delivery_failed frame carries, or the one a
message.* webhook names.
The response
Prop
Type
delivered and read are three-valued. null is "the transport does not know", not "no". A
client that writes if (!answer.delivered) reports a delivered message as undelivered the first
time a bridge was offline when it was asked.
When there is nothing to ask about
409 conflictwithdetails.reason: "no_command"— the message is real and this key may read it, but it was never handed to a transport, so there are no receipts to ask for. That is every inbound message, and every outbound one whose transport never accepted it.404 not_foundwith adetails.reasonis the transport's answer:not_settledmeans it knows the message and has not settled it — ask again shortly — whilenot_a_sendandno_echo_guidmean this message will never have receipts.404 not_foundwith no reason is a message this key cannot read, or one the transport does not know.
Errors
| Status | Code | Cause |
|---|---|---|
400 | bad_request | The transport refused the question; details.reason is its own word |
401 | invalid_credentials | No key, or one that is unknown, revoked or expired |
404 | not_found | No such message for this key, or the transport's not_settled, not_a_send or no_echo_guid (above) |
409 | conflict | details.reason: "no_command" — the message was never handed to a transport. A transport's own reason may add details.retryAfter: the seconds to wait before asking again |
409 | project_archived | The project is archived |
422 | validation_failed | messageId is not a uuid, or an x-mapier-version this build does not answer to |
429 | rate_limited | The transport's own rate limit (details.retryAfter when it gave a wait), or too many failed authentications from your calling address |
500 | internal_error | An unhandled failure, reported; details.requestId names the log line when present |
503 | line_unavailable | The message's line cannot be asked right now; details.reason says why |
503 | upstream_unavailable | The transport did not answer, or answered with something this platform could not use |
503 | service_busy | The platform had no database connection free in time and did nothing; wait details.retryAfter seconds and ask again |
This route has no rate-limit budget of its own. Every refusal is the one envelope described in Error codes.