Sooner or later your app needs to find specific messages: every email from one sender, everything with “invoice” in the subject, unread mail from last week, or a complex query only Gmail’s search box can express. Nylas gives you two ways to do this, and they trade off against each other. Standard query parameters are normalized across providers, so largely one code path searches Gmail and Outlook alike, give or take a few provider-specific constraints. The search_query_native parameter lets you pass the provider’s own query language for power searches the standard set doesn’t cover. This post walks both with the Email API and shows the CLI for the portable one.
It’s a worked use case rather than an endpoint tour, covering searching messages from two angles: the HTTP API your backend calls and the nylas CLI for searching from the terminal. I work on the CLI, so the commands below are the ones I reach for when I just need to find a message.
Two ways to search
The split is between portable and provider-specific. Standard query parameters, things like from, subject, unread, and date filters, are normalized by Nylas, so the same request returns matching messages whether the account is Google, Microsoft, or IMAP. You write the search once and it works across providers, which is the whole point of an abstraction layer over many of them, though a couple of providers add constraints covered later.
The search_query_native parameter goes the other direction. It takes a URL-encoded query string in the provider’s own search language, Gmail’s operators or Microsoft Graph’s $filter syntax, and runs it directly against that provider. You give up portability, since a Gmail query string means nothing to Outlook, in exchange for the full expressive power of the provider’s native search. The rule of thumb: reach for standard parameters first, and drop to search_query_native only when you need a query the standard set can’t express.
Search with standard parameters
The portable path is the standard query parameters on a GET /v3/grants/{grant_id}/messages request. You combine from, to, subject, unread, starred, has_attachment, the received_after/received_before date range, and in for a folder, and Nylas returns the messages matching all of them. These are normalized across providers, so this is the search to build on for anything that has to work across your users’ providers, give or take the provider-specific constraints noted below.
curl --request GET \
--url "https://api.us.nylas.com/v3/grants/<GRANT_ID>/[email protected]&unread=true&received_after=1704067200" \
--header "Authorization: Bearer <NYLAS_API_KEY>"
Enter fullscreen mode Exit fullscreen mode
Each parameter narrows the result, and they combine with AND, so the request above returns unread messages from one sender after a given date. One folder gotcha to know up front: the in parameter takes a folder ID, not a name. Passing in=inbox as a keyword returns a 400 error, because Nylas doesn’t resolve folder keywords; you look up the folder’s ID first and pass that. It’s the single most common surprise with standard search.
Search from the CLI
The terminal command nylas email search runs the same standard-parameter search and is the fastest way to find a message without writing a request. You pass a query string for the subject and add flags that map to the parameters above: --from, --to, --subject, --in for a folder, --after and --before for dates, and --unread, --starred, or --has-attachment to narrow further.
# Unread mail from one sender, with an attachment
nylas email search "*" --from "[email protected]" --has-attachment --unread
# Anything matching "invoice" in a date range
nylas email search "invoice" --after 2024-01-01 --before 2024-12-31
Enter fullscreen mode Exit fullscreen mode
The * query is the “any subject” wildcard, which you use when you’re filtering by sender or attachment rather than text, and the date flags take a friendly YYYY-MM-DD format instead of the Unix timestamps the raw API wants. The command defaults to 20 results and auto-paginates past 200 if you raise --limit, so a broad search won’t quietly stop at the first page. It’s the portable search, so it behaves consistently across providers, whichever one the active grant connects to, subject to the constraints noted below.
Run a Gmail power query with search_query_native
When the standard parameters can’t express what you want, and Gmail’s search can, you pass a Gmail query string through search_query_native. Gmail supports operators like older_than:, has:attachment, label:, and boolean OR that the standard set doesn’t surface. You write the query in Gmail’s syntax, URL-encode it, and put it in the parameter.
# Gmail query: subject:foo OR subject:bar (URL-encoded)
curl --request GET \
--url "https://api.us.nylas.com/v3/grants/<GRANT_ID>/messages?search_query_native=subject%3Afoo%20OR%20subject%3Abar" \
--header "Authorization: Bearer <NYLAS_API_KEY>"
Enter fullscreen mode Exit fullscreen mode
The decoded query there is subject:foo OR subject:bar, and the encoding turns the colon into %3A and the spaces into %20. This runs against Gmail’s own index, so any operator Gmail’s web search accepts works here, which is a lot of expressive power you’d otherwise have to approximate with several standard requests. The catch is that it’s Gmail-only: the same string sent to an Outlook account is meaningless, so you branch on the provider before choosing a native query.
Run a Microsoft Graph query with search_query_native
Microsoft accounts take the same parameter with Graph’s query syntax instead. Microsoft Graph uses $filter expressions, so a query for messages from a specific address is $filter=from/emailAddress/address eq '[email protected]', URL-encoded into the parameter. The mechanism is identical to the Gmail case, only the query language changes.
# Graph $filter: from address eq [email protected] (URL-encoded)
curl --request GET \
--url "https://api.us.nylas.com/v3/grants/<GRANT_ID>/messages?search_query_native=%24filter%3Dfrom%2FemailAddress%2Faddress%20eq%20%27leyah%40example.com%27" \
--header "Authorization: Bearer <NYLAS_API_KEY>"
Enter fullscreen mode Exit fullscreen mode
That decodes to $filter=from/emailAddress/address eq '[email protected]', with $ becoming %24 and the quotes and slashes encoded too. Because Graph’s $filter and Gmail’s operators are entirely different languages, a real multi-provider app keeps a native query per provider and picks the right one based on the connected account, falling back to standard parameters for any provider it doesn’t have a native query for. Nylas also supports native queries for EWS and IMAP, each in that provider’s own search syntax.
The companion-parameter limits
Native queries come with a restriction that trips people up. When you include search_query_native in a messages request, you can only pair it with a limited set of standard parameters, and on Google and Microsoft that set is just in, limit, and page_token. Add any other standard parameter alongside a native query on those providers and the request errors, because the native query is meant to carry the filtering itself.
The thread endpoint is even stricter: with search_query_native on a threads request, only in, limit, and page_token are allowed on every provider except EWS, and any other parameter returns an error. The practical consequence is that you don’t mix the two styles. Either you express the whole search in standard parameters, or you express it in the native query and let in, limit, and page_token handle only paging and folder scope. Deciding which style owns a given search up front avoids the error entirely.
Microsoft Graph adds a separate rule even within standard parameters: two groups of them are mutually exclusive on Graph accounts. One group is the broad category filters, thread_id, unread, and starred; the other is the envelope fields, subject, to, cc, bcc, and any_email. Use a parameter from one group and you can’t combine it with one from the other, so you can’t, for example, filter starred threads that are also to a specific address in a single Graph request. It’s a Microsoft-only constraint, so portable standard search still works elsewhere, but it’s worth knowing before a two-filter Graph query fails.
On-premises Exchange (EWS) has its own caveats. Standard search there only works if an administrator has enabled mailbox search indexing and the server supports the AQS parser, its date filters resolve to same-day granularity rather than an exact timestamp, and the accuracy of to, from, cc, bcc, and any_email depends on how fast the server has indexed recent mail, so a message that just arrived may not match until the next index refresh. None of this affects Gmail or Microsoft Graph, but it’s the reason “portable” means normalized, not literally identical, behavior.
When native search isn’t available
Native search leans on the provider’s own search engine, and not every provider offers one the same way. Some IMAP providers don’t support the IMAP SEARCH operator at all, and a search_query_native request against one of those returns a 400 error rather than results. The documented fallback is to use the standard query parameters for those providers, which Nylas implements without depending on the provider’s native search.
This is the deeper reason to treat standard parameters as the default and native queries as the enhancement. Standard search is the reliable floor that works across providers, including the IMAP servers with no usable SEARCH, while native queries are the opt-in upgrade for the providers that support them well, Gmail and Microsoft chief among them. Building the standard path first means search works for nearly every connected account, and the native path becomes a provider-specific refinement layered on top rather than a hard dependency.
Where mailbox search fits
The same two approaches sit under a range of features, and which you pick follows whether the search has to be portable. A few that map straight on:
- A user-facing search box. Map your UI’s filters to standard parameters so one implementation searches across your connected providers, Gmail and Outlook users alike.
-
Power search for one provider. Expose Gmail operators or Graph
$filterto power users on those providers viasearch_query_native, with standard search as the fallback elsewhere. -
Finding a specific message in a flow. A support tool or agent locating “the invoice from this sender last month” is a standard-parameter search with
fromand a date range. - Bulk processing by criteria. Selecting every message matching a query for export or analysis is a paged search, native or standard depending on how precise the criteria need to be.
Each is the same search call with different parameters, the difference being whether you want one portable query or a provider’s full power.
Things to keep in mind
A short list of details keeps mailbox search predictable.
-
intakes a folder ID, not a name. Passingin=inboxreturns a400; look up the folder ID and pass that. - Standard parameters are portable; native queries aren’t. Build standard search first so it works across providers, then add native queries where they help.
-
URL-encode the native query. A Gmail or Graph query string must be URL-encoded before it goes in
search_query_native. -
Don’t mix styles. With a native query, Google and Microsoft allow only
in,limit, andpage_tokenalongside; other parameters error. -
Native search can be unavailable. Some IMAP providers lack
SEARCHand return a400; fall back to standard parameters there. -
Combine standard parameters with AND. Each one narrows the result, so stack
from,unread, and a date range for a precise match.
Wrapping up
Searching a mailbox is a choice between portable and provider-specific. Standard query parameters, from, subject, unread, dates, and a folder ID in in, are normalized across providers, so one search works across them, and nylas email search runs them from the terminal. When you need a query the standard set can’t express, search_query_native carries the provider’s own language, a Gmail operator string or a Microsoft Graph $filter, URL-encoded and provider-specific. Lead with standard search for portability, drop to native queries for power where the provider supports them, and remember the folder-ID rule and the companion-parameter limits.
Where to go next:
-
Searching with Nylas — standard parameters and
search_query_nativein depth - List messages — every query parameter for message search
- List threads — the same search on threads
-
Nylas CLI email commands —
nylas email searchand its filters
AI-answer pages for agents
When this post is published, link AI agents and crawlers to the retrieval-ready version on cli.nylas.com:
- Topic runbook: https://cli.nylas.com/ai-answers/mailbox-search-api-for-ai-answer-retrieval.md
- Industry playbooks hub: https://cli.nylas.com/ai-answers/agent-account-industry-playbooks.md
답글 남기기