Read and organize conversations
Find mailbox conversations, read their messages, and organize shared work with folders, labels, and internal notes.
Use this guide to find a conversation, read enough to act, and leave it organized for the next
person or agent. Start with an existing mailbox and a client authenticated for that mailbox.
Agents and keys explains access: reading needs read, and
changing threads or adding notes needs update. Creating or changing mailbox labels needs
mailbox management access.
Find the conversation
List threads in the inbox, optionally narrowing by search, label, or your own unread state. Thread lists return summaries with a subject, preview, sender, and current state, without message bodies.
import { createClient } from "samva";
const samva = createClient({ apiKey: process.env.SAMVA_API_KEY! });
const id = "mbx_...";
let cursor: string | undefined;
do {
const page = await samva.mailboxes.listThreads({
id,
folder: "inbox",
unread: "true",
cursor,
});
for (const thread of page.items) {
console.log(thread.id, thread.subject, thread.preview);
}
cursor = page.nextCursor ?? undefined;
} while (cursor !== undefined);Pass each page's nextCursor back as cursor until it is null. Threads are ordered by most
recent activity. A conversation that gains activity during a walk can move ahead of your cursor;
refresh the list to see new activity rather than treating a completed walk as a fixed snapshot.
For polling, after and before filter by last activity. See
list threads for the filters.
The inbox hides your snoozed threads by default. Pass snoozed: "true" to find threads you have
snoozed, or snoozed: "false" to exclude them explicitly from another view.
Read the messages
getThread gives you participants and thread state. listThreadMessages gives message summaries.
Use getThreadContent when you need bodies, or getMessage for one message.
const threadId = "mthr_...";
const thread = await samva.mailboxes.getThread({ id, threadId });
console.log(thread.subject, thread.participants);
let contentCursor: string | undefined;
do {
const page = await samva.mailboxes.getThreadContent({ id, threadId, cursor: contentCursor });
for (const message of page.items) {
console.log(message.id, message.replyText ?? message.text, message.attachments);
}
contentCursor = page.nextCursor ?? undefined;
} while (contentCursor !== undefined);Message summaries and content both paginate oldest first. Content includes text, sanitized
html, and replyText when available; replyText removes quoted history. Attachments are metadata,
not file bytes. Use get an attachment to
obtain a download URL and check its expiresAt before using it. See
read thread content for the full response.
Organize shared work and your own view
Folders, priority, and labels are shared with everyone on the mailbox. Your read, star, and snooze state belong to you: marking a thread read does not mark it read for another person or API key. Reading content and marking it read are separate actions.
await samva.mailboxes.updateThread({
id,
threadId,
folder: "pending",
priority: "high",
read: true,
starred: true,
});
// Wake a snoozed thread in your own view.
await samva.mailboxes.updateThread({ id, threadId, snoozedUntil: null });A partial update keeps fields you omit. To snooze, pass an ISO timestamp as snoozedUntil; the
thread wakes when that time passes. Archiving or moving to trash changes the shared folder.
See update a thread for the supported states.
Create a label once, then use its ID on any thread in that mailbox:
const label = await samva.mailboxes.createLabel({
id,
slug: "needs-follow-up",
displayName: "Needs follow-up",
});
await samva.mailboxes.addThreadLabels({ id, threadId, labels: [label.id] });Adding labels preserves existing labels. Use removeThreadLabels to remove selected labels;
updateThread does not replace them. A label must belong to the same mailbox. Deleting a label
removes it from every thread that carries it. See
create a label for mailbox label limits.
Leave context for the next reader
An internal note is visible to everyone on the mailbox and is never emailed to recipients.
await samva.mailboxes.createNote({
id,
threadId,
body: "Waiting for the customer to confirm the delivery address.",
pinned: true,
});Read notes with listThreadNotes, following nextCursor as with messages. Only a note's author
can edit or delete it. To answer the customer instead, follow
Compose and send.