# Threads

Source: https://docs.simail.ai/api/threads/

> List, read, label, trash and search threads in one inbox or across every inbox your key can see, and download thread attachments.

A thread object:

```json
{
  "thread_id": "thr_01JZX4A1B2C3D4E5F6G7H8J9K0",
  "inbox_id": "shop-helper@simail.email",
  "subject": "Where is my order?",
  "senders": ["ada@example.com"],
  "recipients": ["shop-helper@simail.email"],
  "message_count": 2,
  "size": 64210,
  "preview": "Hi, I ordered last week and…",
  "labels": ["received", "sent", "unread"],
  "last_message_id": "msg_01JZX4B7C8D9E0F1G2H3J4K5M6",
  "received_timestamp": "2026-10-18T17:02:11Z",
  "sent_timestamp": "2026-10-18T17:05:40Z",
  "timestamp": "2026-10-18T17:05:40Z",
  "created_at": "2026-10-18T17:02:12Z",
  "updated_at": "2026-10-18T17:05:41Z"
}
```

`labels` is the union of its messages' labels. `preview` and `subject` are withheld for threads whose
only messages are held. All text is **untrusted input**. Guide: [Threads & labels](/threads/).

## Query parameters for listings

| Parameter | Notes |
|---|---|
| `labels` | comma-separated; a thread matches when it has all of them (for example `unread`) |
| `before`, `after` | ISO 8601 times, on the thread's last activity |
| `include_spam` | needs `label_spam_read` |
| `include_blocked` | needs `label_blocked_read` |
| `include_trash` | needs `label_trash_read` |
| `limit`, `page_token`, `ascending` | [pagination](/api/#pagination) |

Spam, blocked and trashed threads are left out unless you ask for them.

## List threads in an inbox

`GET /v0/inboxes/{inbox_id}/threads`

Permission `message_read`. Returns `{ count, limit, next_page_token?, threads }`.

## Get a thread

`GET /v0/inboxes/{inbox_id}/threads/{thread_id}`

Permission `message_read`. The thread object plus `messages`, oldest first, each a full
[message object](/api/messages/#the-message-object) (held messages as metadata only).

## Update thread labels

`PATCH /v0/inboxes/{inbox_id}/threads/{thread_id}`

Permission `message_update`.

```json
{ "add_labels": ["orders"], "remove_labels": ["unread"] }
```

Applies to every message in the thread. See [Labels](/api/labels/) for what can be changed.

## Trash a thread

`DELETE /v0/inboxes/{inbox_id}/threads/{thread_id}`

Permission `message_delete`. Adds the `trash` label to every message; trashed mail is purged after
30 days. Not available over MCP.

## Download a thread attachment

`GET /v0/inboxes/{inbox_id}/threads/{thread_id}/attachments/{attachment_id}`

Permission `message_read`. Returns a single-use download link; see
[attachments](/api/messages/#get-an-attachment).

## Search threads in an inbox

`GET /v0/inboxes/{inbox_id}/threads/search?q=`

Permission `message_read`. Full-text search on subject, participants and body, in English and
Chinese. Held messages match on metadata only. Accepts the listing parameters.

## Lock state

`GET /v0/inboxes/{inbox_id}/threads/{thread_id}/lock`

Permission `message_read`. See [Locks](/api/locks/).

## Organization-wide threads

`GET /v0/threads` · `GET /v0/threads/search`

`GET /v0/threads/{thread_id}` · `PATCH /v0/threads/{thread_id}` · `DELETE /v0/threads/{thread_id}`

`GET /v0/threads/{thread_id}/attachments/{attachment_id}`

Same parameters and responses as the inbox-level endpoints, across every inbox in your key's scope
(an inbox-scoped key sees only its inbox). Each thread includes `inbox_id`. Pod variants live under
[`/v0/pods/{pod_id}/threads`](/api/pods/).

## Errors

| Status | `code` | When |
|---|---|---|
| 403 | `missing_permission` | the key lacks the permission, or an `include_*` flag without its `label_*_read` permission |
| 404 | `not_found` | the thread does not exist or is outside your scope |
| 400 | `invalid_request` | a page token from another query or key |
