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

# Threads

> Understand how received emails are grouped into conversation threads. List, retrieve, and manage threads.

Threads group related messages into conversations. When a new message arrives, Nuntly automatically determines whether it belongs to an existing thread or starts a new one.

## Threading algorithm

Nuntly uses the following logic to match incoming messages to threads, evaluated in order:

1. **In-Reply-To header.** If the incoming message has an `In-Reply-To` header, Nuntly looks for a message in the same inbox with a matching `Message-ID`. If found, the new message joins that thread.
2. **References header.** If no match is found via `In-Reply-To`, Nuntly checks the `References` header for any matching `Message-ID` in the same inbox.
3. **Subject matching.** If no header match is found, Nuntly normalizes the subject line (stripping prefixes like `Re:` and `Fwd:`) and looks for a thread in the same inbox with a matching normalized subject that had activity within the last 7 days.
4. **New thread.** If none of the above produce a match, a new thread is created.

## List threads

You can list threads for a specific inbox. Filter by read status or spam flag.

```typescript theme={null}
import { Nuntly } from '@nuntly/sdk';

const nuntly = new Nuntly({
  apiKey: process.env.NUNTLY_API_KEY,
});

// List all threads in an inbox
const threads = await nuntly.inboxes.listThreads('ibx_01kabn43yqyxn2bx4ve84mczd3');

// Filter unread threads
const unreadThreads = await nuntly.inboxes.listThreads('ibx_01kabn43yqyxn2bx4ve84mczd3', {
  isRead: false,
});

// Filter spam threads
const spamThreads = await nuntly.inboxes.listThreads('ibx_01kabn43yqyxn2bx4ve84mczd3', {
  isSpam: true,
});
```

### Available filters

| Parameter | Description                                             |
| --------- | ------------------------------------------------------- |
| `isRead`  | Filter by read status (`true` or `false`).              |
| `isSpam`  | Filter by spam flag (`true` or `false`).                |
| `cursor`  | Cursor for pagination.                                  |
| `limit`   | Maximum number of results to return (1-30, default 30). |

### Thread fields

| Field           | Description                               |
| --------------- | ----------------------------------------- |
| `id`            | The unique thread identifier.             |
| `domainName`    | The domain name.                          |
| `inboxId`       | The inbox this thread belongs to.         |
| `subject`       | The original subject line.                |
| `lastMessageAt` | The timestamp of the most recent message. |
| `messageCount`  | The number of messages in the thread.     |
| `isRead`        | Whether the thread has been read.         |
| `isSpam`        | Whether the thread is marked as spam.     |
| `agentId`       | The AI agent identifier, or `null`.       |

## Retrieve a thread

Get the full details of a single thread. Retrieving a thread automatically marks it as read.

```typescript theme={null}
const thread = await nuntly.threads.retrieve('thr_01kabn43yqyxn2bx4ve84mczd3');

console.log('Subject:', thread.data.subject);
console.log('Messages:', thread.data.messageCount);
console.log('Last activity:', thread.data.lastMessageAt);
```

<Note>
  Retrieving a thread automatically sets `isRead` to `true`. If you need to mark it as unread again, use the update endpoint.
</Note>

## List thread messages

Retrieve the messages in a thread. Messages are returned in chronological order (oldest first).

```typescript theme={null}
const messages = await nuntly.threads.listMessages('thr_01kabn43yqyxn2bx4ve84mczd3');

for (const message of messages.data) {
  console.log(`${message.from.address}: ${message.subject}`);
}
```

## Update a thread

Update thread properties such as read status, spam flag, or agent assignment.

```typescript theme={null}
// Mark as unread
await nuntly.threads.update('thr_01kabn43yqyxn2bx4ve84mczd3', {
  isRead: false,
});

// Mark as spam
await nuntly.threads.update('thr_01kabn43yqyxn2bx4ve84mczd3', {
  isSpam: true,
});

// Assign an AI agent
await nuntly.threads.update('thr_01kabn43yqyxn2bx4ve84mczd3', {
  agentId: 'my-support-agent',
});
```

### Update request fields

| Field     | Description                                                 |
| --------- | ----------------------------------------------------------- |
| `isRead`  | Set to `true` or `false` to mark as read or unread.         |
| `isSpam`  | Set to `true` or `false` to mark as spam or not spam.       |
| `agentId` | The AI agent identifier. Set to `null` to remove the agent. |

## Next steps

<CardGroup cols={2}>
  <Card title="Messages" icon="envelope" href="/docs/guides/receiving-messages">
    Access message content, headers, and attachments
  </Card>

  <Card title="Send, reply, and forward" icon="reply" href="/docs/guides/receiving-send-reply">
    Respond to messages within threads
  </Card>
</CardGroup>
