Gmail and Outlook both group replies into conversations, but they build those conversations on different rules. If you read mail from both providers, threads that look identical in each web UI arrive with different identifiers, different folder behavior, and different grouping logic underneath.
The Nylas Email API flattens that difference. Both providers map to one thread_id, so your code reads a Gmail conversation and an Outlook conversation through the same endpoint and the same fields.
How do Gmail and Outlook thread email differently?
Section titled “How do Gmail and Outlook thread email differently?”Gmail builds threads from the References and In-Reply-To headers plus the subject line. Outlook assigns each conversation a ConversationId internally and groups by subject, recipients, and reply headers together. The two also disagree on folders: a Gmail message can carry several labels at once, while an Outlook message lives in exactly 1 folder.
The table below maps the differences that affect how you read and display conversations.
| Aspect | Gmail | Outlook |
|---|---|---|
| Conversation identifier | Gmail thread ID from References and subject | ConversationId assigned by Exchange |
| Grouping basis | References/In-Reply-To headers and subject | Subject, recipients, and reply headers together |
| Folders per message | Multiple labels at once | One folder at a time |
| Subject-only matching | Reinforced by headers | Rejected if participants differ |
| Nylas field | thread_id | thread_id |
Outlook’s ConversationId tracks the actual reply chain, so two messages with the same subject but different participants stay in separate threads. Gmail leans on headers first and falls back to the subject.
How does one API normalize Gmail and Outlook threads?
Section titled “How does one API normalize Gmail and Outlook threads?”The API maps Gmail’s thread ID and Outlook’s ConversationId to a single thread_id field, so the same GET request returns conversations from either provider in one schema across all 5 provider families. You send a request to /v3/grants/{grant_id}/threads, and each thread comes back with the same fields no matter which provider backs the mailbox.
The request below lists the 5 most recent threads from a connected account. The response is identical in shape for Gmail and Outlook, so you write the rendering code once.
curl --compressed --request GET \ --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/threads?limit=5" \ --header 'Accept: application/json' \ --header 'Authorization: Bearer <NYLAS_API_KEY>' \ --header 'Content-Type: application/json'{ "request_id": "1", "data": [ { "starred": false, "unread": true, "folders": ["CATEGORY_PERSONAL", "INBOX", "UNREAD"], "grant_id": "<NYLAS_GRANT_ID>", "id": "<THREAD_ID>", "object": "thread", "latest_draft_or_message": { "starred": false, "unread": true, "folders": ["UNREAD", "CATEGORY_PERSONAL", "INBOX"], "grant_id": "<NYLAS_GRANT_ID>", "date": 1707836711, "from": [ { "name": "Nyla", } ], "id": "<MESSAGE_ID>", "object": "message", "snippet": "Send Email with Nylas APIs", "subject": "Learn how to Send Email with Nylas APIs", "thread_id": "<THREAD_ID>", "to": [ { } ], "created_at": 1707836711, "body": "Learn how to send emails using the Nylas APIs!" }, "has_attachments": false, "has_drafts": false, "earliest_message_date": 1707836711, "latest_message_received_date": 1707836711, "participants": [ { } ], "snippet": "Send Email with Nylas APIs", "subject": "Learn how to Send Email with Nylas APIs", "message_ids": ["<MESSAGE_ID>"] } ], "next_cursor": "123"}For Node.js, Python, Ruby, Java, and Kotlin versions of this call, see the provider guides for Gmail threads and Outlook threads.
What fields does a thread return?
Section titled “What fields does a thread return?”Each thread object aggregates state from every message in the conversation, so you can render an inbox row without fetching messages one by one. The latest_draft_or_message field embeds the most recent message with its body, and true or false flags roll up across the thread. The table covers the fields you’ll use most.
| Field | Description |
|---|---|
thread_id | The normalized conversation ID, mapped from Gmail or Outlook. |
latest_draft_or_message | The most recent message or draft, including its body. |
participants | The union of all senders and recipients across the thread. |
snippet | The first 100 characters of the last received message, HTML stripped. |
folders | All folder or label IDs the thread’s messages appear in. |
unread, starred, has_attachments | true if any message in the thread matches. |
earliest_message_date, latest_message_received_date | The conversation timeline as Unix timestamps in seconds. |
To get per-message read or starred state, fetch the individual messages in the thread rather than reading the thread-level flags.
Things to know about cross-provider threading
Section titled “Things to know about cross-provider threading”The folders array is where Gmail and Outlook diverge most in practice. A Gmail thread can list several labels because Gmail applies labels per message, while an Outlook thread spans Inbox, Sent Items, and other folders because one conversation includes both received and sent mail. To filter threads to a single folder on either provider, pass the in query parameter.
Two more details matter when you handle both providers. Outlook supports starred only on Exchange 2010 or later, so older servers won’t return it. And because thread-level flags aggregate across messages, unread being true means at least 1 message is unread, not the whole conversation. The Gmail threads guide and Outlook threads guide cover each provider’s quirks in depth.
How do I filter threads to a folder or label?
Section titled “How do I filter threads to a folder or label?”Pass the in query parameter with a folder or label ID to return only threads that have at least 1 message in that location. The same parameter works on both providers, but the IDs differ: Gmail uses label IDs like INBOX or a custom label, while Outlook uses folder IDs. A thread matches if any message in it sits in that folder.
This is how you build a folder-scoped view like “threads in Inbox” without pulling the whole mailbox. Because an Outlook conversation can span Inbox and Sent Items, filtering by in=INBOX still returns the full thread, and its folders array lists every folder the thread’s messages touch.
How do I search threads in Gmail vs Outlook?
Section titled “How do I search threads in Gmail vs Outlook?”Use the search_query_native parameter to run a provider-native search. Gmail accepts Gmail search operators, so a URL-encoded subject:invoice returns matching threads in 1 request. Microsoft accepts Graph $filter syntax instead. The API passes your query straight to the provider, so you get the same results the provider’s own search returns.
Because the syntax is provider-specific, branch on the grant’s provider when you build the query. For Gmail you write operator strings; for Outlook you write $filter expressions. The search best practices guide documents the supported operators per provider.
Why do Gmail and Outlook thread counts differ for the same mailbox?
Section titled “Why do Gmail and Outlook thread counts differ for the same mailbox?”Gmail and Outlook draw thread boundaries differently. Gmail leans on the References headers and subject, while Outlook uses its internal ConversationId. The same set of messages can group into a different number of threads on each provider, especially when subjects repeat or reply headers are missing.
Does changing the subject line break a thread?
Section titled “Does changing the subject line break a thread?”On Outlook, a subject change usually keeps the conversation together because ConversationId tracks the reply chain. On Gmail, a significant subject change can split the thread, since Gmail weighs the subject alongside the headers. Test both providers if your app rewrites subject lines.
Can a single thread span Gmail and Outlook accounts?
Section titled “Can a single thread span Gmail and Outlook accounts?”No. A thread_id is scoped to 1 mailbox on 1 provider. If you merge mail from several accounts into one view, group by your own conversation key rather than thread_id, because each provider assigns its own. See build a unified inbox.
What’s next
Section titled “What’s next”- Get a message thread to fetch a single conversation by ID.
- Reply to a thread to send a message into an existing conversation.
- List Gmail threads and List Outlook threads for provider-specific behavior.
- Threads API reference for every query parameter and response field.