Yahoo Mail doesn’t have a public REST API. There’s no equivalent to Gmail’s API or Microsoft Graph. Under the hood, Nylas connects to Yahoo accounts over IMAP, but you don’t need to deal with IMAP protocols, socket connections, or MIME parsing yourself. The same Messages API you use for Gmail and Outlook works for Yahoo.
This guide covers listing messages from Yahoo accounts, including the OAuth setup process, the 90-day message cache, and how to reach older messages when you need them.
Why use Nylas instead of IMAP directly?
Section titled “Why use Nylas instead of IMAP directly?”Yahoo’s only developer-facing email interface is raw IMAP. That means building your own connection pooling, MIME parsing, and sync infrastructure from scratch. On top of the protocol complexity, Yahoo OAuth requires signing a Commercial Access Agreement before you can even get API credentials, and the IMAP search implementation has known gaps (no NOT operator support, for example).
Nylas wraps all of that in a REST API with JSON responses. You don’t need to sign Yahoo’s agreement yourself, manage IMAP sockets, or work around IMAP search limitations. Your code works across Yahoo, Gmail, Outlook, and every other provider without modification.
If you’re only targeting Yahoo and are comfortable with IMAP, you can connect directly. For everything else, Nylas saves you significant development time.
Before you begin
Section titled “Before you begin”You’ll need:
- A Nylas application with a valid API key
- A grant for a Yahoo Mail account
- A Yahoo OAuth connector configured with your Yahoo app credentials (see Yahoo authentication guide)
New to Nylas? Start with the quickstart guide to set up your app and connect a test account before continuing here.
Yahoo OAuth setup
Section titled “Yahoo OAuth setup”Yahoo requires a few extra steps compared to Google or Microsoft. You’ll need to:
- Request API access by submitting the Yahoo Mail API Access form. Yahoo will send you a Commercial Access Agreement to sign.
- Create a Yahoo app by registering your application in the Yahoo Apps dashboard to get a client ID and secret.
- Create a Yahoo connector in Nylas and configure it with your Yahoo client ID and secret.
Yahoo OAuth scopes are simpler than Google’s tier system:
| Access level | Scopes required |
|---|---|
| Read-only | email, mail-r |
| Read-write | email, mail-r, mail-w |
You can only select one access level. Yahoo doesn’t let you request both mail-r and mail-w separately.
If you’d rather skip the OAuth setup for testing, you can also authenticate Yahoo accounts using IMAP with an app password. This uses the imap provider type instead of yahoo and requires each user to generate an app password in their Yahoo account settings. OAuth is the better choice for production apps.
The full setup walkthrough is in the Yahoo authentication guide.
List messages
Section titled “List messages”Make a List Messages request with the grant ID. By default, Nylas returns the 50 most recent messages. These examples limit results to 5:
curl --request GET \ --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages?limit=5" \ --header 'Accept: application/json, application/gzip' \ --header 'Authorization: Bearer <NYLAS_API_KEY>' \ --header 'Content-Type: application/json'{ "request_id": "d0c951b9-61db-4daa-ab19-cd44afeeabac", "data": [ { "starred": false, "unread": true, "folders": [ "UNREAD", "CATEGORY_PERSONAL", "INBOX" ], "grant_id": "1", "date": 1706811644, "attachments": [ { "id": "1", "grant_id": "1", "filename": "invite.ics", "size": 2504, "content_type": "text/calendar; charset=\"UTF-8\"; method=REQUEST" }, { "id": "2", "grant_id": "1", "filename": "invite.ics", "size": 2504, "content_type": "application/ics; name=\"invite.ics\"", "is_inline": false, "content_disposition": "attachment; filename=\"invite.ics\"" } ], "from": [ { "name": "Nylas DevRel", } ], "id": "1", "object": "message", "snippet": "Send Email with Nylas APIs", "subject": "Learn how to Send Email with Nylas APIs", "thread_id": "1", "to": [ { "name": "Nyla", } ], "created_at": 1706811644, "body": "Learn how to send emails using the Nylas APIs!" } ], "next_cursor": "123"}app.get("/nylas/recent-emails", async (req, res) => { try { const identifier = process.env.USER_GRANT_ID; const messages = await nylas.messages.list({ identifier, queryParams: { limit: 5, }, });
res.json(messages); } catch (error) { console.error("Error fetching emails:", error); }});from dotenv import load_dotenvload_dotenv()
import osimport sysfrom nylas import Client
nylas = Client( os.environ.get('NYLAS_API_KEY'), os.environ.get('NYLAS_API_URI'))
grant_id = os.environ.get("NYLAS_GRANT_ID")
messages = nylas.messages.list( grant_id, query_params={ "limit": 5 })
print(messages)require 'nylas'
nylas = Nylas::Client.new(api_key: '<NYLAS_API_KEY>')query_params = { limit: 5 }messages, _ = nylas.messages.list(identifier: '<NYLAS_GRANT_ID>', query_params: query_params)
messages.each {|message| puts "[#{Time.at(message[:date]).strftime("%d/%m/%Y at %H:%M:%S")}] \ #{message[:subject]}"}import com.nylas.NylasClient;import com.nylas.models.*;import java.text.SimpleDateFormat;
public class ListMessages { public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError { NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build(); ListMessagesQueryParams queryParams = new ListMessagesQueryParams.Builder().limit(5).build(); ListResponse<Message> message = nylas.messages().list("<NYLAS_GRANT_ID>", queryParams);
for(Message email : message.getData()) { String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"). format(new java.util.Date((email.getDate() * 1000L)));
System.out.println("[" + date + "] | " + email.getSubject()); } }}import com.nylas.NylasClientimport com.nylas.models.*import java.text.SimpleDateFormatimport java.util.*
fun main(args: Array<String>) { val nylas = NylasClient(apiKey = "<NYLAS_API_KEY>") val queryParams = ListMessagesQueryParams(limit = 5) val messages = nylas.messages().list("<NYLAS_GRANT_ID>", queryParams).data
for (message in messages) { val date = SimpleDateFormat("yyyy-MM-dd HH:mm:ss") .format(Date(message.date.toLong() * 1000)) println("[$date] | ${message.subject}") }}Filter messages
Section titled “Filter messages”You can narrow results with query parameters. Here’s what works with Yahoo accounts:
| Parameter | What it does | Example |
|---|---|---|
subject | Match on subject line | ?subject=Weekly standup |
from | Filter by sender | [email protected] |
to | Filter by recipient | [email protected] |
unread | Unread messages only | ?unread=true |
in | Filter by folder or label ID | ?in=INBOX |
received_after | After a Unix timestamp | ?received_after=1706000000 |
received_before | Before a Unix timestamp | ?received_before=1706100000 |
has_attachment | Only messages with attachments | ?has_attachment=true |
Here’s how to combine filters. This pulls unread messages from a specific sender:
curl --request GET \ --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/[email protected]&unread=true&limit=10" \ --header 'Accept: application/json' \ --header 'Authorization: Bearer <NYLAS_API_KEY>'const messages = await nylas.messages.list({ identifier: grantId, queryParams: { unread: true, limit: 10, },});messages = nylas.messages.list( grant_id, query_params={ "unread": True, "limit": 10, })Search with search_query_native
Section titled “Search with search_query_native”Yahoo supports the search_query_native parameter for IMAP-style search. Unlike Google and Microsoft, Yahoo lets you combine search_query_native with any other query parameter, not just in, limit, and page_token.
curl --request GET \ --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages?search_query_native=subject:invoice&limit=10" \ --header 'Accept: application/json' \ --header 'Authorization: Bearer <NYLAS_API_KEY>'const messages = await nylas.messages.list({ identifier: grantId, queryParams: { searchQueryNative: "subject:invoice", limit: 10, },});messages = nylas.messages.list( grant_id, query_params={ "search_query_native": "subject:invoice", "limit": 10, })Yahoo’s IMAP search doesn’t support NOT syntax. If you use a negation query, the results may still contain messages you intended to exclude. Filter those out in your application code instead.
See the search best practices guide for more on search_query_native across providers.
Things to know about Yahoo
Section titled “Things to know about Yahoo”Yahoo is IMAP-based, which means it behaves differently from Google and Microsoft in a few important ways.
The 90-day message cache
Section titled “The 90-day message cache”This is the most important Yahoo-specific detail. Nylas maintains a rolling cache of messages from the last 90 days. Anything received or created within that window is synced and available through the API. Messages older than 90 days are not in the cache, but you can still reach them by setting query_imap=true to query Yahoo’s IMAP server directly. This is slower due to provider latency, but it gives you access to the full mailbox.
curl --request GET \ --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages?query_imap=true&in=INBOX&limit=10" \ --header 'Accept: application/json' \ --header 'Authorization: Bearer <NYLAS_API_KEY>'const messages = await nylas.messages.list({ identifier: grantId, queryParams: { queryImap: true, in: "INBOX", limit: 10, },});messages = nylas.messages.list( grant_id, query_params={ "query_imap": True, "in": "INBOX", "limit": 10, })When using query_imap, you must include the in parameter to specify which folder to search.
Webhooks don’t cover old messages
Section titled “Webhooks don’t cover old messages”Nylas webhooks only fire for changes to messages within the 90-day cache window. If a user modifies or deletes a message older than 90 days, you won’t receive a notification. Plan your sync strategy accordingly if your app needs to track changes across the full mailbox.
Yahoo uses standard IMAP folders
Section titled “Yahoo uses standard IMAP folders”Unlike Microsoft’s internal names (sentitems, deleteditems) or Google’s label system, Yahoo uses straightforward IMAP folder names:
| Yahoo UI name | Folder ID |
|---|---|
| Inbox | Inbox |
| Sent | Sent |
| Draft | Draft |
| Trash | Trash |
| Bulk Mail (Spam) | Bulk Mail |
| Archive | Archive |
Custom folders created by the user appear with their display names. Use the List Folders endpoint to get the complete list for a given account.
Rate limits aren’t publicized
Section titled “Rate limits aren’t publicized”Yahoo doesn’t publish its API rate limits. If your app hits a rate limit, the response will include the duration you need to wait before retrying. Nylas handles retries automatically, but if you’re making a high volume of requests for many Yahoo users, you may see throttling.
As with other providers, webhooks are the best way to avoid hitting rate limits. Let Nylas notify you of changes instead of polling.
Sync and threading
Section titled “Sync and threading”Yahoo accounts in Nylas use IMAP for reading and SMTP for sending. This is invisible to your code, but it explains a few behaviors:
- Sync is slower than Google or Microsoft because those providers have native APIs with push notifications. Yahoo relies on periodic IMAP polling.
- Message IDs are IMAP UIDs, which are numeric values like
12345that are unique within a folder but may not be globally unique across the account. - Thread grouping relies on subject-line and header matching rather than a native threading system. This works well for most conversations but isn’t as precise as Gmail’s built-in
thread_id.
Two ways to authenticate
Section titled “Two ways to authenticate”Yahoo supports two authentication methods in Nylas:
| Method | Provider type | Best for |
|---|---|---|
| Yahoo OAuth | yahoo | Production apps with a seamless user experience, no app passwords needed |
| IMAP with app password | imap | Testing or apps where users already manage app passwords |
Yahoo OAuth is the recommended approach. It gives you a proper OAuth consent flow and doesn’t require users to create app passwords. See the Yahoo authentication guide for both methods.
Paginate through results
Section titled “Paginate through results”The Messages API returns paginated responses. When there are more results, the response includes a next_cursor value. Pass it back as page_token to get the next page:
curl --request GET \ --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages?limit=10&page_token=<NEXT_CURSOR>" \ --header 'Accept: application/json' \ --header 'Authorization: Bearer <NYLAS_API_KEY>'let pageCursor = undefined;
do { const result = await nylas.messages.list({ identifier: grantId, queryParams: { limit: 10, pageToken: pageCursor, }, });
// Process result.data here
pageCursor = result.nextCursor;} while (pageCursor);page_cursor = None
while True: query = {"limit": 10} if page_cursor: query["page_token"] = page_cursor
result = nylas.messages.list(grant_id, query_params=query)
# Process result.data here
page_cursor = result.next_cursor if not page_cursor: breakKeep paginating until the response comes back without a next_cursor.
What’s next
Section titled “What’s next”- Messages API reference for full endpoint documentation and all available parameters
- Using the Messages API for search, modification, and deletion
- Threads to group related messages into conversations
- Search best practices for advanced search with
search_query_nativeacross providers - Webhooks for real-time notifications instead of polling
- Yahoo authentication guide for full Yahoo setup including OAuth and IMAP options
- IMAP provider guide for general IMAP configuration and behavior