Messages
Stored messages, with their deliveries and attachments.
Auth: Session token · Base URL:
https://api.mailkite.dev
Endpoints
Each row expands to its request and response schema. The address bar follows along, so any endpoint can be linked to directly.
GET /api/messages List stored messages, newest first. Optionally filter with `search` (matches sender, recipient, or subject) and page with `before` (a `received_at` cursor) and `limit`; omit all for the default newest 100. Response is a bare array — paginate by passing the last row's `received_at` as the next `before`.
List stored messages, newest first. Optionally filter with `search` (matches sender, recipient, or subject) and page with `before` (a `received_at` cursor) and `limit`; omit all for the default newest 100. Response is a bare array — paginate by passing the last row's `received_at` as the next `before`.
A stored message (msg_…), inbound or outbound. GET /api/messages returns list rows: the stored fields plus per-message delivery counters, without bodies. GET /api/messages/:id (see message-detail) returns the same resource with bodies (text_body/html_body/headers_json) and without the list counters.
| Field | Type | Notes |
|---|---|---|
| id req | string | Message id (msg_…), stable across webhook retries and replays. |
| user_id req | string | Owning account (usr_…). |
| route_id | string · null | The route that handled an inbound message (rte_…); null for outbound sends. |
| mailbox_id | string · null | The mailbox the message is anchored to for access control; null when the address isn't on an owned domain. |
| direction req | "inbound" · "outbound" | Whether MailKite received or sent the message. |
| from req | object | Structured sender — the same shape the email.received webhook carries. |
| from.address req | string | Email address, from the SMTP envelope. |
| from.name | string | Display name decoded from the MIME header. Omitted when the message carried none or the header names a different address. Sender-asserted and unverified. |
| to req | object[] | Structured recipients — the same shape the email.received webhook carries. |
| to[].address req | string | Email address, from the SMTP envelope. |
| to[].name | string | Display name decoded from the MIME header. Omitted when the message carried none or the header names a different address. Sender-asserted and unverified. |
| from_addr req | string | Bare sender address from the SMTP envelope (MAIL FROM). |
| to_addr req | string | Bare recipient address from the SMTP envelope (RCPT TO). |
| subject | string · null | Decoded subject line; null when the message had none. |
| text_body | string · null | Plain-text body. Detail responses only — list rows never carry bodies. |
| html_body | string · null | HTML body. Detail responses only — list rows never carry bodies. |
| headers_json | string · null | Stored MIME headers as a JSON string. Detail responses only. |
| spf | string · null | SPF verdict for an inbound message ('pass', 'fail', …); null when not checked. |
| dkim | string · null | DKIM verdict for an inbound message; null when not checked. |
| dmarc | string · null | DMARC verdict for an inbound message; null when not checked. |
| spam | string · null | Spam verdict for an inbound message ('ham', 'spam'); null when not checked. |
| thread_id | string · null | Conversation root id — pass it to send()'s inReplyTo to reply in-thread. null when the message carried no usable id. |
| send_status | string | Outbound send state: 'sending', 'sent', or 'failed'. Always 'sent' for inbound rows. |
| track_id | string · null | Open-tracking token for an outbound message when tracking was on; null = off. |
| received_at req | integer | When MailKite accepted the message (arrival time — stable across retries and replays), in Unix epoch milliseconds (UTC). |
| size_bytes | integer · null | Stored byte size (headers + bodies; attachments sized separately). |
| delivery_count | integer | How many webhook deliveries exist for this message. List rows only. |
| attempts | integer · null | Max attempts across this message's deliveries. List rows only. |
| last_status_code | integer · null | HTTP status of the most recent delivery. List rows only. |
| delivered_count | integer | Deliveries in state 'delivered'. List rows only. |
| failed_count | integer | Deliveries in state 'failed'. List rows only. |
| pending_count | integer | Deliveries in state 'pending'. List rows only. |
| webhook_status | string · null | Rolled-up webhook state for the list pill ('delivered', 'failed', 'pending'); null when the message has no deliveries. List rows only. |
An actual array of results, recorded from the conformance suite.
[
{
"id": "msg_2Hk9QpVn4tLd",
"user_id": "usr_7Fj3MnQw",
"route_id": "rte_4Bn8XcVm",
"direction": "inbound",
"from": {
"address": "ada@example.com",
"name": "Ada Lovelace"
},
"to": [
{
"address": "support@myapp.ai",
"name": "Support"
}
],
"from_addr": "ada@example.com",
"to_addr": "support@myapp.ai",
"subject": "Invoice question",
"thread_id": "msg_2Hk9QpVn4tLd",
"received_at": 1769731200000,
"size_bytes": 4821,
"spf": "pass",
"dkim": "pass",
"dmarc": "pass",
"spam": null,
"send_status": "sent",
"delivery_count": 1,
"attempts": 1,
"last_status_code": 200,
"delivered_count": 1,
"failed_count": 0,
"pending_count": 0,
"webhook_status": "delivered"
}
] {
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://api.mailkite.dev/v1/schemas/message.json",
"title": "Message",
"description": "A stored message (msg_…), inbound or outbound. GET /api/messages returns list rows: the stored fields plus per-message delivery counters, without bodies. GET /api/messages/:id (see message-detail) returns the same resource with bodies (text_body/html_body/headers_json) and without the list counters.",
"type": "object",
"required": [
"id",
"user_id",
"direction",
"from",
"to",
"from_addr",
"to_addr",
"received_at"
],
"properties": {
"id": {
"type": "string",
"description": "Message id (msg_…), stable across webhook retries and replays.",
"examples": [
"msg_2Hk9QpVn4tLd"
]
},
"user_id": {
"type": "string",
"description": "Owning account (usr_…).",
"examples": [
"usr_7Fj3MnQw"
]
},
"route_id": {
"type": [
"string",
"null"
],
"description": "The route that handled an inbound message (rte_…); null for outbound sends."
},
"mailbox_id": {
"type": [
"string",
"null"
],
"description": "The mailbox the message is anchored to for access control; null when the address isn't on an owned domain."
},
"direction": {
"type": "string",
"enum": [
"inbound",
"outbound"
],
"description": "Whether MailKite received or sent the message."
},
"from": {
"type": "object",
"required": [
"address"
],
"description": "Structured sender — the same shape the email.received webhook carries.",
"properties": {
"address": {
"type": "string",
"description": "Email address, from the SMTP envelope.",
"examples": [
"ada@example.com"
]
},
"name": {
"type": "string",
"description": "Display name decoded from the MIME header. Omitted when the message carried none or the header names a different address. Sender-asserted and unverified.",
"examples": [
"Ada Lovelace"
]
}
}
},
"to": {
"type": "array",
"description": "Structured recipients — the same shape the email.received webhook carries.",
"items": {
"type": "object",
"required": [
"address"
],
"description": "One recipient.",
"properties": {
"address": {
"type": "string",
"description": "Email address, from the SMTP envelope.",
"examples": [
"ada@example.com"
]
},
"name": {
"type": "string",
"description": "Display name decoded from the MIME header. Omitted when the message carried none or the header names a different address. Sender-asserted and unverified.",
"examples": [
"Ada Lovelace"
]
}
}
}
},
"from_addr": {
"type": "string",
"description": "Bare sender address from the SMTP envelope (MAIL FROM).",
"examples": [
"ada@example.com"
]
},
"to_addr": {
"type": "string",
"description": "Bare recipient address from the SMTP envelope (RCPT TO).",
"examples": [
"support@myapp.ai"
]
},
"subject": {
"type": [
"string",
"null"
],
"description": "Decoded subject line; null when the message had none.",
"examples": [
"Invoice question"
]
},
"text_body": {
"type": [
"string",
"null"
],
"description": "Plain-text body. Detail responses only — list rows never carry bodies."
},
"html_body": {
"type": [
"string",
"null"
],
"description": "HTML body. Detail responses only — list rows never carry bodies."
},
"headers_json": {
"type": [
"string",
"null"
],
"description": "Stored MIME headers as a JSON string. Detail responses only."
},
"spf": {
"type": [
"string",
"null"
],
"description": "SPF verdict for an inbound message ('pass', 'fail', …); null when not checked.",
"examples": [
"pass"
]
},
"dkim": {
"type": [
"string",
"null"
],
"description": "DKIM verdict for an inbound message; null when not checked.",
"examples": [
"pass"
]
},
"dmarc": {
"type": [
"string",
"null"
],
"description": "DMARC verdict for an inbound message; null when not checked.",
"examples": [
"pass"
]
},
"spam": {
"type": [
"string",
"null"
],
"description": "Spam verdict for an inbound message ('ham', 'spam'); null when not checked."
},
"thread_id": {
"type": [
"string",
"null"
],
"description": "Conversation root id — pass it to send()'s inReplyTo to reply in-thread. null when the message carried no usable id.",
"examples": [
"msg_2Hk9QpVn4tLd"
]
},
"send_status": {
"type": "string",
"description": "Outbound send state: 'sending', 'sent', or 'failed'. Always 'sent' for inbound rows.",
"examples": [
"sent"
]
},
"track_id": {
"type": [
"string",
"null"
],
"description": "Open-tracking token for an outbound message when tracking was on; null = off."
},
"received_at": {
"type": "integer",
"description": "When MailKite accepted the message (arrival time — stable across retries and replays), in Unix epoch milliseconds (UTC).",
"examples": [
1769731200000
]
},
"size_bytes": {
"type": [
"integer",
"null"
],
"description": "Stored byte size (headers + bodies; attachments sized separately).",
"examples": [
4821
]
},
"delivery_count": {
"type": "integer",
"description": "How many webhook deliveries exist for this message. List rows only.",
"examples": [
1
]
},
"attempts": {
"type": [
"integer",
"null"
],
"description": "Max attempts across this message's deliveries. List rows only.",
"examples": [
1
]
},
"last_status_code": {
"type": [
"integer",
"null"
],
"description": "HTTP status of the most recent delivery. List rows only.",
"examples": [
200
]
},
"delivered_count": {
"type": "integer",
"description": "Deliveries in state 'delivered'. List rows only.",
"examples": [
1
]
},
"failed_count": {
"type": "integer",
"description": "Deliveries in state 'failed'. List rows only.",
"examples": [
0
]
},
"pending_count": {
"type": "integer",
"description": "Deliveries in state 'pending'. List rows only.",
"examples": [
0
]
},
"webhook_status": {
"type": [
"string",
"null"
],
"description": "Rolled-up webhook state for the list pill ('delivered', 'failed', 'pending'); null when the message has no deliveries. List rows only.",
"examples": [
"delivered"
]
}
}
} GET /api/messages/:id Get a message with deliveries + attachments.
Get a message with deliveries + attachments.
Response body
message-detail.jsonGET /api/messages/:id — the full message with its delivery history, pipeline events, per-attempt audit rows, recorded opens, and attachments.
| Field | Type | Notes |
|---|---|---|
| message req | message | The message itself, with bodies (text_body/html_body/headers_json) and without the list-row counters. |
| message.id req | string | Message id (msg_…), stable across webhook retries and replays. |
| message.user_id req | string | Owning account (usr_…). |
| message.route_id | string · null | The route that handled an inbound message (rte_…); null for outbound sends. |
| message.mailbox_id | string · null | The mailbox the message is anchored to for access control; null when the address isn't on an owned domain. |
| message.direction req | "inbound" · "outbound" | Whether MailKite received or sent the message. |
| message.from req | object | Structured sender — the same shape the email.received webhook carries. |
| message.from.address req | string | Email address, from the SMTP envelope. |
| message.from.name | string | Display name decoded from the MIME header. Omitted when the message carried none or the header names a different address. Sender-asserted and unverified. |
| message.to req | object[] | Structured recipients — the same shape the email.received webhook carries. |
| message.to[].address req | string | Email address, from the SMTP envelope. |
| message.to[].name | string | Display name decoded from the MIME header. Omitted when the message carried none or the header names a different address. Sender-asserted and unverified. |
| message.from_addr req | string | Bare sender address from the SMTP envelope (MAIL FROM). |
| message.to_addr req | string | Bare recipient address from the SMTP envelope (RCPT TO). |
| message.subject | string · null | Decoded subject line; null when the message had none. |
| message.text_body | string · null | Plain-text body. Detail responses only — list rows never carry bodies. |
| message.html_body | string · null | HTML body. Detail responses only — list rows never carry bodies. |
| message.headers_json | string · null | Stored MIME headers as a JSON string. Detail responses only. |
| message.spf | string · null | SPF verdict for an inbound message ('pass', 'fail', …); null when not checked. |
| message.dkim | string · null | DKIM verdict for an inbound message; null when not checked. |
| message.dmarc | string · null | DMARC verdict for an inbound message; null when not checked. |
| message.spam | string · null | Spam verdict for an inbound message ('ham', 'spam'); null when not checked. |
| message.thread_id | string · null | Conversation root id — pass it to send()'s inReplyTo to reply in-thread. null when the message carried no usable id. |
| message.send_status | string | Outbound send state: 'sending', 'sent', or 'failed'. Always 'sent' for inbound rows. |
| message.track_id | string · null | Open-tracking token for an outbound message when tracking was on; null = off. |
| message.received_at req | integer | When MailKite accepted the message (arrival time — stable across retries and replays), in Unix epoch milliseconds (UTC). |
| message.size_bytes | integer · null | Stored byte size (headers + bodies; attachments sized separately). |
| message.delivery_count | integer | How many webhook deliveries exist for this message. List rows only. |
| message.attempts | integer · null | Max attempts across this message's deliveries. List rows only. |
| message.last_status_code | integer · null | HTTP status of the most recent delivery. List rows only. |
| message.delivered_count | integer | Deliveries in state 'delivered'. List rows only. |
| message.failed_count | integer | Deliveries in state 'failed'. List rows only. |
| message.pending_count | integer | Deliveries in state 'pending'. List rows only. |
| message.webhook_status | string · null | Rolled-up webhook state for the list pill ('delivered', 'failed', 'pending'); null when the message has no deliveries. List rows only. |
| actor_email req | string · null | When a team member sent this message as the domain owner: the acting member's email. null otherwise. |
| actor_team_name req | string · null | When a team member sent this message as the domain owner: the team's name. null otherwise. |
| deliveries req | delivery[] | Every webhook delivery of this message, newest last — retries and replays append. |
| deliveries[].id req | string | Delivery id (dlv_…). |
| deliveries[].message_id req | string | The message this delivery carries (msg_…). |
| deliveries[].route_id req | string | The route whose webhook was targeted (rte_…). |
| deliveries[].url req | string | The webhook URL the body was POSTed to. |
| deliveries[].status req | "pending" · "delivered" · "failed" · "paused" | Current state of this delivery. |
| deliveries[].attempts req | integer | How many attempts this delivery has made. |
| deliveries[].last_status_code | integer · null | HTTP status of the most recent attempt. |
| deliveries[].next_retry_at | integer · null | When the auto-retry cron will re-attempt a failed delivery; null when nothing is due, in Unix epoch milliseconds (UTC); null when it has never happened. |
| deliveries[].retry_attempts | integer | How many automatic retries have been scheduled so far. |
| deliveries[].created_at req | integer | When the delivery was created, in Unix epoch milliseconds (UTC). |
| deliveries[].updated_at req | integer | When the delivery last changed, in Unix epoch milliseconds (UTC). |
| events req | object[] | The pipeline timeline for this message (received → routed → webhook attempts → retries). Metadata only, never bodies. |
| events[].id req | string | Event id (evt_…). |
| events[].kind req | string | Event kind (e.g. 'email.received', 'webhook.delivered', 'webhook.failed', 'webhook.test'). |
| events[].status req | "ok" · "fail" · "info" | Outcome facet. |
| events[].domain | string · null | Domain the event belongs to. |
| events[].route_id | string · null | Route involved, when any. |
| events[].message_id | string · null | Message involved, when any. |
| events[].delivery_id | string · null | Delivery involved, when any. |
| events[].target | string · null | Webhook URL / forward address / recipient, when relevant. |
| events[].code | integer · null | HTTP or provider status code, when relevant. |
| events[].message | string · null | Human-readable detail. |
| events[].created_at req | integer | When the event was recorded, in Unix epoch milliseconds (UTC). |
| deliveryAttempts req | object[] | Per-attempt audit rows (timing, response code/headers/body) behind the delivery inspector. |
| deliveryAttempts[].id req | string | Attempt id (att_…). |
| deliveryAttempts[].delivery_id req | string | The delivery this attempt belongs to (dlv_…). |
| deliveryAttempts[].message_id req | string | The message delivered (msg_…). |
| deliveryAttempts[].attempt_number req | integer | 1-based attempt counter within the delivery. |
| deliveryAttempts[].ok req | 0 · 1 | 1 when the attempt succeeded. |
| deliveryAttempts[].reason | string · null | Failure classification when not ok (e.g. 'http_5xx', 'timeout', 'no-ack'). |
| deliveryAttempts[].response_status | integer · null | HTTP status the endpoint returned. |
| deliveryAttempts[].response_headers | string · null | Response headers as a JSON string. |
| deliveryAttempts[].response_body | string · null | Response body, truncated to ~4KB. |
| deliveryAttempts[].duration_ms | integer · null | Round-trip time of the attempt. |
| deliveryAttempts[].requested_at req | integer | When the attempt started, in Unix epoch milliseconds (UTC). |
| deliveryAttempts[].created_at req | integer | When the audit row was recorded, in Unix epoch milliseconds (UTC). |
| opens req | object[] | Recorded opens for an outbound message; empty when tracking was off or nothing was opened. |
| attachments req | object[] | Stored attachments with signed download URLs. |
| attachments[].id req | string | Attachment id. |
| attachments[].filename req | string | Original filename. |
| attachments[].contentType | string · null | MIME type. |
| attachments[].size req | integer | Size in bytes. |
| attachments[].contentId | string · null | MIME Content-ID for inline attachments. |
| attachments[].disposition | string · null | 'inline' or 'attachment'. |
| attachments[].url req | string | Signed, time-limited download URL — valid 7 days, no credential needed. |
An actual response, recorded from the conformance suite.
{
"message": {
"id": "msg_2Hk9QpVn4tLd",
"user_id": "usr_7Fj3MnQw",
"route_id": "rte_4Bn8XcVm",
"direction": "inbound",
"from": {
"address": "ada@example.com",
"name": "Ada Lovelace"
},
"to": [
{
"address": "support@myapp.ai",
"name": "Support"
}
],
"from_addr": "ada@example.com",
"to_addr": "support@myapp.ai",
"subject": "Invoice question",
"text_body": "Could you resend invoice 4021?",
"html_body": null,
"headers_json": null,
"spf": "pass",
"dkim": "pass",
"dmarc": "pass",
"spam": null,
"thread_id": "msg_2Hk9QpVn4tLd",
"send_status": "sent",
"received_at": 1769731200000,
"size_bytes": 4821
},
"actor_email": null,
"actor_team_name": null,
"deliveries": [
{
"id": "dlv_6Kp2LsWq",
"message_id": "msg_2Hk9QpVn4tLd",
"route_id": "rte_4Bn8XcVm",
"url": "https://myapp.ai/hooks/mailkite",
"status": "delivered",
"attempts": 1,
"last_status_code": 200,
"created_at": 1769731200000,
"updated_at": 1769731201000
}
],
"events": [
{
"id": "evt_8Rt5NmZx",
"kind": "webhook.delivered",
"status": "ok",
"domain": "myapp.ai",
"route_id": "rte_4Bn8XcVm",
"message_id": "msg_2Hk9QpVn4tLd",
"delivery_id": "dlv_6Kp2LsWq",
"target": "https://myapp.ai/hooks/mailkite",
"code": 200,
"message": "delivered",
"created_at": 1769731201000
}
],
"deliveryAttempts": [
{
"id": "att_3Yh7GbFd",
"delivery_id": "dlv_6Kp2LsWq",
"message_id": "msg_2Hk9QpVn4tLd",
"attempt_number": 1,
"ok": 1,
"reason": null,
"response_status": 200,
"response_headers": null,
"response_body": null,
"duration_ms": 142,
"requested_at": 1769731201000,
"created_at": 1769731201000
}
],
"opens": [],
"attachments": [
{
"id": "att0",
"filename": "invoice-4021.pdf",
"contentType": "application/pdf",
"size": 20841,
"contentId": null,
"disposition": "attachment",
"url": "https://api.mailkite.dev/att/msg_2Hk9QpVn4tLd/0?exp=1770336000&sig=9f2c"
}
]
} {
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://api.mailkite.dev/v1/schemas/message-detail.json",
"title": "Message detail",
"description": "GET /api/messages/:id — the full message with its delivery history, pipeline events, per-attempt audit rows, recorded opens, and attachments.",
"type": "object",
"required": [
"message",
"actor_email",
"actor_team_name",
"deliveries",
"events",
"deliveryAttempts",
"opens",
"attachments"
],
"properties": {
"message": {
"$ref": "message.json",
"description": "The message itself, with bodies (text_body/html_body/headers_json) and without the list-row counters."
},
"actor_email": {
"type": [
"string",
"null"
],
"description": "When a team member sent this message as the domain owner: the acting member's email. null otherwise."
},
"actor_team_name": {
"type": [
"string",
"null"
],
"description": "When a team member sent this message as the domain owner: the team's name. null otherwise."
},
"deliveries": {
"type": "array",
"description": "Every webhook delivery of this message, newest last — retries and replays append.",
"items": {
"$ref": "delivery.json"
}
},
"events": {
"type": "array",
"description": "The pipeline timeline for this message (received → routed → webhook attempts → retries). Metadata only, never bodies.",
"items": {
"type": "object",
"required": [
"id",
"kind",
"status",
"created_at"
],
"properties": {
"id": {
"type": "string",
"description": "Event id (evt_…).",
"examples": [
"evt_8Rt5NmZx"
]
},
"kind": {
"type": "string",
"description": "Event kind (e.g. 'email.received', 'webhook.delivered', 'webhook.failed', 'webhook.test').",
"examples": [
"webhook.delivered"
]
},
"status": {
"type": "string",
"enum": [
"ok",
"fail",
"info"
],
"description": "Outcome facet."
},
"domain": {
"type": [
"string",
"null"
],
"description": "Domain the event belongs to."
},
"route_id": {
"type": [
"string",
"null"
],
"description": "Route involved, when any."
},
"message_id": {
"type": [
"string",
"null"
],
"description": "Message involved, when any."
},
"delivery_id": {
"type": [
"string",
"null"
],
"description": "Delivery involved, when any."
},
"target": {
"type": [
"string",
"null"
],
"description": "Webhook URL / forward address / recipient, when relevant."
},
"code": {
"type": [
"integer",
"null"
],
"description": "HTTP or provider status code, when relevant.",
"examples": [
200
]
},
"message": {
"type": [
"string",
"null"
],
"description": "Human-readable detail."
},
"created_at": {
"type": "integer",
"description": "When the event was recorded, in Unix epoch milliseconds (UTC).",
"examples": [
1769731200000
]
}
}
}
},
"deliveryAttempts": {
"type": "array",
"description": "Per-attempt audit rows (timing, response code/headers/body) behind the delivery inspector.",
"items": {
"type": "object",
"required": [
"id",
"delivery_id",
"message_id",
"attempt_number",
"ok",
"requested_at",
"created_at"
],
"properties": {
"id": {
"type": "string",
"description": "Attempt id (att_…).",
"examples": [
"att_3Yh7GbFd"
]
},
"delivery_id": {
"type": "string",
"description": "The delivery this attempt belongs to (dlv_…).",
"examples": [
"dlv_6Kp2LsWq"
]
},
"message_id": {
"type": "string",
"description": "The message delivered (msg_…).",
"examples": [
"msg_2Hk9QpVn4tLd"
]
},
"attempt_number": {
"type": "integer",
"description": "1-based attempt counter within the delivery.",
"examples": [
1
]
},
"ok": {
"type": "integer",
"enum": [
0,
1
],
"description": "1 when the attempt succeeded."
},
"reason": {
"type": [
"string",
"null"
],
"description": "Failure classification when not ok (e.g. 'http_5xx', 'timeout', 'no-ack')."
},
"response_status": {
"type": [
"integer",
"null"
],
"description": "HTTP status the endpoint returned.",
"examples": [
200
]
},
"response_headers": {
"type": [
"string",
"null"
],
"description": "Response headers as a JSON string."
},
"response_body": {
"type": [
"string",
"null"
],
"description": "Response body, truncated to ~4KB."
},
"duration_ms": {
"type": [
"integer",
"null"
],
"description": "Round-trip time of the attempt.",
"examples": [
142
]
},
"requested_at": {
"type": "integer",
"description": "When the attempt started, in Unix epoch milliseconds (UTC).",
"examples": [
1769731200000
]
},
"created_at": {
"type": "integer",
"description": "When the audit row was recorded, in Unix epoch milliseconds (UTC).",
"examples": [
1769731200000
]
}
}
}
},
"opens": {
"type": "array",
"description": "Recorded opens for an outbound message; empty when tracking was off or nothing was opened.",
"items": {
"type": "object",
"description": "One recorded open of an outbound message (present when open tracking was on). Machine opens (Apple MPP, Gmail proxy, scanners) are flagged so human counts stay meaningful."
}
},
"attachments": {
"type": "array",
"description": "Stored attachments with signed download URLs.",
"items": {
"type": "object",
"required": [
"id",
"filename",
"size",
"url"
],
"properties": {
"id": {
"type": "string",
"description": "Attachment id."
},
"filename": {
"type": "string",
"description": "Original filename.",
"examples": [
"invoice-4021.pdf"
]
},
"contentType": {
"type": [
"string",
"null"
],
"description": "MIME type.",
"examples": [
"application/pdf"
]
},
"size": {
"type": "integer",
"description": "Size in bytes.",
"examples": [
20841
]
},
"contentId": {
"type": [
"string",
"null"
],
"description": "MIME Content-ID for inline attachments."
},
"disposition": {
"type": [
"string",
"null"
],
"description": "'inline' or 'attachment'."
},
"url": {
"type": "string",
"description": "Signed, time-limited download URL — valid 7 days, no credential needed.",
"examples": [
"https://api.mailkite.dev/att/msg_2Hk9QpVn4tLd/0?exp=1770336000&sig=9f2c"
]
}
}
}
}
}
}