Threads
A thread is an email conversation: a subject and the messages exchanged under it. Carom imports threads from every mailbox connected to your account, and a thread that reached several of your team’s mailboxes appears once, listing each mailbox it came through. Use this resource to find threads, read their messages, and keep track of which ones need attention.
Your key sees the threads your key’s user can see: those in mailboxes that user owns or has been given access to, and those shared with them. Read, flagged, resolved, and snoozed are kept per user, so marking a thread read through the API changes it for your key’s user and no one else.
#The thread object
Returned by List threads and Retrieve a thread. List responses leave messages empty and return tasks and comments as null; retrieving a single thread fills them in.
Attributes
-
idstring · uuidUnique identifier for the thread.
-
subjectstring · nullable -
snippetstring · nullableA short plain-text excerpt of the thread.
-
headlinestring · nullableA one-sentence summary written by Carom. Null until Carom has summarized the thread.
-
summarystring · nullableA longer summary of the whole thread, written by Carom. Null until Carom has summarized the thread.
-
message_countinteger · nullable -
has_attachmentsboolean · nullable -
readbooleanWhether your key’s user has read the thread. Change it with Mark a thread read.
-
flaggedbooleanWhether your key’s user has flagged the thread.
-
resolvedbooleanWhether your key’s user has marked the thread as dealt with. Resolved threads drop out of List open threads.
-
snooze_untilstring · date-time · nullableWhen your key’s user’s snooze on this thread ends. Null when the thread isn’t snoozed.
-
mailbox_idsarray of strings · uuidThe mailboxes the thread came through.
-
inbox_sort_timestring · date-time · nullableWhen the thread last received a message. The
inboxslice of List threads sorts by this. -
first_sent_atstring · date-time · nullable -
last_sent_atstring · date-time · nullableWhen the latest message was sent. The default sort for List threads.
-
participantsobjectEvery participant’s email address, mapped to the matching contact when one is visible to your key, otherwise to the display name from the message headers, or to null.
-
participant_namesobjectEvery participant’s email address, mapped to the display name from the message headers, or to null when the headers carried none.
-
messagesarray of objects · nullableThe messages visible to your key, oldest first. Empty in list responses. A message that reached only mailboxes your key can’t access is left out even when the thread itself is visible.
Show 10 child attributesHide child attributes
idstring · uuidsent_atstring · date-time · nullablefrom_email_addressstring · nullableto_email_addressesarray of stringscc_email_addressesarray of stringsparticipant_email_addressesarray of stringsEveryone on the message: sender and all recipients.
snippetstring · nullablesummarystring · nullableCarom’s summary of this message.
-
attachmentsarray of objects · nullableFiles attached to the message. Each links to a file you can download.
Show 8 child attributesHide child attributes
idstring · uuidfile_idstring · uuid · nullablefileobject · nullableThe file’s
id,name,file_name,extension, anddescription.content_typestring · nullablesizeinteger · nullableIn bytes.
inlineboolean · nullableTrue for images embedded in the message body.
content_idstring · nullableThe MIME
Content-IDthe HTML body uses to reference this attachment ascid:content_id.decorativebooleanTrue for a signature logo, a tracking pixel, or an image that appears only in quoted earlier messages, rather than a file someone meant to send. List files leaves these out by default.
-
bodyobject · nullableThe message content. Carom splits each body at the quote header of a reply, so you can show only what this message added.
Show 8 child attributesHide child attributes
source_formatstring · nullableWhether the original body was HTML or plain text.
htmlplainsanitized_htmlstring · nullableThe whole HTML body, including any quoted reply, with scripts and other unsafe markup removed. An inline image that matches one of this message’s
attachmentsbycontent_idhas itssrcset to/files/{file_id}/download?attachment_id={id}, a path on the API that needs your key; any othercid:reference is left unchanged. Null whensource_formatisplain.new_plain_textstring · nullableThe text this message added, above any quote header, as plain text.
new_htmlstring · nullableThe HTML this message added, above any quote header, sanitized and with inline images resolved as in
sanitized_html. Null whensource_formatisplain.quoted_plain_textstring · nullableThe earlier messages quoted below the quote header, as plain text.
quoted_htmlstring · nullableThe quoted part, sanitized and with inline images resolved as in
sanitized_html. Null whensource_formatisplain.has_quote_headerboolean · nullableWhether Carom found a quote header, such as “On Tuesday, Priya wrote:”, to split the body at.
truncatedbooleanTrue when the original body was too large for Carom to read in full. Every text and HTML field then holds only the beginning of the message.
-
tasksarray of tasks · nullableTasks attached to the thread that are visible to your key. Null in list responses.
-
commentsarray of comments · nullableYour team’s internal comments on the thread. Null in list responses.
-
tagsarray of tags · nullableTags applied to this thread.
-
sharesarray of shares · nullableWho this thread has been shared with, and how.
-
pending_messagesarray of objectsMessages your key’s user sent from Carom that haven’t synced back from the provider yet, oldest first. Each is a draft with status
sendingorsent, shown in message form, and drops out once the sent copy arrives in the thread. Queued and failed drafts don’t appear here. Empty in list responses.Show 14 child attributesHide child attributes
idstring · uuidThe draft’s id.
delivery_statusstringsendingwhile Carom hands the message to the provider,sentonce the provider has accepted it.sendingsentthread_idstring · uuid · nullablemailbox_idstring · uuid · nullablefrom_email_addressstring · nullableto_email_addressesarray of stringscc_email_addressesarray of stringsbcc_email_addressesarray of stringssubjectstring · nullablebodystring · nullablebody_htmlstring · nullablerfc_idstring · nullableThe message’s
Message-IDheader.created_atstring · date-time · nullablesent_atstring · date-time · nullable
{
"id": "7c2e9a14-5b3d-4f8e-9a61-3d0b8e2f4c57",
"subject": "Q4 renewal terms",
"snippet": "Thanks Dana. The 12-month term works for us if we can keep the current per-site rate.",
"headline": "Wildgrove accepts a 12-month renewal at the current rate",
"summary": "Dana proposed a 12-month renewal starting October 1. Priya agreed on the condition that the per-site rate stays the same and asked for the paperwork by September 15.",
"message_count": 4,
"has_attachments": true,
"read": true,
"flagged": true,
"resolved": false,
"snooze_until": null,
"mailbox_ids": ["d4e5f6a7-b8c9-4d0e-9f1a-2b3c4d5e6f70"],
"inbox_sort_time": "2026-09-04T21:17:09.332Z",
"first_sent_at": "2026-09-01T15:42:30.734Z",
"last_sent_at": "2026-09-04T21:17:09.332Z",
"participants": {
"priya@wildgrove.example": {
"id": "1f3c9a52-7b0e-4d4a-9c1e-2a6f0d8b3e41",
"name": "Priya Natarajan",
…
},
"dana@harborline.example": "Dana Whitfield"
},
"participant_names": {
"priya@wildgrove.example": "Priya Natarajan",
"dana@harborline.example": "Dana Whitfield"
},
"messages": [
{
"id": "5a1e3c7b-9d2f-4e6a-8b0c-7f3d1e5a9c26",
"sent_at": "2026-09-01T15:42:30.734Z",
"from_email_address": "dana@harborline.example",
"to_email_addresses": ["priya@wildgrove.example"],
"summary": "Dana proposes a 12-month renewal starting October 1.",
…
}
],
"tasks": [],
"comments": [],
"tags": [
{
"id": "0f1e2d3c-4b5a-4968-8776-655443322110",
"name": "Customer",
"color": "#66b185",
…
}
],
"shares": [],
"pending_messages": []
}
#List threads
Returns the threads visible to your key, 50 per page, most recently sent first. Narrow the list with a slice, a record it involves, text, state, dates, or tags, and page through the result with a cursor.
A contact_id, organization_id, or space_id that isn’t visible to your key returns record_not_found. A visible record with no email addresses returns an empty list.
Query parameters
-
slicestringA preset view, in terms of your key’s user.
inboxsorts by when threads last received a message instead oflast_sent_at.todaykeeps threads whose latest message was sent today, andworkweekthose sent since the start of this week, in that user’s time zone.unrepliedkeeps threads with no message sent from that user’s own email address.awaitingis the same asunreplied.snoozedkeeps threads whose snooze hasn’t ended.pinned-contactskeeps threads involving a contact that user has pinned.sharedkeeps threads shared directly with that user.flagged,unread,unresolved, andhas_attachmentmatch the boolean filters of the same names.inboxtodayworkweekflaggedunreadunrepliedawaitinghas_attachmentunresolvedsnoozedpinned-contactsshared -
scopestringpersonalkeeps threads in your key’s user’s primary mailbox;sharedkeeps threads shared with that user or one of their groups. Omit for no scope filter.personalshared -
mailbox_idstring · uuidOnly threads that came through this mailbox.
-
contact_idstring · uuidOnly threads involving one of this contact’s email addresses.
-
organization_idstring · uuidOnly threads involving someone employed at this organization.
-
space_idstring · uuidOnly threads that belong to this space, through its contacts and organizations or through its tags, depending on how the space is set up.
-
querystringMatch against subjects and snippets. Up to 500 characters.
-
subjectstringMatch against subjects only. Up to 500 characters.
-
participantstringAn email address that must be on the thread. Matched exactly, ignoring case.
-
categorystringThe provider’s classification of the thread. Gmail threads take their inbox category. Outlook threads are
personalwhen Focused Inbox puts them in Focused, andupdatewhen it puts them in Other.personalpromotionupdateforum -
unread,flagged,unresolved,has_attachmentbooleanWhen
true, keep only threads in that state for your key’s user.falseis the same as omitting the parameter. -
first_sent_beforestring · date-timeISO 8601. Only threads that started before this time.
-
last_sent_afterstring · date-timeISO 8601. Only threads with a message sent after this time.
-
tagsstringComma-separated tag ids, at most 50.
-
tag_operatorstringdefaultanyWhether a thread must carry any of the given tags, or all of them.
anyall -
next_cursorstringOpaque token from the previous page’s
page_info.next_cursor. Omit to start from the beginning. Theinboxslice sorts differently from the others, so a cursor from aninboxpage works only withinbox. See Pagination.
Returns
-
collectionobjectA page of threads and the cursor to the next one.
Show 4 child attributesHide child attributes
-
recordsarray of threadsUp to 50 threads, newest first.
-
page_infopage infoWhere this page sits in the full list. Pass
next_cursorback to fetch the next page whilehas_more_afteris true. -
slice_keystring · nullableThe
sliceyou asked for, echoed back. -
filtersobject · nullableThe filters that were applied, echoed back.
-
Errors
- 400
invalid_requestA parameter is malformed, for example an unknownslice, an id that isn’t a UUID, or a date that isn’t ISO 8601. - 400
invalid_cursorThe cursor is unreadable, or came from another list or sort. - 400
unsupported_cursor_directionYou sentprev_cursor. This list pages forward only. - 404
record_not_foundcontact_id,organization_id, orspace_idnames a record that isn’t visible to your key.
curl "https://api.carom.io/threads?slice=inbox&unread=true" \
-H "Authorization: Bearer $CAROM_API_KEY"
{
"collection": {
"records": [
{
"id": "2f8d4b61-9c0a-4e37-b5d2-8a1c6e9f3b04",
"subject": "Site walkthrough on the 22nd",
"read": false,
"inbox_sort_time": "2026-09-18T16:05:44.192Z",
"messages": [],
"tasks": null,
…
},
{
"id": "e4a7c1d9-3f52-4b8e-a0c6-5d9b2f7e1a38",
"subject": "Invoice 2026-0914 from Tallis Freight",
"read": false,
"inbox_sort_time": "2026-09-18T09:31:02.012Z",
"messages": [],
"tasks": null,
…
}
],
"page_info": {
"limit": 50,
"next_cursor": "c8Kq2vTnR4wLm7ZpX1dHsF9b",
"prev_cursor": null,
"has_more_after": true,
"has_more_before": false
},
"slice_key": "inbox",
"filters": {
"unread": true
}
}
}
#List open threads
Returns the threads that still need your key’s user’s attention: every thread visible to your key that received a message in the last 14 days and that user hasn’t resolved, including snoozed threads. They come in three groups: unread, read and flagged, and the rest. Returns every open thread in one response; the list isn’t paginated.
Entries are a shorter form of the thread object, without messages, participants, tasks, comments, tags, or shares. Order within a group isn’t guaranteed; sort by inbox_sort_time if you need a stable order.
Returns
-
inboxobjectShow 3 child attributesHide child attributes
unreadarray of objectsThreads your key’s user hasn’t read.
flaggedarray of objectsThreads that user has read and flagged.
otherarray of objectsThreads that user has read and not flagged.
Each entry has these attributes of the thread object: id, subject, snippet, headline, summary, message_count, has_attachments, read, flagged, resolved, snooze_until, mailbox_ids, inbox_sort_time, first_sent_at, and last_sent_at. It also has these:
-
categorystring · nullableAs on the
categoryfilter of List threads.personalpromotionupdateforum -
sender_email_addressesarray of stringsEveryone who has sent a message in the thread.
-
participant_email_addressesarray of stringsEveryone on the thread.
-
participant_namesobjectEvery participant’s email address, mapped to the display name from the message headers, or to null when the headers carried none.
curl https://api.carom.io/threads/open \
-H "Authorization: Bearer $CAROM_API_KEY"
{
"inbox": {
"unread": [
{
"id": "2f8d4b61-9c0a-4e37-b5d2-8a1c6e9f3b04",
"subject": "Site walkthrough on the 22nd",
"read": false,
"flagged": false,
"category": "personal",
"sender_email_addresses": ["priya@wildgrove.example"],
"inbox_sort_time": "2026-09-18T16:05:44.192Z",
…
}
],
"flagged": [
{
"id": "7c2e9a14-5b3d-4f8e-9a61-3d0b8e2f4c57",
"subject": "Q4 renewal terms",
"read": true,
"flagged": true,
…
}
],
"other": []
}
}
#Retrieve a thread
Returns a single thread with its messages, tasks, comments, and your key’s user’s pending sent messages. If some message bodies haven’t been downloaded yet, Carom fetches them from the provider before responding, so the first retrieval of an older thread can take longer.
Retrieving a thread doesn’t mark it read; read shows whether your key’s user has read it. To mark it read, use Mark a thread read.
Path parameters
-
idstring · uuidrequiredThe thread’s id.
Returns
The thread object, wrapped in thread.
Errors
- 404
record_not_foundNo thread with that id is visible to your key.
curl https://api.carom.io/threads/7c2e9a14-5b3d-4f8e-9a61-3d0b8e2f4c57 \
-H "Authorization: Bearer $CAROM_API_KEY"
{
"thread": {
"id": "7c2e9a14-5b3d-4f8e-9a61-3d0b8e2f4c57",
"subject": "Q4 renewal terms",
"read": true,
…
"messages": [
…
{
"id": "b8d2f6a0-4c1e-4a9b-9e3d-2c7f5a1b8e64",
"sent_at": "2026-09-04T21:17:09.332Z",
"from_email_address": "priya@wildgrove.example",
"to_email_addresses": ["dana@harborline.example"],
"cc_email_addresses": [],
"snippet": "Thanks Dana. The 12-month term works for us if we can keep the current per-site rate.",
"attachments": [
{
"id": "3e9b7d15-2a4c-4f6e-8d1b-9c5a3e7f2b40",
"file_id": "91c4e8a2-6d3b-4e7f-a5c9-0b2d4f6e8a13",
"file": {
"id": "91c4e8a2-6d3b-4e7f-a5c9-0b2d4f6e8a13",
"name": "Wildgrove site list",
"file_name": "wildgrove-sites-2026.xlsx",
"extension": "xlsx",
"description": null
},
"content_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"size": 48213,
"inline": false,
"content_id": null,
"decorative": false,
…
}
],
"body": {
"source_format": "html",
"new_plain_text": "Thanks Dana. The 12-month term works for us if we can keep the current per-site rate. Updated site list attached.",
"has_quote_header": true,
"truncated": false,
…
}
}
],
"tasks": [
{
"id": "e7f8a9b0-c1d2-4e3f-8a4b-5c6d7e8f9a01",
"description": "Send the Q4 renewal proposal",
"due": "2026-09-15",
…
}
],
"comments": [],
"pending_messages": []
}
}
#Count threads
Counts the threads that List threads would return for the same slice and filters, without fetching them. Counting stops at cap when you give one, which keeps the call fast on large mailboxes.
Query parameters
-
slice,scope,mailbox_id,contact_id,organization_id,space_id,query,subject,participant,category,unread,flagged,unresolved,has_attachment,first_sent_before,last_sent_after,tags,tag_operatorAs on List threads.
-
capintegerStop counting at this many. When the cap is reached,
totalequalscapandexactis false.
Returns
-
countcount resultShow 4 child attributesHide child attributes
totalintegerexactbooleanFalse when counting stopped at
cap.cappedbooleancapinteger · nullableThe cap that applied, or null.
Errors
- 400
invalid_requestA parameter is malformed, for example an unknownsliceor an id that isn’t a UUID. - 404
record_not_foundcontact_id,organization_id, orspace_idnames a record that isn’t visible to your key.
curl "https://api.carom.io/threads/count?unread=true&cap=500" \
-H "Authorization: Bearer $CAROM_API_KEY"
{
"count": {
"total": 37,
"exact": true,
"capped": false,
"cap": 500
}
}
#Flag a thread
Flags the thread for your key’s user. Flagging a thread that is already flagged succeeds and changes nothing.
If your key’s user owns a mailbox the thread came through and that mailbox has label_sync on, Carom also flags the thread at the provider (a star, in Gmail) shortly after the request returns.
Path parameters
-
thread_idstring · uuidrequired
Returns
The ok object, {"ok": "ok"}.
Errors
- 404
record_not_foundNo thread with that id is visible to your key.
curl -X POST https://api.carom.io/threads/7c2e9a14-5b3d-4f8e-9a61-3d0b8e2f4c57/flag \
-H "Authorization: Bearer $CAROM_API_KEY"
{ "ok": "ok" }
#Unflag a thread
Removes your key’s user’s flag from the thread. Unflagging a thread that isn’t flagged succeeds and changes nothing. With label_sync on, Carom removes the flag at the provider as well.
Path parameters
-
thread_idstring · uuidrequired
Returns
An empty response with status 204.
Errors
- 404
record_not_foundNo thread with that id is visible to your key.
curl -X DELETE https://api.carom.io/threads/7c2e9a14-5b3d-4f8e-9a61-3d0b8e2f4c57/flag \
-H "Authorization: Bearer $CAROM_API_KEY"
No content
#Mark a thread read
Marks the thread read for your key’s user. If your key’s user owns a mailbox the thread came through and that mailbox has label_sync on, Carom also marks it read at the provider, shortly after the request returns.
Path parameters
-
thread_idstring · uuidrequired
Returns
The ok object, {"ok": "ok"}.
Errors
- 404
record_not_foundNo thread with that id is visible to your key.
curl -X POST https://api.carom.io/threads/2f8d4b61-9c0a-4e37-b5d2-8a1c6e9f3b04/read \
-H "Authorization: Bearer $CAROM_API_KEY"
{ "ok": "ok" }
#Mark a thread unread
Marks the thread unread for your key’s user, and at the provider when label_sync applies.
Path parameters
-
thread_idstring · uuidrequired
Returns
An empty response with status 204.
Errors
- 404
record_not_foundNo thread with that id is visible to your key.
curl -X DELETE https://api.carom.io/threads/2f8d4b61-9c0a-4e37-b5d2-8a1c6e9f3b04/read \
-H "Authorization: Bearer $CAROM_API_KEY"
No content
#Resolve a thread
Marks the thread as dealt with for your key’s user. A resolved thread leaves List open threads and the unresolved filter of List threads. Resolution is kept in Carom only; nothing changes at the provider.
Path parameters
-
thread_idstring · uuidrequired
Returns
The ok object, {"ok": "ok"}.
Errors
- 404
record_not_foundNo thread with that id is visible to your key.
curl -X POST https://api.carom.io/threads/7c2e9a14-5b3d-4f8e-9a61-3d0b8e2f4c57/resolution \
-H "Authorization: Bearer $CAROM_API_KEY"
{ "ok": "ok" }
#Reopen a thread
Removes your key’s user’s resolution from the thread, so it counts as open again.
Path parameters
-
thread_idstring · uuidrequired
Returns
An empty response with status 204.
Errors
- 404
record_not_foundNo thread with that id is visible to your key.
curl -X DELETE https://api.carom.io/threads/7c2e9a14-5b3d-4f8e-9a61-3d0b8e2f4c57/resolution \
-H "Authorization: Bearer $CAROM_API_KEY"
No content
#Snooze a thread
Snoozes the thread for your key’s user until a given time. The thread shows the time as snooze_until and appears in the snoozed slice of List threads until then. Snoozing doesn’t remove the thread from other lists. Snoozing a thread that is already snoozed replaces the old time.
Path parameters
-
thread_idstring · uuidrequired
Request body application/json
-
snooze_untilstringrequiredAn ISO 8601 timestamp, or one of the shortcuts below, which use your key’s user’s time zone.
soonis three hours from now, on the hour;tonightis 19:00 today, or halfway between now and midnight when it’s already 17:00 or later;morningis 8:00 tomorrow;weekendis 8:00 on the coming Saturday;weekis 8:00 next Monday;monthis 8:00 on the same date next month. Send a timestamp when the exact time matters.soontonightmorningweekendweekmonth
Returns
-
threadobjectShow 1 child attributeHide child attributes
snooze_untilstring · date-timeWhen the snooze ends. A timestamp you sent is echoed as you sent it.
Errors
- 400
invalid_requestsnooze_untilis missing or empty. - 404
record_not_foundNo thread with that id is visible to your key.
curl https://api.carom.io/threads/7c2e9a14-5b3d-4f8e-9a61-3d0b8e2f4c57/snooze \
-H "Authorization: Bearer $CAROM_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "snooze_until": "2026-09-22T15:00:00.000Z" }'
{
"thread": {
"snooze_until": "2026-09-22T15:00:00.000Z"
}
}
#Unsnooze a thread
Ends your key’s user’s snooze on the thread now. Unsnoozing a thread that isn’t snoozed succeeds and changes nothing.
Path parameters
-
thread_idstring · uuidrequired
Returns
An empty response with status 204.
Errors
- 404
record_not_foundNo thread with that id is visible to your key.
curl -X DELETE https://api.carom.io/threads/7c2e9a14-5b3d-4f8e-9a61-3d0b8e2f4c57/snooze \
-H "Authorization: Bearer $CAROM_API_KEY"
No content