The Nylas APIs
The Nylas Platform provides a modern API that works with existing email providers. It makes it simple and fast to integrate your app with a user's email, contacts, or calendar data, and eliminates the complexity of working with old protocols like IMAP and MIME.
The API is designed around the REST ideology, providing simple and predictable URIs to access and modify objects. Requests support standard HTTP methods like GET, PUT, POST, and DELETE and standard status codes. Response bodies are always UTF-8 encoded JSON objects, unless explicitly documented otherwise.
Looking to sync and process mail on-the-fly for many accounts? Check out the Nylas Sync Strategies article in our Knowledge Base for our recommended approach.
Introduction
There are two ways you can connect users to your application. If you don't want to design an authentication flow yourself, you can always use our OAuth flow to get started quicker. Keep in mind this may be faster initially, but you'll have less control over the authentication user experience.
With our Native Authentication flow, a user never has to leave your application to connect their account and you have the freedom to design what the entire process looks like natively.
Once you've successfully connected an email account using one of the authentication methods outlined above, you'll have an access_token that allows you to pull email, contact, and calendar data for that email account. To learn more about how to use this access_token to make requests to the Nylas API see this guide.
Create your developer account
Before you can interact with the Nylas API, you need to sign up for a developer account, which will generate an API client_id and client_secret for you.
OAuth
The Nylas platform uses the OAuth 2.0 protocol for simple, effective authorization. Before making API calls on behalf of a user, you need to fetch an access_token that grants you access to their email. Once you've obtained a token, you include it with Nylas API requests as the HTTP Basic Auth Username. Although although you'll immediately have access to the API once you authorize an account, it may take some time until all historical messages are synced.
Nylas supports both two-legged and three-legged OAuth. It's important to identify which flow you should use:
You should use Server-side (explicit, three-legged) OAuth if you'll be using the Nylas API from:
- backend web services (Ruby on Rails, PHP, Python, etc.)
- a service that will store a large number of access tokens
- a service running on Amazon EC2 or another cloud platform
You should use Client-side (implicit, two-legged) OAuth if you'll be using the Nylas API from:
- a native app on desktop or on mobile
- a client-side Javascript application
- any other app that does not have a server component
Server Side (Explicit) Flow
Step 1
From your application, redirect users to https://api.nylas.com/oauth/authorize, with the parameters detailed in /oauth/authorize. Note for this server side flow response_type should be set to code.
Step 2
Nylas will present your user with the correct sign in panel based on their email address. For example, a user with a Gmail address will see the Gmail “Authorize this Application” screen, while a user with a Yahoo address is shown a Yahoo sign in panel.
If (and only if) Nylas cannot auto detect the user's email provider from their address, the user will see a provider selection screen first.
For Exchange users, clicking "Advanced Settings" will enable the user to enter a login name and/or Exchange server. The majority of Exchange users can log on with their email address and auto-detected server details, but some will have to enter this additional information.
Step 3
Once the user has signed in, their browser will be redirected to the redirect_uri you provided. If authentication was successful, Nylas will include a code parameter in the query string.
Make an HTTP POST to https://api.nylas.com/oauth/token to exchange the code for an access_token. See /oauth/token for details. Make sure to securely store the access_token and provide it as the HTTP Basic Auth Username to make API calls on behalf of the user.
Client Side (Implicit) Flow
Step 1
From your application, redirect users to https://api.nylas.com/oauth/authorize, with the parameters detailed in /oauth/authorize. Note for this server side flow response_type should be set to token.
Step 2
Nylas will present your user with the correct sign in flow based on their email address. This is the exact same as step 2 in the server side flow.
Step 3
Once the user has signed in, their browser will be redirected to the redirect_uri you provided. If authentication was successful, Nylas will include a token parameter in the query string. That's it! We recommend storing the access_token and then removing it from the URL fragment with JavaScript. This is the token you will provide as a HTTP Basic Auth Username to make API calls on behalf of the user.
Note:
If you're building a mobile app or desktop application, you may want to use a custom URL scheme to listen for the redirect to happen in the user's web browser. For example, myapp://app/auth-response.
/oauth/revoke
You can easily revoke an access token by issuing a POST request to the following endpoint. Include the to-be-revoked access token as the HTTP Basic Auth username.
A 200 status code response with an empty body signifies that the token has been successfully revoked and can no longer be used.
Re-authentication
When a user's credentials or server settings (for IMAP/ SMTP or Exchange) changes, the account will stop syncing and its status will change to 'invalid-credentials'. For the account sync to resume, you must ask the user to go through the authentication flow again with their new credentials or server settings.
For a credentials change, once the user has re-authenticated, account sync simply resumes.
Important note!
For a server settings change, for example if the user changes the IMAP/ SMTP or Exchange server endpoint, all previously synced Nylas API object ids for the account will be invalidated. The user will be associated with a new account and account_id, and the Nylas API token returned from reauthentication will point to this account.
Your application must detect this new account_id and take appropriate measures to invalidate any existing IDs you have cached.
Native Authentication
This is a set of endpoints for programmatically creating and updating accounts on Nylas Cloud. It allows you to build a signup form for a user to connect their mailbox to your application.
Connecting a new account is a two-step process, and follows semantics similar to OAuth. The first step is verifying credentials from a user, and the second step is associating this new account with your application in order to receive an API access token.
There are two main endpoints:
https://api.nylas.com/connect/authorize for authenticating a mailboxhttps://api.nylas.com/connect/token for connecting the mailbox to your Nylas Cloud app
All API requests must be made over SSL (HTTPS). The Nylas API is not available via unencrypted HTTP.
/connect/token
This endpoint is where your application exchanges the code received from /connect/authorize and receives an access_token. This associates the mailbox with your Nylas Cloud app.
A successful response from this will be an account object with an access_token attribute. Once you’ve obtained a token, you include it with Nylas API requests as the HTTP Basic Auth Username.
You can remove this account from your Nylas Cloud app in the Nylas API console.
Never send your client secret to a browser!
This request should be made from your server. It's important that you never send your client secret to a browser. In order to do this, your browser JS code should securely send the received code in the previous step to your web app, which in turn makes the request to /connect/token.
Accounts
An account corresponds to an email address, mailbox, and optionally a calendar. When connecting to the Nylas API, a specific access token gives you access to a specific account’s data.
The Account object
Responses for the Account object are encoded as UTF-8 JSON objects with the following attributes:
| attribute | type | description |
|---|---|---|
id |
string | Globally unique object identifier |
object |
string | A string describing the type of object (value is "acount") |
account_id |
string | Reference to parent account object (self-referential in this case) |
name |
string | Full name of the user, used as the default "from" name when sending mail. |
email_address |
string | The canonical email address of the account. For Gmail accounts, this removes periods and plus suffixes. |
provider |
string | Which provider backs the account, e.g. gmail or eas. See [[Supported providers]] for a full list. |
organization_unit |
string | Either "label" or "folder" depending on the provider capabilities |
sync_state |
string | The syncing status of the account. See the Sync status documentation for possible values. |
Folders vs. Labels
Messages and threads in accounts can either be organized around folders, or around labels. This depends on the backend provider. For example, Gmail uses labels whereas Yahoo! Mail uses folders.
Labels and Folders have fundamentally different semantics and these are preserved in the API. The core difference is that a message can have more than one label, versus only having one folder.
The organization_unit attribute on the account object indicates whether the account supports folders or labels. Possible values are folder or label. For more details on format and usage, see the related documentation on Folders and Labels.
/account
An access token can be used to request information about the account it corresponds to. This includes information such as the end-user’s name, email address, and backend mailbox provider.
Account Management
These endpoints allow for account management outside the developer console interface. You can list, cancel, reactivate, and delete accounts associated with your application.
Two important notes!
This endpoint uses the management API domain with different authentication from the rest of the Nylas API.
You must apply for production status before you can cancel or re-activate an account.
Listing all accounts
Often you may want to retrieve a list of all users who have connected to your application. You can use the /accounts endpoint within your application namespace. This will list the accounts associated with your Nylas developer application.
Instead of using a connected email account’s token, you use your client_secret for the Basic Auth username which can be found in the developer console.
Responses are encoded as UTF-8 JSON objects with the following attributes.
| attribute | type | description |
|---|---|---|
account_id |
string | Reference to parent account object (self-referential in this case) |
billing_state |
string | The billing state for the account. Can be free, paid, cancelled, or deleted |
id |
string | Globally unique object identifier |
sync_state |
string | The current sync state for the account. See all sync states |
Re-activate an account
You can re-enable cancelled accounts to make them active again using this endpoint.
Deleting an account
If you would like for an account's data to be completely removed from Nylas' servers, follow these steps to queue the account for deletion:
Please note once you follow these steps, the account will be queued for deletion. It can take up to 30 days for an account's data to be completely removed. Furthermore, if the user re-connects their account and authenticates again, their account won't be deleted.
Account Sync Status
Sometimes, syncing cannot complete successfully for an account, or it might get interrupted. In the event of a recoverable failure, you will see a notification in your developer dashboard and one of the following status messages in the Accounts API:
| Status | Action required |
|---|---|
| running | Sync is successfully running. No action required. |
| invalid-credentials | Authenticating failure with mail server. You should prompt the user to re-authorize |
| config-error | Configuration issue. Prompt the user to re-authorize and update configuration |
| connection-error | Error connecting to backend provider. Wait.* |
| sync-error | Error while syncing. Wait.* |
| stopped | Syncing is stopped. Upgrade the account to start syncing |
Most sync and connection failures are temporary, but if this persists, check our status page for any known problems and/or contact support.
Credential errors
These occur when the user's account fails authorization. Usually this is because the user has changed their password, revoked their OAuth credentials, or their IMAP/ SMTP or Exchange server endpoint has changed.
Without authorization, no mail operations can successfully complete. In order to make the account active again, you will need to re-authorize the user by asking them to reauthenticate by going through the authentication flow again.
Configuration Problems
Sometimes you might run into trouble when trying to sync accounts. Here is a list of common problems you might run into.
'All Mail' folder disabled
For Gmail and Google Apps accounts, the Nylas Sync Engine synchronizes the 'All Mail' folder. If a user has disabled IMAP access for this folder, synchronization will fail.
To fix it, the user needs to make sure the 'All Mail' folder has 'Show in IMAP' checked in their Gmail settings. After enabling it, re-authorize the user by restarting the authorization flow.
Full IMAP not enabled
As the Nylas Sync Engine synchronizes mail over IMAP, if IMAP access is not properly enabled for an account or a domain, synchronization will fail. This does not apply to Microsoft Exchange accounts.
The user needs to ensure IMAP is fully enabled for their account. This may involve contacting their domain administrator or hosting provider. Once it is enabled, re-authorize the user.
Connection and sync errors
If temporary connection issues persist, contact support for assistance. Outages or other unscheduled service interruptions are posted on Nylas Status.
Too many connections
Some IMAP configurations limit the number of connections which can be made. If a user has several programs accessing their email account via IMAP, they may run into this error with the Nylas Sync Engine. The resolution is for the user to close other programs which may be accessing their account via IMAP. Gmail users can check which applications they have authorized, and remove any that are no longer being used.
Introduction
Threads are a first-class object, allowing you to build beautiful mail applications that behave the way users have come to expect. Actions like archiving or deleting can be performed on threads or individual messages.
Nylas threads messages together using a variety of heuristics. On Gmail and Microsoft Exchange accounts, messages will be threaded together as close as possible to the representation in those environments. For all other providers (including generic IMAP), messages are threaded using a custom JWZ-inspired algorithm. (Open source here, for the curious.)
To load all messages for a given thread, you should instead use the messages endpoint with a thread_id filter parameter.
Supported Modifications
You can make many modifications to the state of threads:
- Modify the unread status
- Star or unstar the thread
- Move the thread to a different folder
- Modify the thread's labels
To make these modifications, make an HTTP PUT request to /threads/{id} with any combination of the body parameters specified here.
A note about thread modifications
An operation on a thread is performed on all the messages in the thread. It's a convenient shortcut to perform bulk operations on messages, which is what users have come to expect with modern mail applications.
Filtering, Pagination, and Views with Threads
The threads endpoint supports Filters, Pagination, and Views, making it easy to return a subset of threads in specific folder, from a certain address, with a specific subject, etc.
Thread Filtering
Threads support various combinations of Filters. Check all the query parameters on the /threads endpoint for more information.
Thread Pagination
By default the /threads endpoint will return a maximum of 100 objects. You should paginate through an entire user's mailbox by using the limit and offset URL query parameters. See Pagination for more details about pagination in general. Check all the query parameters on the /threads endpoint for more information.
Thread Views
Threads support the use of Views by including the view query parameter in your request.
The Expanded Threads View expands the threads response to contain message and draft sub-objects. Adding view=expanded will remove message_ids and draft_ids, and include messages and drafts. Note the message and draft sub-objects do not include a body parameter.
/threads
Responses are encoded as UTF-8 JSON objects with the following attributes:
| attribute | type | description |
|---|---|---|
id |
string | Globally unique object identifier |
object |
string | A string describing the type of object (value is "thread") |
account_id |
string | Reference to parent account object |
subject |
string | Subject of the first message in the thread |
unread |
boolean | Indicates whether the thread contains unread messages (mutable) |
starred |
boolean | Indicates one or more messages are starred, aka flagged (mutable) |
last_message_timestamp |
unix timestamp | Timestamp of the most recent message |
last_message_received_timestamp |
unix timestamp | Timestamp of the most recently received message. (Excludes messages sent by the account.) |
first_message_timestamp |
unix timestamp | Timestamp when the thread began |
participants |
array | List of participant objects computed from all messages in the thread. |
snippet |
string | A shortened plain-text preview of the most recent message in the thread |
message_ids |
array | Array of IDs for messages within the thread, sorted by their timestamps |
draft_ids |
array | Array of IDs for unsent drafts in the thread. May be null or absent |
version |
integer | Incrementing value related to thread updates. You can use this to compare revisions, or invalidate your local cache. |
folders |
array | The folder location(s) of a thread, present only if the parent account's organization_unit is folder. Note that threads can span folders, depending on the location of the thread's messages. See the [[folders]] docs for more info. |
labels |
array | A list of [[label]] objects, present only if the parent account's organization_unit is label. These have Gmail-style semantics and can be arbitrarily added and removed from threads. |
/threads/{id}
Unread status
The unread attribute is set to true if any of the thread's messages are unread. To mark all underlying messages as "read", your application should change the unread attribute to false on the thread. Any change to a thread's unread status will cascade to all messages in the thread.
Changes to the unread status will propagate to the backend mailbox provider, such as Gmail or Exchange.
Starring (flags)
Stars, also know as "flags", are displayed in nearly every mail app, and are an easy way to highlight a specific message. Although most apps usually show stars at the thread level, they are actually an attribute of messages themselves. Changing the starred property of a thread will cause all messages in that thread to be starred or unstarred.
The starred property in the Nylas API is equivalent to stars in Gmail, the IMAP flagged message attribute and Microsoft Exchange message "flags."
Changes to the starred value will propagate to the backend mailbox provider, such as Gmail or Exchange.
Moving a thread
Note about thread folders
This is only supported for accounts where the organization_unit is set to folder. Generally this is all non-Gmail/Google Apps accounts. You can check if an account supports folders by the organization_unit property on the Account object.
The folders attribute of a thread contains an array of folder objects. This is the union of all folders containing messages in the thread. For example, an ongoing discussion thread would likely have messages in the Inbox, Sent Mail, and perhaps the Archive folders.
Your application can move a thread to a new folder by specifying a folder_id, and this will perform the operation on all messages within that thread. Using the Inbox folder ID will move all messages of the thread to the Inbox.
Note that messages in the sent folder are not moved via this batch action.
Modifying labels
Note about labels
This is only supported for accounts where the organization_unit is set to label. Generally this is only Gmail/Google Apps accounts. You can check if an account supports labels by the organization_unit property on the Account object.
Labels are a Gmail-specific way of organizing messages. A message or thread can have multiple labels, enabling more complex queries and email management workflows. The labels attribute of a thread contains an array of [[label]] objects. This is the union of all labels on messages in the thread.
The Nylas platform lets you easily change the labels associated with a message. This change will propagate to the backend mailbox provider (Gmail).
Introduction
Messages are the fundamental object of the Nylas platform, and the core building block for most email applications. They contain several pieces of information, such as when a message was sent, the sender's address, to whom it was sent, and the message body. They can also contain files (attachments), calendar event invitations, and more.
Security notice about message bodies
Although message bodies are HTML, they are generally not safe to directly inject into a web app. This could result in global styles being applied to your app, or the execution of arbitrary JavaScript.
Supported Modifications
Like with Threads, you can make many modifications to the state of messages. You can:
- Modify the unread status
- Star or unstar the message
- Move the message to a different folder
- Modify the message's labels
To make these modifications, make an HTTP PUT request to /messages/{id} with any combination of the body parameters specified here.
The Nylas APIs expose a parsed and sanitized version of the original RFC-2822 email object, combined with state from the mail server, such as unread status and folder location. This results in a simple and universal object type that makes building applications a breeze.
We still provide access to the RFC-2822 raw message object if you want it.
Filtering, Pagination, and Views with Messages
The messages endpoint supports Filters, Pagination, and Views, making it easy to return a subset of messages in specific folder, from a certain address, with a specific subject, etc.
Message Filtering
Messages support various combinations of Filters. Check all the query parameters on the /messages endpoint for more information.
Message Pagination
By default the /messages endpoint will return a maximum of 100 objects. You should paginate through an entire user's mailbox by using the limit and offset URL query parameters. See Pagination for more details about pagination in general. Check all the query parameters on the /messages endpoint for more information.
Message Views
Messages support the use of Views by including the view query parameter in your request.
The expanded message view exposes several additional RFC2822 headers, useful for implementing custom threading or cross-mailbox identification. Pass the view=expanded query parameter when making requests to /messages and /messages/{id}
The following block is added to the message object when using the expanded view.
{
"headers": {
"In-Reply-To": "<evh5uy0shhpm5d0le89goor17-0@mailer.nylas.com>",
"Message-Id": "<84umizq7c4jtrew491brpa6iu-0@mailer.nylas.com>",
"References": ["<evh5uy0shhpm5d0le89goor17-0@mailer.nylas.com>"]
}
}
| Header | Requirement | Description |
|---|---|---|
Message-Id |
optional | Generated by clients while sending messages. It is different from a message's ID returned by the Nylas API (the message object's id). Unlike the id, the Message-Id header is not guaranteed to be unique since it is generated by clients. This field may be null. |
In-Reply-To |
optional | The parent Message-Id to which this message replied. Expected null for messages that are not replies. |
References |
optional | A list of Message-Ids related to a given message. Expected empty for messages which are not replies or related to existing messages. |
A note about expanded message view
Note that these values are unrelated to Nylas object IDs. Because they are provided by clients without validation, there is no guarantee of their accuracy, uniqueness, or consistency.
/messages
Responses are encoded as UTF-8 JSON objects with the following attributes:
| Attribute | Type | Description |
|---|---|---|
id |
string | Globally unique object identifier |
object |
string | A string describing the type of object (value is "message") |
account_id |
string | Reference to parent account object |
thread_id |
string | Reference to parent thread object (all messages have a thread) |
subject |
string | Subject line of the message |
from |
array | List of name+email pairs the message was sent from. This is usually one object, but can be many. |
to |
array | Array of name+email pairs the message was sent to. |
cc |
array | Array of name+email pairs the message was cc'd to. |
bcc |
array | Array of name+email pairs the message was bcc'd to. In received mail this is nearly always empty (for obvious reasons). |
reply_to |
array | Array of name+email pairs replies should be sent to. |
date |
unix timestamp | Timestamp of the date the message was received by the mail server. Note this may be different from the unverified Date header in raw message object. |
unread |
boolean | Message is unread, default for new incoming mail (mutable) |
starred |
boolean | Starred or flagged state (mutable) |
snippet |
string | A shortened plain-text preview of the message body |
body |
string | The full HTML message body. Messages with only plain-text representations are up-converted to HTML. |
files |
array | Array of [[file]] objects, if message includes attachments |
events |
array | Array [[event]] objects, if message includes calendar invites |
folder |
folder object | A single folder object indicating the location of the message, present only if the parent account's organization_unit is folder. This property can be changed to move the message to di |
labels |
array | An list of [[label]] objects, present only if the parent account's organization_unit is "label". These have Gmail-style semantics and can be arbitrarily added and removed from messages. |
/messages/{id}
Unread status
In most systems, incoming mail is given an "unread" status to help the user triage messages. When viewing a message, it's customary for a mail app to automatically modify this "unread" attribute and remove the notification or highlight.
However, unlike its literal meaning, the unread value is mutable, and so it's possible to manually change a message back to "unread." Users will often do this as a reminder to follow up or triage a message later.
The Nylas platform lets you easily change the unread property of a message. This change will propagate to the backend mailbox provider, such as Gmail or Exchange.
Starring (flags)
Stars, also know as "flags", are displayed in nearly every mail app, and are an easy way to highlight a specific message. Although most apps usually show stars at the thread level, they are actually an attribute of messages themselves. (e.g. If one message in a thread is starred, the entire thread is shown as starred.)
The starred property in the Nylas API is equivalent to stars in Gmail, the IMAP flagged message attribute and Microsoft Exchange message "flags."
They Nylas platform lets you easily change the starred property of a message. This change will propagate to the backend mailbox provider, such as Gmail or Exchange.
Moving a message
Note about moving messages
This is only supported for accounts where the organization_unit is set to folder. Generally this is all non-Gmail/Google Apps accounts. You can check if an account supports folders by the organization_unit property on the Account object.
Folders are a common way to organize email messages. A mailbox usually has a set of standard folders like Inbox, Sent Mail, and Trash, along with any number of user-created folders. For more information about types and capabilities, see the [[Folders]] section.
Nylas supports moving messages between folders with a single, simple API call. Note that messages can only exist within one folder.
Modifying labels
Note about modifying message labels
This is only supported for accounts where the organization_unit is set to label. Generally this is only Gmail/Google Apps accounts. You can check if an account supports labels by the organization_unit property on the Account object.
Labels are a Gmail-specific way of organizing messages. A message or thread can have multiple labels, enabling more complex queries and email management workflows.
The Nylas platform lets you easily change the labels associated with a message. This change will propagate to the backend mailbox provider (Gmail).
Raw message contents
Access to the RFC-2822 message object
If you need to access some specific email headers or data that is not exposed by the standard message API, you can request the original raw message data originally downloaded from the mail server. Setting the Accept header to message/rfc822 will return the entire raw message object in RFC 2822 format, including all MIME body subtypes and attachments.
Introduction
Folders behave like normal IMAP or filesystem folders. A Message can only exist within one folder at a time, but a Thread with many messages may span several folders.
Folders are only supported on accounts for which organization_unit is folder. You can check if an account supports labels by the organization_unit property on the Account object.
Folders support basic CRUD operations outlined in the endpoints below.
Using Filters with Folders
The endpoints for Messages, Threads, and Files support Filters for folders using the in query parameter. Simply pass a folder_id, name, or display_name value when calling those endpoints. This conveniently has the same format for both labels and folders, so you application can specify a single filtering request independent of organization unit. See the Filters documentation for more details.
Nested Folders
IMAP has very limited support for nested folders: it encodes a folder's path in its name. For example, the folder Accounting/Taxes will actually be named Accounting.Taxes or even INBOX.Accounting.Taxes depending on your IMAP server. To complicate things, different IMAP servers use different path separators (for example, Taxes.Accounting` on server A will beTaxes\Accounting` on server B).
The Nylas API handles nested IMAP folders transparently. Creating a Taxes/Invoices folder using the API will create a folder with the right path separators (i.e: depending on your server, INBOX.Taxes.Invoices or Taxes/Invoices).
/folders
Responses are encoded as UTF-8 JSON objects with the following attributes:
| Attribute | Type | Description |
|---|---|---|
id |
string | Globally unique object identifier |
object |
string | A string describing the type of object (value is "folder") |
account_id |
string | Reference to parent account object |
name |
string | Standard categories type, based on RFC-6154. Can be one of the following:
|
display_name |
string | Localized name of folder, matching what is presented in their other mail apps. If you are displaying folders, use this instead of name. |
/folders
This endpoint will return a new folder object upon success. An error will be returned if the supplied display_name is too long, or a conflicting folder already exists.
/folders/{id}
The display_name attribute of a folder can modified, and these changes will propagate back to the account provider. Note that the core folders such as INBOX, Trash, etc. often cannot be renamed.
A successful request will return the full updated folder object.
/folders/{id}
Note about deleting folders
Folders must be emptied before being deleted to prevent the accidental deletion of threads. If the requested folder is not empty, the server will respond with a Forbidden error.
Introduction
Labels are equivalent to Gmail labels. Messages can have more than one label, which is popular for users who set up mail filters.
Labels are only supported on accounts for which organization_unit is label. You can check if an account supports labels by the organization_unit property on the Account object.
Labels support basic CRUD operations outlined in the endpoints below.
Using Filters with Folders
The endpoints for Messages, Threads, and Files support Filters for labels using the in query parameter. Simply pass a label id, name, or display_name value when calling those endpoints. This conveniently has the same format for both labels and folders, so you application can specify a single filtering request independent of organization unit. See the Filters documentation for more details.
/labels
Responses are encoded as UTF-8 JSON objects with the following attributes:
| Attribute | Type | Description |
|---|---|---|
id |
string | Globally unique object identifier |
object |
string | A string describing the type of object (value is "label") |
account_id |
string | Reference to parent account object |
name |
string | Standard categories type, based on RFC-6154. Can be one of the following:
|
display_name |
string | Localized name of label, matching what is presented in their other mail apps. If you are displaying labels, use this instead of name. |
/labels
You can easily create new labels on accounts where the organization_unit is set to label. Generally this is only Gmail/Google Apps accounts.
This endpoint will return a new label object upon success. An error will be returned if the supplied display_name is too long, or a conflicting label already exists.
/labels/{id}
The display_name attribute of a label can modified, and these changes will propagate back to the account provider. Note that the core labels such as Inbox, Trash, etc. cannot be renamed.
A successful request will return the full updated label object.
/labels/{id}
Labels can be deleted by issuing a DELETE request to the label’s URI. A label can be deleted even if it still has associated messages.
Introduction
A draft is a special kind of message which has not been sent, and therefore its body contents and recipients are still mutable. The drafts endpoints let you read and modify existing drafts, create new drafts, send drafts, and delete drafts. Draft modifications are propagated to the mailbox provider in all cases, excluding Microsoft Exchange systems.
/drafts
Responses are encoded as UTF-8 JSON objects with the following attributes:
| Attribute | Type | Description |
|---|---|---|
id |
string | Globally unique object identifier |
object |
string | A string describing the type of object (value is "draft") |
account_id |
string | Reference to parent account object |
thread_id |
string | Reference to parent thread object. If this is a new draft, the thread will be empty. |
subject |
string | Subject line of the draft |
reply_to_message_id |
string | ID of a message this draft is a reply to, allowing the sending API to include threading-specific headers for other mail clients |
from |
array | Array containing a single name+email pair to set as the "from" header. (See "Aliases" below.) |
reply_to |
array | Array of name+email pairs to set an alternative Reply-To header in the final sent message |
to |
array | Array of name+email pairs of recipients |
cc |
array | Array of name+email pairs of recipients to be cc'd |
bcc |
array | Array of name+email pairs of recipients to be bcc'd |
date |
unix timestamp | Timestamp of the last modification of the draft |
unread |
boolean | Believe it or not, drafts also have an unread state |
starred |
boolean | Starred or flagged state (mutable) |
snippet |
string | A shortened plain-text preview of the draft body |
body |
string | The full HTML draft body text |
files |
array | Array of file objects, if draft includes attachments |
events |
array | Array event objects, if draft includes calendar invites |
folder |
folder object | A single folder object indicating the location of the draft, present only if the parent account's organization_unit is folder. Customarily this is a folder where name is drafts, but not always. |
labels |
array | An list of label objects, present only if the parent account's organization_unit is "label". These have Gmail-style semantics and can be arbitrarily added and removed from messages. |
version |
integer | Incrementing value related to draft updates. You can use this to compare revisions, or invalidate your local cache. |
/drafts
Note about creating drafts
All body params optional though if omitted, an empty draft will still be created. A successful response will contain the newly created draft object. At least one recipient in to, cc, or bcc must be specified before sending.
Attachments
Creating a draft will fail if the files with the referenced file_ids have not been uploaded. See Files for more details on how to upload and reference attachments.
Replies
If the draft is a response to an existing message, you should provide the message's ID as a reply_to_message_id attribute and omit the subject parameter. Note that you still must explicitly specify the message's recipients in the to, cc or bcc fields of the post body. (This is by design to prevent any ambiguity about whom the message will be sent to.)
Aliases
If you would like to use an alias for sending and/or receiving emails, you can optionally set the from or reply_to fields. Note that if the given address is actually not an alias, most SMTP servers will either reject the message or silently replace it with the primary sending address.
If the from and reply_to fields are omitted, the account's default sending name and address will be used.
/drafts/{id}
The request body must contain the version of the draft you wish to update. Other fields are optional and will overwrite previous values.
Updating a draft returns a draft object with the same id but different version. When submitting subsequent send or save actions, you must use this new version.
/drafts/{id}
Drafts can be deleting by issuing a DELETE request to the draft’s URI. The request body must contain a JSON object specifying the latest version, or deletion will fail. This is to prevent accidental deletion of drafts which have been updated.
Introduction
The Nylas platform provides two ways to send messages: either through sending an existing draft, or by sending directly. Both systems send mail through the account's original SMTP/ActiveSync gateway, just as if they were sent using any other app. This means messages sent through Nylas have very high deliverability (i.e. not landing in Gmail's promotions tab), but may also be subject to backend provider rate-limiting and abuse detection. Make sure to send wisely!
Sending timeouts
A successful request to the send endpoint can sometimes take up to two minutes for self-hosted Exchange accounts, though the average send time is around 2 seconds. We recommend that you set a minimum timeout of 150s to ensure that you receive a response from us.
All sending operations are synchronous, meaning the request will block until the draft has succeeded or failed. In the event of failure, the sending API will not automatically retry.
We recommend that you apply backoff when HTTP 503s are returned. Your app may need to wait 10-20 minutes, or SMTP servers may continue to refuse connections for a particular account. For some providers like Gmail, there are hard limits on the number of messages you can send per day.
If large-volume sending continues to fail for your application, we recommend switching to a transactional sending service like Mailgun, Sendgrid, Mandrill, or Amazon SES.
Sending Errors
Sometimes message delivery can fail if the user’s email gateway rejects the message. This could happen for a number of reasons, including illegal attachment data, bad credentials, or rate limiting. If your message is sent successfully, the server will respond with an HTTP response code of 200 OK. If your message couldn’t be sent, the server will respond with an appropriate error code.
| Status Code | Reason | |
|---|---|---|
200 |
OK | Your message was sent. |
400 |
Bad Request | Your request was malformed, or contained an invalid parameter. The most common issue is invalid JSON. |
402 |
Message Rejected | The mail provider rejected your message because of its content or recipients. Note this means that your message may have been delivered to only a subset of participants if the message includes "Sending to at least one recipient failed". |
403 |
Unauthorized | The server was unable to authenticate with the user's mail provider. Re-authenticate the user and try again. |
422 |
Mail provider error | An error occurred while the mail provider was sending the message. See the server_error in the response body JSON for more information. |
429 |
Quota Exceeded | The user has exceeded their mail provider's sending quota. Unfortunately there is no reliable way to determine these limits. Wait and try again later. |
503 |
Service Unavailable | There was an error connecting to the user's mail provider. Wait and try again. |
In addition, the response body contains a JSON object with information about the specific error, including the following attributes:
| Status Code | Type | Reason |
|---|---|---|
type |
string | Error type |
message |
string | A brief human-readable description of the error. |
server_error |
string (optional) | The original error returned by the user's mail server. |
See Errors for more information about error responses and how to handle them.
Sending inline images
You can send image attachments inline in the body of your emails. Simply reference one of the attached file_ids in an img tag. For example, if one of your attachments has file_id = '472ypl5vqbnh0l2ac3y71cdks' then you could display it inline like in the example to the right. Don't forget to prepend the file_id with cid: for the src attribute.
<div>
<p>Before image</p>
<img src="cid:472ypl5vqbnh0l2ac3y71cdks">
<p>After image</p>
</div>
Sending directly
Messages can be sent directly, without saving them as drafts beforehand.
A note on sending directly
All of these attributes are individually optional. However, sending a message will fail if there is no recipient specified in either to, cc, or bcc.
A successful response will include a full new Message object.
Sending raw MIME
You can also send via submitting raw MIME message object. The submitted object is entirely preserved, except the bcc header which is removed. Additional headers used by Nylas may be added.
If the message is in reply to an existing message, you should make sure to include the In-Reply-To and References headers. These headers are set to the Message-Id header of the message you are replying to and Message-Id header of related messages, respectively. For more details, see this excellent article by djb.
A successful response will include a full new Message object.
Introduction
The files endpoint manages data attached to messages. It allows you to download existing attachments from messages and threads, as well as upload new files to be sent. Note that before creating or modifying a draft to include an attachment, you must upload it via this API and use the returned file ID.
Actual attached files may be relatively large (upwards of 25MB), so this API has separate endpoints for requesting file Metadata and Downloading the actual file.
Files can be downloaded by appending /download to the file metadata URI. If available, the response will include the filename in the Content-Disposition header.
The Upload endpoint is used to transfer files to Nylas, which must be done before adding them to a draft message. Data should be sent as multipart-form data with a single field named file.
Filtering and Files
This endpoint supports Filters and Pagination, which allow you to fetch multiple files matching specific criteria and iterate through a large set of files. See the query parameters in the endpoints below to see what kind of filtering is supported.
Popular Content-Type values corresponding to popular file extensions
| Document | Content-Type |
|---|---|
| PNG images | image/png |
| JPEG images | image/jpeg |
| PDF documents | application/pdf |
| ZIP archives | application/zip |
| MS Word (.doc) | application/msword |
| MS Excel (.xls) | application/vnd.ms-excel |
| MS Powerpoint (.ppt) | application/vnd.ms-powerpoint |
| MS Word (.docx) | application/vnd.openxmlformats-officedocument.wordprocessingml.document |
| Microsoft Powerpoint (.pptx) | application/vnd.openxmlformats-officedocument.presentationml.pesentation |
| Microsoft Excel (.xlsx) | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet |
Here is a more complete list of Content Types.
/files
Access to file metadata
Responses are encoded as UTF-8 JSON objects with the following attributes:
| Attribute | Type | Description |
|---|---|---|
id |
string | Globally unique object identifier |
object |
string | A string describing the type of object (value is "file") |
account_id |
string | Reference to parent account object |
filename |
string | Name of the file, if available |
size |
integer | Size of the file, in bytes |
content_type |
string | Content-Type of the file, sometimes also called Internet media type or MIME type. |
message_ids |
array | Array of identifiers for messages that contain this attachment. (Not guaranteed to be a complete set) |
content_id |
string | Included if file was attached as a inline media. Using this value, your app can locate the associated cid URL in the message body and embed the resource. |
/files
Uploading files
This endpoint is used to transfer files to Nylas, which must be done before adding them to a draft message. Data should be sent as multipart-form data with a single field named file.
A successful upload will return an array with a single file object. This object's ID may be attached to a Draft by appending it to file_ids array of the draft object. Additionally, if the object is an image it may be included inline in the body of the email by referencing it inside an img tag like so: <img src="cid:file_id">. See Sending for more info about inline images.
Introduction
Each account connected to Nylas can have zero or more calendars, and each calendar has a collection of individual events. The calendar object is very simple, and mostly serves as a container for events. The read_only flag on a calendar indicates whether or not you can modify its properties or make changes to its events.
The calendar endpoint supports Pagination (although most users have only a few calendars).
Provider-backed calendars
The primary calendar of the account is usually named the same as the email address, or sometimes simply called "Calendar." Users may also have other custom calendars, or access to shared team calendars. See [[events]] for more details.
Events can be viewed, added, modified, and deleted on calendars where read_only is false. Changes are automatically synced back to the provider.
The "Emailed events" calendar
All accounts also include a special calendar called "Emailed events" which contains event invitations that have been sent to the user's mailbox. This calendar is read-only, meaning events cannot be added, updated, or deleted. However, the events can be RSVP'd to. See the [[events]] documentation for details.
/calendars
Responses are encoded as UTF-8 JSON objects with the following attributes:
| Attribute | Type | Description |
|---|---|---|
id |
string | Globally unique object identifier |
object |
string | A string describing the type of object (value is "file") |
account_id |
string | Reference to parent account object |
name |
string | Name of the Calendar |
description |
string | Description of the Calendar |
read_only |
boolean | True if the Calendar is read only |
Introduction
Events are objects within a calendar, generally supporting all features of modern scheduling apps. Using the calendar APIs, your application can schedule events, send meeting invitations, RSVP, and more.
Events supports Filtering and Pagination
The events endpoint supports filters, which allow you to fetch multiple events matching specific criteria, as well as pagination. See the Events endpoint query parameters for specific query parameters you can use to filter Events.
Event subobjects
There are various subobjects within the Event object itself. To learn more about each of these subobjects see Event Subobjects
Recurring events
Using the expand_recurring URL parameter is an easy way to expand recurring events server-side so your application doesn't need to deal with RRULEs. Note that when using this query parameter, you must also use filters to specify a time range.
Currently, these expanded instances of recurring events are read-only. If the recurring event has individual modifications (overrides), such as a one-off time change, we will return these as individual events regardless of whether expand_recurring is set or not.
If expand_recurring is not set, we will return any one-off cancellations in addition to the base event, for apps that are expanding the recurrence client-side. A cancellation has the field cancelled set to true.
/events
Note about event sorting
Events are always sorted by their start date.
Responses are encoded as UTF-8 JSON objects with the following attributes:
| Attribute | Type | Description |
|---|---|---|
id |
string | Globally unique object identifier |
object |
string | A string describing the type of object (value is "event") |
account_id |
string | Reference to parent account object |
calendar_id |
string | Reference to the parent calendar object |
title |
string | Title of the event, usually kept short. |
description |
string | Description of the event, which may contain more details or an agenda. |
when |
subobject | One of four subobjects corresponding to the time and duration of an event: time, timespan, date, or datespan. See below for more details. |
location |
string | Location, such as a physical address or meeting room name |
owner |
string | The owner of the event, usually their email or name and email. |
participants |
array | Array of others invited to the event. Keys are email, name, status. Participants may also be rooms or resources. See below for more details. |
status |
string | Either confirmed, tentative, or cancelled. |
read_only |
boolean | Whether the event can be modified |
busy |
boolean | On shared or public calendars, whether to show this event's time block as available or not. (Also called "transparency" in some systems.) |
recurrence |
subobject | Included if the event is a master recurring event. See below for the subobject definition |
master_event_id |
string | Only included in exceptions (overrides) to [[recurring events]], the id of the recurring event. |
original_start_time |
unix timestamp | Only included in exceptions (overrides) to [[recurring events]], the start time of the recurring event. |
/events
Note about event sorting
Events are always sorted by their start date.
Responses are encoded as UTF-8 JSON objects with the following attributes:
| Attribute | Type | Description |
|---|---|---|
id |
string | Globally unique object identifier |
object |
string | A string describing the type of object (value is "event") |
account_id |
string | Reference to parent account object |
calendar_id |
string | Reference to the parent calendar object |
title |
string | Title of the event, usually kept short. |
description |
string | Description of the event, which may contain more details or an agenda. |
when |
subobject | One of four subobjects corresponding to the time and duration of an event: time, timespan, date, or datespan. See below for more details. |
location |
string | Location, such as a physical address or meeting room name |
owner |
string | The owner of the event, usually their email or name and email. |
participants |
array | Array of others invited to the event. Keys are email, name, status. Participants may also be rooms or resources. See below for more details. |
status |
string | Either confirmed, tentative, or cancelled. |
read_only |
boolean | Whether the event can be modified |
busy |
boolean | On shared or public calendars, whether to show this event's time block as available or not. (Also called "transparency" in some systems.) |
recurrence |
subobject | Included if the event is a master recurring event. See below for the subobject definition |
master_event_id |
string | Only included in exceptions (overrides) to [[recurring events]], the id of the recurring event. |
original_start_time |
unix timestamp | Only included in exceptions (overrides) to [[recurring events]], the start time of the recurring event. |
/events/{id}
Note about read_only and recurring event updates
Updating and deleting an event is managed in a similar fashion to other endpoints with the restriction that read_only events cannot be updated and events cannot be updated or deleted from a read_only calendar.
Furthermore, updates cannot be made to recurring events yet.
/events/{id}
Events can also be deleted from the calendar. Pass the notify_participants URL parameter to notify those who have been invited that the event has been cancelled.
Event Subobjects
The Event object has various subobjects that are detailed below.
Participants
The participants attribute is returned as an array of dictionaries corresponding to participants. These include the keys:
| Attribute | Type | Description |
|---|---|---|
name |
string | The participant's full name (optional) |
email |
string | The participant's email address |
status |
string | Attendance status. Allowed values are yes, maybe, no and noreply. Defaults is noreply |
comment |
string | A comment by the participant (optional) |
"participants": [
{
"comment": null,
"email": "kelly@nylas.com",
"name": "Kelly Nylanaut",
"status": "noreply"
},
{
"comment": null,
"email": "sarah@nylas.com",
"name": "Sarah Nylanaut",
"status": "no"
}
]
Time
The time subobject corresponds a single moment in time, which has no duration. Reminders or alarms would be represented as time subobjects.
| Attribute | Type | Description |
|---|---|---|
object |
string | A string describing the type of object (value is "time") |
time |
unix timestamp | A UNIX timestamp (UTC) |
{
"object": "time",
"time": 1408875644
}
Timespan
A span of time with a specific beginning and end time. An hour lunch meeting would be represented as timespan subobjects.
| Attribute | Type | Description |
|---|---|---|
object |
string | A string describing the type of object (value is "timespan") |
start_time |
unix timestamp | Starting time of the event |
end_time |
unix timestamp | Ending time of the event |
{
"object": "timespan",
"start_time": 1409594400,
"end_time": 1409598000
}
Date
A specific date for an event, without a clock-based starting or end time. Your birthday and holidays would be represented as date subobjects.
| Attribute | Type | Description |
|---|---|---|
object |
string | A string describing the type of object (value is "date") |
date |
date | Date of occurance in ISO 8601 format. |
{
"object": "date",
"date": "1912-06-23"
}
Datespan
A span of entire days without specific times. A business quarter or academic semester would be represented as datespan subobjects.
| Attribute | Type | Description |
|---|---|---|
object |
string | A string describing the type of object (value is "datespan") |
start_date |
date | Start date in ISO 8601 format. |
end_date |
date | End date in ISO 8601 format. |
{
"object": "datespan",
"start_date": "1815-12-10",
"end_date": "1852-11-27"
}
Recurrence
If requesting events without expand_recurring, the events endpoint will only return the 'master' recurring event and only if it falls within the requested time range. The recurrence attribute contains recurrence info in RRULE form; this tool is helpful in understanding the RRULE spec.
| Attribute | Type | Description |
|---|---|---|
timezone |
string | IANA time zone database formatted string (e.g. America/New_York) |
rrule |
array | Array of recurrence rule (RRULE) strings. See RFC-2445 |
{
"rrule": [
"RRULE:FREQ=WEEKLY;BYDAY=MO"
],
"timezone": "America/New_York"
},
RSVPing to invitations
The RSVP endpoint allows you to send attendance status updates to event organizers. Note this is only possible for events that appears on the “Emailed events”, which are calendar invitations.
If the RSVP is successful, the event object is returned with your RSVP participant status updated. This endpoint is idempotent: this means that only one email will be sent when you issue the same request with the same body multiple times.
RSVP Errors
Behind the scenes, RSVPs work by sending an email back to the event organizer in iMIP format. Therefore, errors when RSVPing to events follow the same status codes as sending errors.
Introduction
The Nylas API provides access to the user's contacts, making it easy to add contact autocomplete, address book integration, and more to your application.
Note that contacts are currently read-only and supports both Filtering and Pagination
The Contact object
Responses are encoded as UTF-8 JSON objects with the following attributes:
| Attribute | Type | Description |
|---|---|---|
id |
string | Globally unique object identifier |
object |
string | A string describing the type of object (value is "contact") |
account_id |
string | Reference to parent account object |
name |
string | Full name of contact |
email |
string | Email address of contact |
For Microsoft Exchange contacts, we also provide phone numbers associated with the contact. This is an experimental feature so the format may change in a backward incompatible way in the future.
For this reason, you should not rely on using it in production apps without accounting for format changes or the possibility of the attribute not always being returned in the response.
| Attribute | Type | Description |
|---|---|---|
phone_numbers |
array | Array of zero or more phone numbers, each represented as a dict with the keys "type" and "number" (values are strings) |
The values for number and type are unformatted strings so any formatting, such as phone number formatting should be done on the client side. Note that duplicates may also exist.
Using Filters with Contacts
Contacts only supports one filter query parameter that searches for the contact's email address. See getting contacts for detailed info about using this filter.
Search Overview
The search sub-endpoint is used to run a full-text search that is proxied to the account's provider. Results are matched with objects that have been synced, and are then returned.
The search endpoint returns 40 results by default. This endpoint supports Pagination so your application can request more objects, or iterate through all results.
For details on the query syntax for the most commmon providers, please see Google, Exchange/Outlook, Yahoo, and Generic IMAP.
Webhooks Overview
Webhooks allow your application to receive notifications when certain events occur. For example, when a new email is received, Nylas will make a POST request to your URI endpoint letting you know information about the new message. You can specify what events you'd like to be notified about in the developer dashboard.
Need help getting started with webhooks?
The Webhook object
The webhook object links a callback URL to the types of notifications that should be sent to it. You can programmatically access information about the state of your webhook using the following urls.
| Attribute | Type | Description |
|---|---|---|
id |
string | Globally unique object identifier |
application_id |
string | Reference to parent application object |
callback_url |
string | The URL that notifications are posted to |
state |
string | The state of the webhook. See the table below for possible values |
triggers |
array | Array containing a set of triggers describing what sort of notifications this webhook should receive. See the triggers table in "Creating a Webhook" for possible values |
version |
string | String describing what version the webhook is on |
A webhook can have the following states:
| State | Description |
|---|---|
active |
We are sending data for this webhook and receiving 200 reponses |
inactive |
The webhook has been disabled from the developer console and we are not sending data for it |
failing |
We are trying to send data, but the callback URL is returning non-200 responses or timing out |
failed |
We have receieved the maximum number of non-200 responses and are no longer sending data for this webhook |
Note about failed webhooks
If your webhook reaches the failed state, you can re-activate it from the developer console. However, we will not send any past data once the webhook is re-activated. You will need to manually resync any data that was lost during that time.
Creating a Webhook
Webhooks for an application are configured from the Nylas Developer Dashboard. To configure a new webhook, go to the "Webhooks" section of your application and select "Add Webhook". You will need to provide:
The full URI for the webhook. Since this is the endpoint the Nylas servers send notifications to, the URI must be accessible from the public internet for the webhook to work. It must be an HTTPS endpoint as well. The endpoint is verified by sending a verification request.
The triggers to receive notifications for. The list of available triggers are:
| Trigger | Description |
|---|---|
account.connected |
An account has been connected to your app |
account.running |
An account is syncing and running properly |
account.stopped |
An account was stopped or cancelled |
account.invalid |
An account has invalid credentials and needs to re-authenticate |
account.sync_error |
An account has a sync error and is no longer syncing |
message.created |
A new message was sent or received |
message.opened |
A tracked message has been opened by a message participant |
message.link_clicked |
A link in a tracked message has been clicked by a message participant |
thread.replied |
A participant replied to a tracked thread |
You can create more than one webhook for your application; however, the webhook endpoints cannot be the same. For example, you may create a webhook to receive notifications for the message.created trigger, and another to receive notifications for the account.connected and account.stopped triggers, but the webhooks must have different callback URIs.
Verification Request
Nylas will check to make sure your webhook is valid by making a GET request to your endpoint with a challenge query parameter when you add the endpoint to the developer dashboard (or anytime you set the webhook state to active). All you have to do is return the value of the challenge query parameter in the body of the response. Make sure you aren't returning anything other than the exact value of the challenge parameter. Your application has up to ten seconds to respond to the verification request. The verification request is not retried automatically.
Enabling and disabling a Webhook
Webhooks are set to "active" by default. To disable a webhook, go to the Webhooks section of your application and change the webhook's state to inactive.
Receiving Notifications
Once a webhook has been successfully created, Nylas will send an HTTPS POST request to the configured endpoint when an event of interest occurs. If multiple changes occur at the same time, they may be included in the same notification.
A request that times out or results in a non-HTTP 200 response code is retried once every 10 minutes, up to 60 times. Failing that, the webhook is retired and its state set to "failed".
Note about webhooks response code
You must return an exact HTTP response code of 200, otherwise Nylas will consider the POST a failure and will retry the request (even if you return a 203, for example).
Each request made by Nylas includes an X-Nylas-Signature header. The header contains the HMAC-SHA256 signature of the request body, using your client secret as the signing key. This allows your app to verify that the notification really came from Nylas.
The body of the request is in UTF-8 JSON format and contains details about the event.
Notification format
The webhook endpoint will receive a list of changes for the triggers specified while creating the webhook. Note that for security reasons, the actual changes are not included. Instead, the response contains the trigger type and object id for each change; you can retrieve the changed object with the corresponding API endpoints.
The body of the POST request is encoded as a UTF-8 JSON object with the following attributes:
| Attribute | Type | Description |
|---|---|---|
deltas |
array | Array of delta objects |
Each delta object has the following attributes:
| Attribute | Type | Description |
|---|---|---|
date |
unix timestamp | Timestamp when the change occurred |
type |
string | The trigger for this notification |
object |
string | The changed object type |
object_data |
object | Contains the changed object's object type, account_id, object id and an attributes sub-object |
The attributes sub-object has extra information about the object. Currently, attributes is only included in object_data for message.created triggers.
| Attribute | Type | Description |
|---|---|---|
received_date |
unix timestamp | Timestamp when the message was originally received |
thread_id |
string | The thread_id that this message belongs to |
For more information about message tracking and the corresponding metadata object type, see Message Tracking.
Message Tracking Overview
The Nylas API offers several ways of tracking different types of actions that may happen to a message or thread. For example, it's possible to detect when an email message has been opened by the recipient.
We'll notify you when these actions occur by sending a webhook notification to your server. If you haven't set up webhooks yet, click here. Make sure that you've enabled all the appropriate triggers you'd like to be notified about in your developer dashboard before sending a message with tracking enabled.
There are three different ways you can track a message or thread and you can use any combination of these tracking features together. All you have to do is include a tracking attribute when you send a message through the /send endpoint.
Enabling Tracking
To enable tracking for a message, include a tracking attribute alongside the other attributes when sending a message. You can include the tracking object when sending a draft or when sending directly.
The tracking object looks like this:
| Attribute | Type | Description |
|---|---|---|
links |
boolean | True enables link tracking |
opens |
boolean | True enables message open tracking |
thread_replies |
boolean | True enables thread reply tracking |
payload |
string | An optional string that allows you to keep track of additional information. This string will be included in the webhook notification. |
curl -X POST -H "Authorization: Basic yourBasicAuth" -d '{
"reply_to_message_id": "84umizq7c4jtrew491brpa6iu",
"body" : "Please click this: <a href='https://nylas.com/'>click</a>",
"subject": "New Site",
"to": [
{
"name": "Nylas",
"email": "support@nylas.com"
}
],
"tracking": {
"links": true,
"opens": true,
"thread_replies": false,
"payload": "Any string you want!!"
}
}' "https://api.nylas.com/send"
Understanding Tracking Notifications
Once a user performs an action on a message that you've enabled tracking for, like opening the message, Nylas will make a POST request to your webhook endpoint with delta information about the action that occurred.
object_data will contain a metadata sub-attribute that has information about the action. To see the more general structure of the webhook notification, click here.
More detailed information about each of the notifications and their specific metadata sub-attributes are below.
Link Tracking
When you send a message with link tracking enabled you'll be notified whenever any of the recipients click on tracked links in that message.
To enable link tracking for a message, set links to true in the tracking attribute when sending the message through the /send endpoint. See here for more information about creating the tracking attribute.
Behind the scenes, Nylas will rewrite all HTML links with a new URL that helps us track link clicks.
Note about link tracking
It's important to note that you must wrap links in <a> tags for them to be tracked. Most email clients automatically "linkify" things that look like links, like 10.0.0.1, tel:5402502334, or apple.com. For links to be tracked properly, you must linkify the content before making a request to /send
metadata is a sub-object of object-data
| Attribute | Type | Description |
|---|---|---|
sender_app_id |
string | The sender's Nylas application id |
link_data |
array | An array of objects with information about number of clicks per link |
payload |
string | An optional string that you can include when enabling tracking for the message to contain arbitrary data |
message_id |
string | Nylas message_id of the message |
recents |
array | An array of the most recent link-click events |
link_data is a sub-object of metadata
| Attribute | Description |
|---|---|
url |
The url that was clicked |
count |
Number of times the url was clicked |
recents is a sub-object of metadata
| Attribute | Description |
|---|---|
id |
An ID unique to each message that increments with each click |
ip |
IP address of the user that clicked the link |
user_agent |
User agent of the user that clicked the link |
link_index |
Corresponds to an entry in link_data |
The recents field will have the last 50 events. These will have ids in order to help parse which events have already been processed. The id s are only unique within a particular recents array, and there is a separate recents array for each message/trigger pair. So, for example, opening message A, clicking on a link in message A, and opening message B will all have an id of 0. Opening message A again will have id 1.
{
"deltas": [
{
"date": 1471630848,
"type": "message.link_clicked",
"object": "metadata",
"object_data": {
"object": "metadata",
"id": "NYLAS_METADATA_ID",
"account_id": "EMAIL_ACCOUNT_ID",
"metadata": {
"sender_app_id": "SENDER_APP_ID",
"link_data": [
{"url": "apple.com", "count": 2},
{"url": "apple.com", "count": 0},
{"url": "nylas.com", "count": 10},
],
"payload": "hello world",
"message_id": "NYLAS_MESSAGE_ID",
"recents": [{
"id:" 0,
"ip": "0.0.0.0",
"user_agent": "chrome",
"link_index": 2
}, ]
}
}
}
]
}
Open Tracking
When you send a message with open tracking enabled you'll be notified whenever any of the recipients open that message.
To enable open tracking for a message, set opens to true in the tracking attribute when sending the message through the /send endpoint. See here for more information about creating the tracking attribute.
A note about open tracking
When you enable open tracking, a 1px by 1px <img> tag will be added to the bottom of the message body. <img> tags are the most reliable way of implementing email read tracking, and Nylas uses industry-wide best practices to ensure images are loaded by the majority of recipients. However, open tracking may not work in some scenarios when users have "Automatically Load Images" disabled in their mail client.
metadata is a sub-attribute of object-data
| Attribute | Description |
|---|---|
sender_app_id |
The sender's Nylas application id |
count |
The number of times this message has been opened |
payload |
An optional string that you can include when enabling tracking for the message to contain arbitrary data |
message_id |
Nylas message_id of the message |
recents |
An array of the most recent link-click events |
{
"deltas": [
{
"date": 1471630848,
"type": "message.opened",
"object": "metadata",
"object_data": {
"object": "metadata",
"id": "NYLAS_METADATA_ID",
"account_id": "EMAIL_ACCOUNT_ID",
"metadata": {
"sender_app_id": "SENDER_APP_ID",
"count": "OPEN_COUNT",
"payload": "{myCustom: 'data'}",
"message_id": "NYLAS_MESSAGE_ID",
"recents": [{
"id:" 0,
"ip": "0.0.0.0",
"user_agent": "chrome"
}, ]
},
}
}
]
}
Reply Tracking
When you send a message with reply tracking enabled you'll be notified whenever any participant of the corresponding thread responds to that thread.
To enable reply tracking for a thread, set thread_replies to true in the tracking attribute when sending the message through the /send endpoint. See here for more information about creating the tracking attribute.
metadata is a sub-attribute of object-data
| Attribute | Description |
|---|---|
sender_app_id |
The sender's Nylas application id |
payload |
An optional string that you can include when enabling tracking for the message to contain arbitrary data |
message_id |
Nylas message_id of the new message |
reply_to_message_id |
Nylas message_id of the message that the new message is replying to |
thread_id |
Nylas thread_id |
from_self |
Boolean that indicates whether the reply came from the account that enabled this tracking or not |
timestamp |
Timestamp in UTC Unix seconds |
{
"deltas": [
{
"date": 1471630848,
"type": "thread.replied",
"object": "metadata",
"object_data": {
"object": "metadata",
"id": "NYLAS_METADATA_ID",
"account_id": "EMAIL_ACCOUNT_ID",
"metadata": {
"sender_app_id": "VELOCIFY_APP_ID",
"payload": "{myCustom: 'data'}",
"message_id": "NYLAS_MESSAGE_ID",
"reply_to_message_id": "NYLAS_REPLY_TO_MESSAGE_ID",
"thread_id": "NYLAS_THREAD_ID",
"from_self": true,
"timestamp": 1471630848,
},
}
}
]
}
Introduction
The Nylas Sync Engine builds a transaction log that records every change as it synchronizes your users' mailboxes. Your application can use these changes, exposed through the Delta endpoint, to build email applications that process new data quickly without fetching an index of the user's mailbox or performing a large number of API calls.
To use the Delta API, your application needs to maintain a sync cursor, a record of the last change you successfully processed. Each time you perform a sync, you process the deltas provided by the API and update your stored cursor.
Obtaining a Delta cursor
The first time you sync using the delta API, you need to obtain a cursor. In subsequent requests, your app will pass this cursor and receive changes (i.e. deltas) from the moment you request the cursor onwards.
A note about cursors
Note that the first time you request a cursor for an account starting its initial sync with Nylas you will receive deltas for the account's entire email history.
Requesting a set of Deltas
Each time your application syncs with Nylas, you provide the cursor indicating your position in the user's mailbox history. The API request below returns a set of JSON objects representing individual changes to the user's mailbox: folder and label changes, new messages, etc.
After processing these deltas, your application should update its stored cursor to the value of cursor_end in the response. The deltas endpoint often only returns a subset of deltas available, so it's important to continue requesting deltas until your application receives a value for cursor_end that is identical to cursor_start. This indicates that you have requested all delta events up to the current moment.
The delta for an object will condense changes to the latest version of the object since the requested cursor. This means that, if an object was modified and then deleted, only a delta representing the "delete" event will be returned.
You can see more detail about how to request a set of Deltas here.
Note about event deletions
For event objects that have been deleted, the event parameter will be set to "modify" and the status attribute set to "cancelled", matching the semantics of the Event objects.
Long-polling Delta updates
Normally a request with the latest cursor will immediately return an empty list with no deltas. However, you can use the long-polling endpoint to instruct the server to hold open the request until either new changes are available, or a timeout occurs. This behavior can be used to provide real-time updates on platforms that do not support partial response parsing, such as web browsers.
You can see more detail about how to use long-polling with Deltas here
Streaming Delta updates
If you are building a server-side application where you can parse incoming data before a request has finished, then you should use the streaming delta endpoint, which allows you to process changes in real time without polling. This will start a HTTP connection that will return deltas starting from that cursor, and then keep the connection open and continue to stream new changes.
You can see more detail about how to stream Delta updates here
If you need to sync a large number of accounts you should use webhooks or long-polling delta updates instead. Since there isn't any mechanism to throttle incoming data from the streaming endpoint, a large number of accounts could produce an amount of data that is too intensive to process. Delta streaming is also not suitable for client-based JavaScript applications. In both of these cases you should use webhooks or the long-polling delta endpoint.
Expanded Delta View
Adding view=expanded to the request expands thread and message objects in the response to include additional information.
Thread objects are expanded to contain message and draft sub-objects and will remove message_ids and draft_ids. Note the message and draft sub-objects do not include a body parameter.
Message objects are expanded to include several additional RFC2822 headers. For more details see the Expanded Message View.
Using Filters with Deltas
The delta endpoint supports a modified version of Filters, which allows applications to request only changes to a specific object type by using exclude_types and include_types. See the query parameters in the endpoints below for more detail.
Note about Delta filtering
Note that specifying both exclude_types and include_types will result in an error.
Requesting a set of deltas
Each element of the delta attribute in the response contains the following fields:
| Attribute | Type | Description |
|---|---|---|
cursor |
string | The cursor value for this delta. |
object |
string | The object type of the changed object. (message, thread, etc.) |
id |
string | The id of the changed object |
event |
string | The type of change. Either create, modify, or delete. |
attributes |
The current state of the object. Note this may be different from the state when the delta change actually happened. |
Filters
Filters allow you to narrow a request based on specific parameters. Generally the more specific you can make the requests, the faster they perform, so it's important to use filters whenever possible.
Filters may be appended to API requests on Messages, Threads,Files, and Events. There is also limited filter support for Contacts and Deltas.
Note that values must use percent-encoding (also known as URL encoding). See the specific endpoint documentation for details on exact syntax and supported parameters.
Filters do not currently support wildcards, such as from=*@expedia.com. Providing multiple values for a single filter is also unsupported. If you're looking for more generalized parameter matching, check out the Search APIs.
Pagination
Even though a user's mailbox usually has thousands upon thousands of items, most Nylas API endpoints return a maximally fixed number of objects for performance reasons.
Your application can increase performance by including a limit parameter to request fewer objects. Using both the limit and offset parameters allows you to easily paginate through a large number of objects.
Note that if a request returns fewer objects than the limit parameter, there are no more items available to return.
| Query Parameter | Type | Description |
|---|---|---|
limit |
integer | Number of objects to return. Often defaults to 100. If set too high, requests may fail to prevent excessively large response bodies. |
offset |
integer | Zero-based offset from default object sorting. |
If you are building an application that intends to maintain a cache of the user's data, such as a full-featured mail client, we recommend using the Webhooks or Deltas endpoints to avoid repeatedly paginating over all objects.
Views
Instead of returning all data about an object, the following views allow you to customize the response for any endpoint. They can be combined with Filters. The following endpoints support view parameters: Threads, Messages, Drafts, Folders, Labels, Files, Calendars, Events, and Contacts.
Return only the IDs of objects.
Supported by Threads, Messages, Drafts, Folders, Labels, Files, Calendars, Events, and Contacts.
curl https://api.nylas.com/messages?thread_id=aqb0llc2ioo0bclh7uxkim9z6&view=ids
[
"f594seo6izjks2s7qxjbwquol",
"3a95fq0askqgj7mnh6i281ahz",
"4vfg8p1om177q2cfx9sselkea"
]
Return the number of objects in the collection being queried.
Supported by Threads, Messages, Drafts, Folders, Labels, Files, Calendars, Events, and Contacts.
curl https://api.nylas.com/threads?in=inbox&view=count
{
"count": 386
}
Expands threads responses to contain message/draft sub-objects. Adding view=expanded will remove message_ids and draft_ids, and include messages and drafts. Note the message and draft sub-objects do not include a body parameter.
Message objects are expanded to include several additional RFC2822 headers. For more details see the Expanded Message View.
Rate limiting
Rate limit is per-account!
We rate-limit API access on a per email account basis. Rate limits typically expire within 10-25 seconds depending on which endpoint you hit.
| Scope | Rate-limit | Expiration |
|---|---|---|
| General | 200 requests per endpoint over 10s | 10s |
| Concurrent Streaming | 10 concurrent requests per streaming endpoint | 25s |
| Concurrent Queries | 5 concurrent connections open to /messages or /threads |
25s |
If you need to request the messages or threads endpoint beyond what our rate limits allow, please contact support@nylas.com and we can chat about your particular use case.
Errors
Nylas uses conventional HTTP response codes to indicate the success or failure of an API request.
| Status Code | Description |
|---|---|
200 OK |
Everything worked as expected. |
400 Bad Request |
Malformed or missing a required parameter. |
401 Unauthorized |
No valid API key provided. |
402 Request Failed |
Parameters were valid but the request failed. |
404 Not Found |
The requested item doesn't exist. |
405 Method Not Allowed |
You tried to access a resource with an invalid method. |
410 Gone |
The requested resource has been removed from our servers. |
418 I'm a teapot |
💁 |
429 Too Many Requests |
Slow down! (If you legitimately require this many requests, please contact support.) |
500, 502, 503, 504 Server errors |
An error occurred in the Nylas server. If this persists, please see our status page or contact support. |
For a full list of possible codes, we recommend the Wikipedia article or this condensed list.
Error bodies includes a JSON object with a standard set of attributes, including an error_type and a human-readable message string. These are designed to make debugging easier and allow for different handling of scenarios that produce the same HTTP status code.
| Error Type | Details |
|---|---|
api_error |
General API error |
invalid_request_error |
The request provided has an invalid format |
Supported Providers
Don't see your provider here?
The Nylas sync engine supports any IMAP mail server. Just use the "custom" provider.
| Key | Provider |
|---|---|
gmail |
Gmail and Google Apps |
eas |
Microsoft Exchange (ActiveSync) and Microsoft Office365 |
outlook |
Outlook.com (aka Hotmail) |
yahoo |
Yahoo! Mail |
icloud |
iCloud (aka MobileMe or DotMac) |
custom |
A custom account syncing via generic IMAP |
Other known IMAP providers:
| Key | Provider |
|---|---|
aol |
AOL Mail |
fastmail |
FastMail |
gandi |
GandiMail |
gmx |
GMX |
mail.ru |
Mail.ru |
yandex |
Yandex.Mail |
godaddy |
GoDaddy Mail |
hover |
Hover.com |
namecheap |
Namecheap |
bluehost |
Bluehost |
soverin |
Soverin |
zimbra |
Zimbra |
123_reg |
123-reg |
126 |
126 |
qq, foxmail, qq_enterprise |
QQ Mail |
aliyun |
Aliyun (Alibaba Group) |
163, 163_ym, 163_qiye |
NetEase 163 (China) |
yeah.net |
Yeah.net |
139 |
139.com (China) |
Deprecated providers:
| Key | Provider |
|---|---|
_outlook |
IMAP-based Outlook.com |
API Changelog
5/11/2017
- Added endpoints for checking on the status of webhooks. See the Webhook Object.
3/6/2017
aolis now a known provider for native authentication so you don't have to provide custom imap server information when authorizing aol accounts.
1/10/2017
- Added message tracking feature and corresponding webhook triggers,
message.opened,message.link_clicked, andthread.replied /sendnow accepts an optionaltrackingattribute to support message tracking
10/13/2016
- Added
attributessubobject toobject_dataformessage.createdwebhooks. It includes thereceived_dateof the message, as well as the messages associatedthread_id
10/4/2016
/eventsendpoint no longer returns events with a non-nulldeleted_atproperty- Ability to send inline images

