import { createClient } from "@mailsai/sdk";
const client = createClient(); // reads MAILS_API_KEY
const result = await client.threads.update(
"thrd_01JZX8K3M9Q4P7VN2YB6RTDC0E",
{
status: "closed",
labels: ["resolved", "shipping"],
},
);
console.log(result);from mailsai import create_client
client = create_client() # reads MAILS_API_KEY
result = client.update_thread(
"thrd_01JZX8K3M9Q4P7VN2YB6RTDC0E",
status="closed",
labels=["resolved", "shipping"],
)
print(result)curl -X PATCH 'https://api.mails.ai/v1/threads/thrd_01JZX8K3M9Q4P7VN2YB6RTDC0E' \
-H "Authorization: Bearer $MAILS_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"status": "closed",
"labels": ["resolved", "shipping"]
}'mails threads update thrd_01JABC --status closed \
--labels resolved,shipping{
"name": "mails_threads_update",
"arguments": {
"thread_id": "thrd_01JZX8K3M9Q4P7VN2YB6RTDC0E",
"labels": ["resolved", "shipping"],
"status": "closed"
}
}{
"id": "thrd_01JZX8K3M9Q4P7VN2YB6RTDC0E",
"agent_id": "agt_01JZX8K3M9Q4P7VN2YB6RTDC0E",
"subject": "<subject>",
"root_message_id": "msg_01JZX8K3M9Q4P7VN2YB6RTDC0E",
"last_message_id": "msg_01JZX8K3M9Q4P7VN2YB6RTDC0E",
"last_message_at": "2026-10-04T12:00:00.000Z",
"message_count": 0,
"participants": ["jordan@example.com"],
"labels": ["<labels>"],
"label_ids": ["lbl_01JZX8K3M9Q4P7VN2YB6RTDC0E"],
"status": "open",
"read": false,
"folder": "inbox",
"trashed_at": "2026-10-04T12:00:00.000Z",
"test_mode": false,
"created_at": "2026-10-04T12:00:00.000Z",
"updated_at": "2026-10-04T12:00:00.000Z"
}200 The updated thread (no messages array).
400 Invalid request — malformed JSON or a field failed
validation. Also feature_not_enabled when this
server has a feature switched off (custom domains
before they are available).
401 Missing or invalid API key.
403 The API key lacks the required scope
(insufficient_scope), or the token belongs to an
app connected by sign-in and this operation is
closed to connected apps
(connected_app_not_allowed).
404 Resource not found in this workspace, or the agent
a send names is archived (agent_archived).
422 Unprocessable — agent paused, recipient suppressed,
a recipient at test.mails.ai other than
reply@test.mails.ai (unknown_test_address), or
abuse guard.
500 Internal server error.Update a thread
read, folder, status, labels and label_ids; emits thread.updated when something changed.import { createClient } from "@mailsai/sdk";
const client = createClient(); // reads MAILS_API_KEY
const result = await client.threads.update(
"thrd_01JZX8K3M9Q4P7VN2YB6RTDC0E",
{
status: "closed",
labels: ["resolved", "shipping"],
},
);
console.log(result);from mailsai import create_client
client = create_client() # reads MAILS_API_KEY
result = client.update_thread(
"thrd_01JZX8K3M9Q4P7VN2YB6RTDC0E",
status="closed",
labels=["resolved", "shipping"],
)
print(result)curl -X PATCH 'https://api.mails.ai/v1/threads/thrd_01JZX8K3M9Q4P7VN2YB6RTDC0E' \
-H "Authorization: Bearer $MAILS_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"status": "closed",
"labels": ["resolved", "shipping"]
}'mails threads update thrd_01JABC --status closed \
--labels resolved,shipping{
"name": "mails_threads_update",
"arguments": {
"thread_id": "thrd_01JZX8K3M9Q4P7VN2YB6RTDC0E",
"labels": ["resolved", "shipping"],
"status": "closed"
}
}{
"id": "thrd_01JZX8K3M9Q4P7VN2YB6RTDC0E",
"agent_id": "agt_01JZX8K3M9Q4P7VN2YB6RTDC0E",
"subject": "<subject>",
"root_message_id": "msg_01JZX8K3M9Q4P7VN2YB6RTDC0E",
"last_message_id": "msg_01JZX8K3M9Q4P7VN2YB6RTDC0E",
"last_message_at": "2026-10-04T12:00:00.000Z",
"message_count": 0,
"participants": ["jordan@example.com"],
"labels": ["<labels>"],
"label_ids": ["lbl_01JZX8K3M9Q4P7VN2YB6RTDC0E"],
"status": "open",
"read": false,
"folder": "inbox",
"trashed_at": "2026-10-04T12:00:00.000Z",
"test_mode": false,
"created_at": "2026-10-04T12:00:00.000Z",
"updated_at": "2026-10-04T12:00:00.000Z"
}200 The updated thread (no messages array).
400 Invalid request — malformed JSON or a field failed
validation. Also feature_not_enabled when this
server has a feature switched off (custom domains
before they are available).
401 Missing or invalid API key.
403 The API key lacks the required scope
(insufficient_scope), or the token belongs to an
app connected by sign-in and this operation is
closed to connected apps
(connected_app_not_allowed).
404 Resource not found in this workspace, or the agent
a send names is archived (agent_archived).
422 Unprocessable — agent paused, recipient suppressed,
a recipient at test.mails.ai other than
reply@test.mails.ai (unknown_test_address), or
abuse guard.
500 Internal server error.Path Parameters
Thread id.
Body Parameters
Label names, up to 50, each at most 64 characters. Replaces the thread's labels. Any such name works; a name that matches a label object picks up its id and colour.
Label object ids (lbl_…). Replaces the thread's labels with those labels' names. Sent together with labels, the thread gets both.
"archived" also files the thread in archive; "open" or "closed" on an archived thread moves it back to the inbox.
Mark the thread read (true) or unread (false).
Move the thread to inbox, archive, spam or trash. archive also sets status "archived", and moving an archived thread anywhere else reopens it. sent cannot be chosen (422): a thread is filed there while every message in it is one you sent. A thread in trash is deleted for good 30 days after it was moved there.
folder: "archive" and status: "archived" move together, and moving an archived thread anywhere else reopens it. folder: "sent" is a 422: a thread is filed there while every message in it is one the agent sent. So is status: "archived" with any folder but archive. A test key cannot move a thread holding live mail to trash (403 live_mode_required).
Response
Thread id (thrd_…).
Id (agt_…) of the agent the thread belongs to; a thread holds one agent's mail only.
The subject of the thread's first message, without one leading Re:, Fwd: or Fw:. Empty when that message had no subject.
Id of the message that started the thread: msg_… for one the agent sent, rcv_… for one it received.
Id of the message that joined the thread most recently (msg_… or rcv_…).
When the latest message joined the thread. The thread list is ordered by it, newest first.
How many messages have joined the thread, sent and received.
Every address the thread has involved, in lower case and without repeats: the agent's own, the senders of received mail and the recipients of sent mail.
Label names, up to 50, each at most 64 characters. Any such name works; names that match a label object also appear in label_ids.
Ids (lbl_…) of the label objects whose names are on this thread.
open (every new thread), closed or archived, changed with PATCH. archived goes with folder archive, and only an open thread takes in new mail matched by its subject (mail from someone already in the thread).
False once new mail arrives; set it with PATCH.
inbox, archive, spam, trash or sent. archive goes with status archived. sent holds a thread whose messages are all ones the agent sent, until a reply moves it to the inbox. Threads in trash are deleted for good 30 days after they were trashed.
When the thread was moved to trash. Present only while it is there.
True when the thread holds no live mail: every message in it was sent with a test key (mk_test_…) or delivered through POST /v1/test/inbound. A thread with any live message is live. Its thread.* events carry the same test_mode, and GET /v1/threads lists a key's own mode unless mode says otherwise.
When the thread was created, with its first message.
When the thread last changed: a message joined it, or its read state, folder, status or labels changed.
Was this page helpful?