Retrieve a stored message
/api/v1/domains/{domain}/messages/{messageId}The archived copy of a message, which is what a webhook's storage.url points at.
messageId is the id exactly as it arrived, angle brackets included. Stripping
them returns 404: the archive stores the id as it was received, and a bridge that
helpfully removed < and > is why every inbound message 404'd here until
2026-09-14.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
domainrequired | path | string | The domain id, or the domain name itself. |
messageIdrequired | path | string | The message id exactly as it arrived, angle brackets included. |
Request
/api/v1/domains/{domain}/messages/{messageId}curl -X GET 'https://app.mailyte.com/api/v1/domains/yourdomain.com/messages/01JBT8XQ2M9WYC3K4F6R7S8T9V' \
-H 'Authorization: Bearer mk_live_YOUR_API_KEY'const response = await fetch('https://app.mailyte.com/api/v1/domains/yourdomain.com/messages/01JBT8XQ2M9WYC3K4F6R7S8T9V', {
method: 'GET',
headers: {
Authorization: 'Bearer mk_live_YOUR_API_KEY',
},
});
const { data } = await response.json();import requests
response = requests.get(
"https://app.mailyte.com/api/v1/domains/yourdomain.com/messages/01JBT8XQ2M9WYC3K4F6R7S8T9V",
headers={"Authorization": "Bearer mk_live_YOUR_API_KEY"},
)
data = response.json()["data"]<?php
$response = Http::withToken('mk_live_YOUR_API_KEY')
->get('https://app.mailyte.com/api/v1/domains/yourdomain.com/messages/01JBT8XQ2M9WYC3K4F6R7S8T9V');
$data = $response->json('data');require "net/http"
require "json"
uri = URI("https://app.mailyte.com/api/v1/domains/yourdomain.com/messages/01JBT8XQ2M9WYC3K4F6R7S8T9V")
request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer mk_live_YOUR_API_KEY"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }Response
Success.
dataobjectobjectstringarchived_message | archived_message_previewWhich of the two shapes you got.
archived_messageis the default and carriesraw;archived_message_previewis?format=htmland carries the parsed fields instead. Branch on this, never on the presence of a key.message_idstringThe Message-ID, angle brackets included, as the send returned it.
domainstringThe domain this copy is archived under.
archived_atstringWhen the message was archived. Null if the stored copy has no date.
legal_holdbooleanDefault shape only. True means retention cannot expire this copy.
rawstringThe raw message (
message/rfc822) exactly as stored: headers, body and attachments. It is not made safe, so do not show it in a browser; use?format=htmlfor that. Not present with?format=html.headersobject?format=htmlonly. The parsed headers, name to value.htmlstringWith
?format=htmlonly: the HTML body, made safe to display, with scripts and remote content removed. Null when the message has no HTML part; showtextinstead.textstringWith
?format=htmlonly: the plain-text body. Null when the message has no plain-text part.htmlandtextcan both be null.attachmentsarray<object>With
?format=htmlonly: each attachment's name, type and size, not the file itself.blocked_remote_countintegerWith
?format=htmlonly: how many remote images or other content were blocked, so you can tell the reader.
Returned inside the standard envelope.
Errors
| Status | When |
|---|---|
401 | The API key is missing, unknown, revoked or expired. All four answer identically, on purpose: distinguishing them would confirm which keys exist. |
403 | The key is valid but may not do this: it lacks the required scope, its IP allowlist does not include you, or this endpoint does not accept API keys. |
404 | No such resource in this organization. |
422 | The request was understood but the values were not acceptable. |
429 | Too many requests, or the organization has spent its sending allowance. `Retry-After` says how long to wait. |
Every status, with what causes it and what to do, is on the error reference.