---
title: "Get the conversation an email belongs to"
method: GET
path: "/emails/{id}/conversation"
tags: ["Emails"]
---

# Get the conversation an email belongs to

`GET /emails/{id}/conversation`

Returns the full conversation the given inbound email belongs
to, as ordered, ready-to-prompt turns WITH bodies. It resolves
the thread from the email and returns every message oldest-first,
so an agent that received an email can pass `messages` straight
to a chat model in one call instead of walking `/threads/{id}`
plus `/emails/{id}` and `/sent-emails/{id}` per message.

Each message carries a `direction` (`inbound` | `outbound`) and a
derived `role`: `inbound` -> `user`, `outbound` -> `assistant`
(your own prior replies). The role mapping assumes the caller
owns the outbound side, which is the agent-reply case this exists
for. If the email has no thread yet (a brand-new message), the
conversation is just that one message as a single user turn.

The message list is capped; check `truncated` to detect when
older messages were omitted. Consecutive same-role turns are not
merged here; that normalization is model-specific and left to the
caller.

## Response `200`

Conversation

- object
  - `success` true, required
  - `data` object, required — The full conversation an inbound email belongs to, as ordered, ready-to-prompt turns with bodies. Resolves the thread from the email and returns every message oldest-first, so an agent that received an email can pass `messages` straight to a chat model in one call.
    - `thread_id` string, uuid, nullable, required — The thread this email belongs to, or null when the email isn't threaded yet (the conversation is then just this one message).
    - `subject` string, nullable — Normalized thread subject (Re/Fwd prefixes stripped), or the email's own subject when it isn't threaded.
    - `message_count` integer, required — Total messages in the thread. `messages` is capped, so `truncated` is true (and this can exceed `messages.length`) when older messages were omitted.
    - `truncated` boolean, required — True when `messages` omits part of the conversation because the thread exceeds the per-call cap.
    - `messages` object[], required
      - `role` 'user' | 'assistant', required — Chat role derived from `direction`: `user` for inbound (received) messages, `assistant` for outbound (your own prior replies). Lets `messages` be passed directly to a chat model.
      - `direction` 'inbound' | 'outbound', required — `inbound` for a received email (`/emails/{id}`), `outbound` for a send (`/sent-emails/{id}`).
      - `id` string, uuid, required
      - `message_id` string, nullable
      - `from` string, nullable
      - `to` string, nullable
      - `subject` string, nullable
      - `text` string, required — Plain-text body. Empty string when the message has no text part or its content was discarded by retention.
      - `timestamp` string, date-time, nullable — received_at for inbound, created_at for outbound.

## Other responses

- `400` — Invalid request parameters
- `401` — Invalid or missing API key
- `404` — Resource not found

---

[API](https://skmtc.dev/primitive/apis/primitive-api.md) · [All operations](https://skmtc.dev/primitive/apis/primitive-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/primitive/primitive-api/revisions/c2299d28022c/schema)
