Conversaciones
Cada operación de este grupo: lo que acepta, lo que devuelve y los errores con los que puede responder.
Operaciones
GET/threads
List threads in a folder
Reads the local index. Passing query searches that same index.
Plain words must all appear, and each one matches loosely: case, accents and separators are ignored and part of a longer word counts, so min and ben jamin both find "Benjamin". A quoted phrase is matched as written apart from case and accents, so its separators have to line up: "ben jamin" does not find "Ben-Jamin", while "quarterly invoice" finds "Quarterly invoice". When nothing matches exactly, close spellings are returned instead, so benjimin finds "Benjamin": a plain word, or the value of from:, to:, cc:, subject:, body:, filename: or label:, may differ from the start of a word by one typo (a changed, missing, extra or swapped letter) when it has four to seven letters and by two when it has eight or more, while a quoted phrase, a word containing a digit, a shorter word and an excluded word still match exactly, and the pages that follow keep matching the same way. Filler words are dropped from a list of plain words when something else is left to search for, so mail server searches for server alone and emails from john searches for john. The filler is a, an, the, and, or, of, to, from, for, about, with, in, on, at, by, my, me, all, any, some, show, find, get, email, emails, mail, mails, message, messages, thread and threads, and it is kept when dropping it would leave nothing but a single letter.
Operators narrow the search: from:, to:, cc:, subject:, body:, label:, filename:, in: (inbox, sent, drafts, spam, trash, archive, snoozed, anywhere or a label name), is: (unread, read, starred, important, snoozed, muted, draft, sent), has: (attachment, pdf, image, video, audio, document, spreadsheet, presentation, userlabels, nouserlabels), after:YYYY/MM/DD, before:YYYY/MM/DD, newer_than:7d and older_than:1y (units h, d, w, m, y). Combine them with OR, AND, NOT, parentheses, braces for a set of alternatives ({stripe paddle}) and a leading - to exclude. Recipients are stored as one list without roles and never hold a Bcc, so cc: reads the same field as to: and bcc: matches nothing of its own. from:me is mail you sent, and to:me is mail carrying one of your own addresses, aliases included, among its recipients or as the address it was delivered to.
A value the search cannot use is ignored rather than narrowing, so a typo in a value widens the result instead of emptying it. Ignored: category:, larger:, smaller:, size:, messagesize:, list:, rfc822msgid:, received:, sent:, the category words (is:primary, is:personal, is:social, is:promotions, is:updates, is:forums, is:reservations, is:purchases), a has: word that names none of the kinds above, an importance: other than high or low, a date that cannot be read, and a duration whose unit is not h, d, w, m or y. An operator name it does not know, project: for instance, is searched as plain text instead.
Words and the from:, to:, cc:, subject: and body: operators read only the newest message on each thread: its sender, its recipients, its subject and the first 4,000 characters of its body. filename: and has: read every attachment on the whole conversation, and label:, in: and is: read the whole conversation. A plain word also matches the name of any attachment on the conversation, whichever message carried it. A message that arrived encrypted has no body text to match. folder still applies unless the query names one with in:, or with an is: that is a folder such as is:sent, and in:anywhere searches every folder, on its own as well as beside other terms. A drafts listing is the exception: GET /drafts and GET /threads?folder=draft stay in drafts whatever the query names.
Dates read the newest activity on the thread, in UTC. after: includes the day it names and before: excludes it. A date can be written YYYY/MM/DD, YYYY-MM-DD, YYYYMMDD, as a bare year, or as epoch seconds or milliseconds; A short date reads day first (16/09/2026), unless the second number cannot be a month (09/16/2026), and a number above 12 settles it either way. A day that does not exist is rejected and ignored.
nextPageToken is opaque. Pass back what you were given, never construct one.
Requires the threads:read scope.
Parámetros de consulta
folderstringLabel the threads must carry, case insensitive. Defaults to
inbox, andbinis read astrash.Predeterminado"inbox"querystringMailbox search. Plain words must all appear and match loosely, ignoring case, accents and separators, against the newest message on each thread and the name of any attachment on it, while a quoted phrase has to appear as written and filler words such as
theoremailsare dropped when something else is left to search for. Operators such asfrom:ada,label:Invoices,is:unread,has:pdfandnewer_than:7dnarrow it, and naming a folder within:replacesfolder, soin:anywheresearches them all. When nothing matches exactly, close spellings are returned instead, sobenjiminfinds "Benjamin". A value the search cannot use is ignored rather than narrowing.labelIdsstringComma-separated label ids. A thread must carry every one of them and sit in
folder, which is how the app filters a folder by a label. To list a label's threads whichever folder they are in, pass its id asfolderinstead:folder=USER_BIG_CLIENTS.sortstringThe four orders of the thread list:
newest,oldest,senderandsubject.senderandsubjectare alphabetical, newest first within one sender or subject. Threads that arrived in the same instant are ordered by id, so every order pages to the end without skipping or repeating one.Uno de"newest""oldest""sender""subject"Predeterminado"newest"dateFromstringKeeps threads whose newest message arrived at or after this instant. ISO 8601 with a time and an offset, such as
2026-09-01T00:00:00Z.Formatodate-timedateTostringKeeps threads whose newest message arrived at or before this instant. Both ends are included, and
dateFromafterdateTois a 422.Formatodate-timefromContactsstringtruekeeps only threads whose newest message came from a saved contact, the From contacts filter of the thread list. A key limited to particular addresses reads the contacts its owner saved, and an app acting for a member reads the contacts that member saved.Uno de"true""false"limitintegerThreads per page, a whole number from 1 to 100. Defaults to 25.
Al menos 1Como máximo 100pageTokenstringThe previous page's
nextPageToken, passed back as it came. Send the samesort, dates and filters with it.
Devuelve
A page of threads.
Errores
Los errores que puede devolver cualquier operación400401403404422500Catálogo de errores
También disponible en
GET/threads/{id}
Retrieve a thread
Every message in it, not only the most recent.
The messages are passed through as the mailbox stored them rather than projected onto a field list, and this document describes only encryption, which is the one field whose absence a caller cannot safely guess at. A message that arrived encrypted carries it and has an EMPTY BODY; read encryption.format before concluding a message was empty, and note that the two *-signed formats are ordinary readable mail.
Requires the threads:read scope.
Parámetros de ruta
idstringObligatorioThread id, as returned by
listor carried on a message.
Devuelve
The thread, with every message on it.
Errores
Los errores que puede devolver cualquier operación400401403404422500Catálogo de errores
También disponible en
PATCH/threads/{id}
Mark read/unread and change labels
Applies and removes labels, and sets read state, on one conversation. Label ids come from GET /labels; the system ids INBOX, ARCHIVE, STARRED, IMPORTANT, SPAM and UNREAD are taken in any case, so archiving is addLabelIds: ["ARCHIVE"] with removeLabelIds: ["INBOX"]. An id in addLabelIds that names no label is a 422 label_not_found, and nothing on the thread changes: create the label with POST /labels first. An unknown id in removeLabelIds is not an error, since the thread does not carry it. TRASH, SNOOZED and DRAFT are refused with label_not_directly_settable; use the trash and snooze endpoints.
Requires the threads:write scope.
Parámetros de ruta
idstringObligatorioThread id.
Cuerpo de la petición
readbooleantrueremovesUNREADandfalseadds it.addLabelIdsstring[]Label ids to put on the thread. Each must name a label.
Hasta 50 elementosremoveLabelIdsstring[]Label ids to take off the thread.
Hasta 50 elementos
Devuelve
Applied.
Errores
- 422
label_not_foundfor an id inaddLabelIdsthat names no label, orlabel_not_directly_settableforTRASH,SNOOZEDorDRAFT.
Los errores que puede devolver cualquier operación400401403404500Catálogo de errores
También disponible en
DELETE/threads/{id}
Delete a thread for good
Deletes every message in the thread, with its attachments, and cannot be undone, which is what Delete from Bin does in the app. It works on a thread in any folder, so move it to the Bin with POST /threads/{id}/trash when you only mean to throw it away.
Requires the threads:write scope.
Parámetros de ruta
idstringObligatorioThe thread, as
GET /threadsreturns it.
Devuelve
Gone for good.
Errores
- 500
thread_delete_failed: the thread could not be deleted, and nothing was removed.
Los errores que puede devolver cualquier operación400401403404422Catálogo de errores
También disponible en
POST/threads/{id}/trash
Move a thread to the Bin
Clears INBOX, SPAM, SNOOZED and ARCHIVE together, which is what the app does. Adding the TRASH label by hand through PATCH is refused, because doing only half of it leaves the thread listed in the Bin AND its old folder.
Requires the threads:write scope.
Parámetros de ruta
idstringObligatorioThread id.
Devuelve
Trashed.
Errores
Los errores que puede devolver cualquier operación400401403404422500Catálogo de errores
También disponible en
POST/threads/{id}/snooze
Snooze a thread
Hides it and schedules its return. Both halves happen together: the label hides it, a stored wake time brings it back, and a thread snoozed by label alone never returns.
Requires the threads:write scope.
Parámetros de ruta
idstringObligatorioThread id.
Cuerpo de la petición
wakeAtstringObligatorio- Formato
date-time
Devuelve
Snoozed.
Errores
Los errores que puede devolver cualquier operación400401403404422500Catálogo de errores
También disponible en
POST/threads/{id}/unsnooze
Unsnooze a thread
Brings it back now and cancels the scheduled return.
Requires the threads:write scope.
Parámetros de ruta
idstringObligatorioThread id.
Devuelve
Back in the inbox.
Errores
Los errores que puede devolver cualquier operación400401403404422500Catálogo de errores
También disponible en
GET/threads/{id}/messages/{messageId}/attachments
A message's attachments
content is base64, and an empty string where the stored bytes could not be found.
This is the DISPLAY list. Of the parts named by a message's encryption.parts, the ciphertext part IS listed and downloads like any other file (it is the message, and downloading it is the only way an API client reads this mail). The PGP/MIME version part and any detached signature are held out deliberately, because they rendered as junk attachments and there is nothing a caller can do with them. Both keep their ids in encryption.parts, which correlates the two views, and this endpoint does not return them.
Requires the threads:read scope.
Parámetros de ruta
idstringObligatorioThread id the message belongs to.
messageIdstringObligatorioMessage id from that thread's
messages.
Devuelve
Attachments.
Errores
Los errores que puede devolver cualquier operación400401403404422500Catálogo de errores
También disponible en
GET/threads/counts
Count the mail in each folder
What the sidebar of the app shows: how many conversations each folder holds and how many of them are unread, and how many inbox conversations arrived at each address. unread is a pseudo-folder whose count is the unread conversations in the inbox. A key or an app limited to particular addresses counts only the mail that arrived at them, and address narrows the counts to one address, never wider than that.
Requires the threads:read scope.
Parámetros de consulta
addressstringCount only the mail delivered to this address. One the key does not reach counts nothing rather than failing.
De 3 a 320 caracteres
Devuelve
The counts.
Errores
Los errores que puede devolver cualquier operación400401403404422500Catálogo de errores
También disponible en
GET/threads/{id}/summary
Read the summary of a thread
The short AI summary the reading pane shows above a thread. It is written once and kept, and written again when a new message arrives, so reading it is cheap. state is ready with the summary, pending while one is being written (ask again in a few seconds), or none when there is nothing to summarise, such as a thread holding a message that arrived encrypted. Writing a summary spends one of the workspace's AI actions.
Requires the threads:read scope.
Parámetros de ruta
idstringObligatorioThe thread, as
GET /threadsreturns it.
Devuelve
The summary, or the state it is in.
Errores
Los errores que puede devolver cualquier operación400401403404422500Catálogo de errores
También disponible en
POST/threads/{id}/restore
Take a thread out of the Bin
Puts a thread back in the inbox, out of the Bin and out of Spam, which is what Restore from Bin and Move to inbox do in the app. It is the undo of POST /threads/{id}/trash, and calling it again changes nothing.
Requires the threads:write scope.
Parámetros de ruta
idstringObligatorioThe thread, as
GET /threadsreturns it.
Devuelve
Back in the inbox.
Errores
- 500
thread_update_failed: the labels could not be written, and nothing on the thread changed.
Los errores que puede devolver cualquier operación400401403404422Catálogo de errores
También disponible en
Objetos
DeletedThreadobject
objectstring- Uno de
"thread" idstringdeletedboolean- Uno de
true
MailboxCountsobject
objectstringObligatorio- Uno de
"mailbox_counts" foldersobject[]ObligatoriolabelstringObligatorioThe folder, as its label id in lower case.
Uno de"inbox""sent""spam""archive""trash""snoozed""unread"countintegerObligatorioConversations in the folder.
unreadintegerObligatorioHow many of them are unread.
addressesobject[]ObligatorioaddressstringObligatorioThe address the mail arrived at, or null for mail that recorded none.
Puede ser nullcountintegerObligatorioInbox conversations delivered to it.
MessageEncryptionobject
What kind of encryption this message arrived carrying, read off its top-level Content-Type when it was ingested.
ABSENCE MEANS NOBODY LOOKED. The field is omitted on every message stored before detection existed. It never means "checked, and found none". A client reading a missing encryption as "this was plaintext" is asserting something no part of this system measured.
It is a statement about the ENVELOPE and not a verification. A message can be seen to be sealed without being opened, and those are different claims: nothing here says a signature checked out, says who holds a key, or licenses a padlock in a user interface.
SIGNED IS NOT SEALED, and that distinction is the whole reason format is an enum rather than a flag. For the three sealed formats the message's body fields are empty or hold PGP armor, and an empty body on such a message means "we cannot read this" rather than "there was nothing here". For the two signed formats the body is ordinary text and every consumer keeps working on it.
formatstringObligatorioWhich of the five envelope shapes was recognised. THREE of them mean the body is unreadable (
pgp-mime,pgp-inlineandsmime-encrypted), and the other two,pgp-signedandsmime-signed, mean the body arrived in the clear beside a detached signature and is read exactly like any other message. Branch on this value; branching on the mere presence of the object treats readable mail as unreadable.Uno de"pgp-mime""pgp-signed""pgp-inline""smime-encrypted""smime-signed"detectedAtstringObligatorioWhen the classification was made, on our clock at ingest. It dates OUR READING of the envelope and says nothing about when the message was encrypted or signed, or by whom.
rawRetainedbooleanWhether the original RFC822 bytes were kept, so that something holding the key could open the message later. Today it is always false. Nothing retains the raw message yet. It is published now so a client can start reading it rather than needing a second pass over every stored message the day that changes.
Predeterminadofalsepartsobject[]The envelope parts, each named by the id its bytes were written under. They are deliberately NOT in the message's attachment list (a PGP/MIME message would otherwise render two junk chips), so a sealed message commonly reports no attachments at all, and that emptiness is not evidence that nothing was attached. These ids are a CORRELATION KEY and not a handle:
GET /threads/{id}/messages/{messageId}/attachmentsserves the display list, so it does not return them, and no other path in this API returns them either.indexis the index into the original MIME parts.indexintegerObligatorioattachmentIdstringObligatoriorolestringObligatorio- Uno de
"version""ciphertext""signature"
RestoredThreadobject
objectstring- Uno de
"thread" idstringrestoredboolean- Uno de
true
Threadobject
objectstring- Uno de
"thread" idstringThe id that was asked for. Echoed back rather than read off the result. The mailbox answers a thread as messages, labels and counts, with no id of its own.
messagesThreadMessage[]Every message on the thread, oldest first, not only the most recent.
labelsobject[]The folders and labels the thread sits in. Backend-shaped like the messages are, so only the two fields every backend agrees on are described.
idstringnamestring
messageCountintegerThe length of
messages, counted here.hasUnreadbooleantotalRepliesintegerdeliveredTostringThe workspace address the thread belongs to, lower-cased: the address its first message was delivered to, with any
+tagremoved, or the address it was sent from when the thread began with a send. Later messages joining the thread do not change it. Null when no address was recorded.Puede ser null
ThreadMessageobject
A message, in whatever shape the mailbox stored it. The fields are deliberately not enumerated here. encryption is the one property this API describes, because it is the one whose absence cannot be guessed at safely.
encryptionMessageEncryption
ThreadSummaryobject
objectstringObligatorio- Uno de
"thread_summary" threadIdstringObligatoriostatestringObligatorio- Uno de
"ready""pending""none" summarystringObligatorioOne or two sentences, present when
stateisready.Puede ser null