# Threads API

List conversation threads and retrieve thread details with messages.

## GET /v1/mailboxes/:id/threads

**GET** `/v1/mailboxes/:id/threads`

List threads for a mailbox, sorted by most recent message. Returns the last 50 threads.

```response — 200 OK
{
  "threads": [
    {
      "id": "c3d4e5f6-789a-4bcd-ef01-333333333333",
      "mailboxId": "a1b2c3d4-5678-4def-abcd-111111111111",
      "subject": "Project update",
      "messageCount": 3,
      "lastMessageAt": "2026-03-11T14:00:00.000Z",
      "participants": ["myagent@robotomail.co", "recipient@example.com"],
      "createdAt": "2026-03-11T12:00:00.000Z"
    }
  ],
  "metadata": {
    "overLimitCount": 3,
    "upgrade": {
      "browserUrl": "https://robotomail.com/billing",
      "apiEndpoint": { "method": "POST", "path": "/v1/billing/upgrade" },
      "hint": "POST /v1/billing/upgrade for a programmatic checkout URL, or visit browserUrl to sign in and upgrade"
    },
    "limitHint": {
      "current": 80,
      "limit": 100,
      "percentage": 80,
      "reset_date": "2026-05-01T00:00:00.000Z",
      "status": "near"
    }
  }
}
```

**Inbound-limit gating.** Threads are ordered by their newest visible message, and per-thread `messageCount` / `lastMessageAt` reflect visible messages only — so hidden activity never leaks through the ordering or counters. Threads whose every message is over-limit are excluded entirely and counted in `metadata.overLimitCount` (the number of hidden messages, not threads). The field is `0` under normal operation. Upgrading the plan or the first-of-month reset unlocks every gated message in place. See [402 `INBOUND_LIMIT_EXCEEDED`](https://robotomail.com/docs/api/errors#inbound-limit-exceeded).

### Metadata envelope

- `overLimitCount` — number of hidden messages across the mailbox (0 under normal operation).
- `upgrade` — always present. Carries `browserUrl`, `apiEndpoint`, and a `hint` string for ending the quota block.
- `limitHint` — appears once monthly inbound usage reaches 50%. Snake-case shape (`current`, `limit`, `percentage`, `reset_date`, `status`) matching the `inbound_usage` block on webhook / SSE payloads. `status` is one of `approaching`, `near`, or `limit_reached`.


## GET /v1/mailboxes/:id/threads/:threadId

**GET** `/v1/mailboxes/:id/threads/:threadId`

Get a thread with all its messages, ordered chronologically (oldest first).

```response — 200 OK
{
  "thread": {
    "id": "c3d4e5f6-789a-4bcd-ef01-333333333333",
    "subject": "Project update",
    "messageCount": 3,
    "participants": ["myagent@robotomail.co", "recipient@example.com"],
    "messages": [
      {
        "id": "b2c3d4e5-6789-4abc-def0-222222222222",
        "direction": "OUTBOUND",
        "subject": "Project update",
        "bodyText": "Here is the latest...",
        "status": "DELIVERED",
        "createdAt": "2026-03-11T12:00:00.000Z"
      },
      {
        "id": "d4e5f6a7-89ab-4cde-f012-444444444444",
        "direction": "INBOUND",
        "subject": "Re: Project update",
        "bodyText": "Thanks for the update...",
        "status": "RECEIVED",
        "createdAt": "2026-03-11T13:00:00.000Z"
      }
    ]
  }
}
```

See [Threading](https://robotomail.com/docs/concepts/threading) for how messages are grouped into threads.

**Inbound-limit gating.** Over-limit messages are filtered from `messages`, and `messageCount` / `lastMessageAt` reflect visible messages only. If every message in the thread is over-limit, the endpoint returns `404` instead of an empty-thread husk. Upgrading the plan or the first-of-month reset unlocks every gated message in place — a subsequent call returns them with full content. See [402 `INBOUND_LIMIT_EXCEEDED`](https://robotomail.com/docs/api/errors#inbound-limit-exceeded).


---

Previous: [Messages](https://robotomail.com/docs/api/messages.md) | Next: [Webhooks](https://robotomail.com/docs/api/webhooks.md)
