> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lupin.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Threads

> Conversations with labels, search and filters.

# Threads

`GET /v0/emails/threads` (org) · `/v0/emails/inboxes/:inbox_id/emails/threads…` ·
`/v0/projects/:project_id/threads…`, plus `GET …/search`.

## List & filter

```
GET /v0/emails/inboxes/:inbox_id/emails/threads?labels=vip&senders=user@&before=…&after=…&ascending=
```

Substring filters: `senders`, `recipients`, `subject` (repeatable, AND).
Gated labels (`spam`, `trash`, `blocked`, `unauthenticated`) are hidden unless
the key holds the matching `label_*_read` permission; `include_spam=false` etc.
force-exclude them.

## Search

```
GET /v0/emails/inboxes/:inbox_id/emails/threads/search?q=vip+renewal
```

Matches senders/recipients/subject (substring) plus tokenized bodies, ranked
by relevance. Gated labels are always excluded. `limit` ≤ 100.

## Labels

`PATCH /v0/emails/inboxes/:inbox_id/emails/threads/:thread_id`:

```json theme={null}
{ "add_labels": ["vip"], "remove_labels": ["new"] }
```

System labels (`sent`, `received`, `bounced`, `spam`, `trash`, `blocked`, …)
cannot be added or removed — 400. Threads with 100+ messages reject relabeling
(422). Every change records a `label.added` / `label.removed` inbox event.

`GET` returns the thread with `messages[]` ascending.
`DELETE` removes the thread and all its messages.
