---
title: "GET /email/{id}"
method: GET
path: "/email/{id}"
---

# GET /email/{id}

`GET /email/{id}`

## Request

- Base URL: `https://api.useanima.sh/v1`
- URL: `https://api.useanima.sh/v1/email/{id}`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

## Path parameters

- `id` string, required: Unique email message identifier

## Response `200`

OK

- object: Full message resource representation
  - `id` string, required: Unique identifier of the message
  - `agentId` string, required: ID of the agent that sent or received the message
  - `inboxId` string, nullable, required: ID of the inbox this message belongs to — the inbox it was delivered to (inbound) or sent from (outbound). Null when no inbox backs the address: SMS/MMS/voice messages, and email sent from an email identity that has no inbox (such as a custom-domain identity added to an agent). Pass it to GET /messages?inboxId= to list one inbox's mail.
  - `channel` 'EMAIL' | 'SMS' | 'MMS' | 'VOICE' | 'WHATSAPP' | 'RCS', required: Communication channel used
  - `direction` 'INBOUND' | 'OUTBOUND', required: Whether the message was inbound or outbound
  - `status` 'QUEUED' | 'SENT' | 'DELIVERED' | 'FAILED' | 'BOUNCED' | 'BLOCKED' | 'PENDING_APPROVAL', required: Current delivery status
  - `fromAddress` string, required: Sender address (email or phone number)
  - `toAddress` string, required: Recipient address (email or phone number)
  - `subject` string, nullable, required: Message subject line, or null for channels that do not support subjects
  - `body` string, required: Plain-text content of the message
  - `bodyHtml` string, nullable, required: HTML content of the message, or null if not available
  - `extractedText` string, nullable, required: Plain-text body with the quoted reply chain and signature stripped — just what this sender actually wrote. Read this instead of `body` to avoid re-reading (and paying for) the whole thread on every message. Null when nothing was extracted: non-email channels, messages your agent sent, and mail received before this field existed — so `extractedText ?? body` is always correct. Best-effort and heuristic; `body` remains the verbatim source of truth. Known weak cases: forwards and bottom-posted replies have no separable 'new' part, so this returns the full body rather than nothing.
  - `extractedHtml` string, nullable, required: HTML body with quoted reply chains removed. Same semantics as `extractedText`; `bodyHtml` stays verbatim. Quoting styles that mark the chain with a sibling element rather than wrapping it (Outlook) are not stripped here — `extractedText` still is.
  - `headers` object, nullable, required: Raw message headers as key-value pairs, or null
  - `metadata` object, nullable, required: Arbitrary metadata attached to the message, or null
  - `threadId` string, nullable, required: Thread identifier for conversation grouping, or null
  - `labels` string[], required: Workflow labels on this message. Always contains exactly one of the system labels `unread` or `read`; may also contain `archived`, `spam` (the inbound spam verdict — see `includeSpam` on list/search), and any labels you add yourself. Stored lowercase, deduped, and sorted. Change them with PATCH /messages/{id}/labels.
  - `inReplyTo` string, nullable, required: Message ID this message is replying to, or null
  - `externalId` string, nullable, required: External identifier, or null. For email: the RFC 5322 Message-ID (bare, no angle brackets) — pass it as inReplyTo to reply in-thread. For SMS: the provider-assigned message id.
  - `deletedAt` string, date-time, nullable, required: When this message was moved to Trash, or null if it is live. Deleted messages are hidden from listings unless `deleted` is set to `include` or `only`, and can be brought back with POST /messages/{id}/restore. Nothing purges them.
  - `sentAt` string, date-time, nullable, required: Timestamp when the message was sent, or null if not yet sent
  - `receivedAt` string, date-time, nullable, required: Timestamp when the message was received, or null for outbound messages
  - `readAt` string, date-time, nullable, required: Outbound WhatsApp and RCS messages only: when the recipient's device reported the message as read. Null for inbound messages and for every other channel. Unrelated to the read and unread labels, which record whether the agent has handled a message.
  - `attachments` object[], required: File attachments associated with this message
    - `id` string, required: Unique identifier of the attachment
    - `filename` string, required: Original filename of the attachment
    - `mimeType` string, required: MIME type of the attachment (e.g. application/pdf)
    - `sizeBytes` integer, required: File size in bytes
    - `storageKey` string, required: Internal storage key for retrieving the file
    - `url` string, uri, nullable, required: Pre-signed download URL, or null if not yet generated
    - `createdAt` string, date-time, required: Timestamp when the attachment was created
    - `scanStatus` 'PENDING' | 'CLEAN' | 'FLAGGED' | 'BLOCKED', required: Content-scan verdict. BLOCKED attachments cannot be downloaded — inspect before fetching bytes.
    - `detectedMimeType` string, nullable, required: MIME type inferred from magic bytes; may differ from the declared mimeType
  - `createdAt` string, date-time, required: Timestamp when the message record was created
  - `updatedAt` string, date-time, required: Timestamp when the message record was last updated

---

[API](https://skmtc.dev/useanima/apis/anima-api.md) · [All operations](https://skmtc.dev/useanima/apis/anima-api/llms.txt) · [OpenAPI document](https://skmtc.dev/useanima/apis/anima-api/revisions/aaa148188980?raw)
