# Nylas Developer Documentation (Full)
> This file contains the complete text of all Nylas developer documentation pages.
> It is generated automatically and intended for use by LLM agents.
> For a curated index, see https://developer.nylas.com/llms.txt
> For individual pages as markdown, request any page with the `Accept: text/markdown` header.
>
> Generated: 2026-04-17T19:39:39.844Z
> Pages: 509
────────────────────────────────────────────────────────────────────────────────
title: "Nylas error responses: 200-299"
description: "Nylas `200` error response codes."
source: "https://developer.nylas.com/docs/api/errors/200-response/"
────────────────────────────────────────────────────────────────────────────────
200 responses return when the request is [successful](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#successful_responses).
## Response 200 - OK
Your message was submitted successfully for sending.
────────────────────────────────────────────────────────────────────────────────
title: "Client error responses: 400–499"
description: "Nylas `400` (client error) response codes."
source: "https://developer.nylas.com/docs/api/errors/400-response/"
────────────────────────────────────────────────────────────────────────────────
Nylas returns `400` responses for [client-side errors](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses)
## Error 400 - Authentication failed
Gmail
> Invalid or revoked refresh token.
**Cause**: The Google refresh token provided is missing one or more of the following required scopes:
- `userinfo.email`
- `userinfo.profile`
- `openid`
**Solution**: Generate a new Google refresh token that includes all of the required scopes.
## Error 400 - Bad request
> The browser (or proxy) sent a request that this server could not understand.
**Cause**: The request was malformed, or it contained an invalid parameter. The most common issue is invalid JSON.
**Solution**: Ensure your API payload is in a valid JSON format. Make sure all quotes are properly escaped in the code.
## Error 400 - Redirect URI is not HTTPS or localhost
**Cause**: Your project's redirect URI doesn't use the HTTPS protocol, or — if the URI directs to a localhost server — you didn't include `http://`.
**Solution**:
- For a public URI, add `https://`.
- For a localhost URI, add `http://`.
## Error 402 - Sending to at least one recipient failed
**Cause**: If a recipient's email address contains non-ASCII characters (such as characters with accents or other diacritics), delivery fails to that email address.
:::warn
**Nylas is currently unable to send messages to email addresses that contain non-ASCII characters**.
:::
## Error 403 - Unauthorized
**Cause**: The server wasn't able to authenticate with the user's email provider.
**Solution**: [Re-authenticate the user's account](/docs/dev-guide/best-practices/manage-grants/#re-authenticate-a-grant) and try again.
checkout
## Error 403 - Gmail API has not been used in project
Gmail
**Cause**: The Gmail API is disabled.
**Solution**: Make sure the Gmail API is enabled in your GCP project.
## Error 403 - Different email address returned
Microsoft
**Cause**: Microsoft 365 returned a different email address from the one that started the authentication process.
**Solution**: When [authenticating with OAuth](/docs/v3/auth/hosted-oauth-apikey/), the email address used to authenticate must remain the same throughout the process. To troubleshoot, check the following things:
- Ensure that the user isn't entering or selecting a different email address on Microsoft 365 than the one they entered in Nylas.
- Make sure the user isn't trying to log into an alias. They must authenticate with the main account.
If the issue persists, ask the user to log out of all their Microsoft 365 accounts and try again. You can also ask them to try authenticating from an incognito or private browser session.
## Error 422 - Mail provider error
**Cause**: An error occurred while the email provider was sending a message.
**Solution**: See the `server_error` value in Nylas' JSON response for more information.
## Error 422 - Sending Error
> Message delivery submission failed.
**Cause**: The user tried to send a message using a different email address than the one synced with Nylas (for example, they synced using `nylas@example.com`, but tried to send the message from `swag@example.com`). See [Microsoft sending errors](/docs/v3/email/sending-errors/#microsoft-sending-errors) for more information.
**Solution**:
1. Check the sending name to ensure that the email address used to send the message is the same as the synced account.
2. Try sending the message again with exponential backoff.
3. Confirm that the Exchange server hasn't quarantined the [syncing devices](/docs/v3/email/sending-errors/).
## Error 429 - Account throttled
**Cause**: The user's account has been throttled, and the provider email server has asked Nylas to temporarily stop making requests.
**Solution**: Wait and try again later. For more information, see [Avoiding rate limits in Nylas](/docs/dev-guide/best-practices/rate-limits/).
## Error 429 - Quota exceeded
**Cause**: The user exceeded their provider's sending quota.
**Solution**: Wait and try again later. See [Provider rate limits](/docs/dev-guide/platform/rate-limits/#provider-rate-limits) for more information.
## Error 429 - Nylas API rate limit
**Cause**: You made too many requests to the Nylas APIs too quickly. For more information, see [Avoiding rate limits in Nylas](/docs/dev-guide/best-practices/rate-limits/).
**Solution**: Wait and try again later.
## Error 429 - Too many requests
Gmail
> The Gmail account has exceeded the usage limit.
**Cause**: You might encounter this error for one of the following reasons:
- You exceeded the daily request limit for your GCP project.
- You exceeded the user rate limit for your GCP project.
See Nylas' [Google rate limits documentation](/docs/dev-guide/platform/rate-limits/#google-rate-limits) for more information.
**Solution**: Check your quotas in your GCP project, and request extra daily use allowances.
1. In the Google API Console, navigate to the [Enabled APIs page](https://console.cloud.google.com/apis/enabled) and select an API from the list.
2. Review your project's usage, then click **Quotas** to view and update quota-related settings.
If you need to reduce your usage volume, use an exponential backoff when you retry failed requests. You should randomize the backoff schedule to avoid a [thundering herd effect](https://en.wikipedia.org/wiki/Thundering_herd_problem).
## Error 429 - Resource exhausted
Gmail
> Resource has been exhausted (e.g. check quota).
**Cause**: You're trying to fetch or modify too much data per second. This error often occurs when you're trying to list all instances of an object on an account that has many (for example, when making an unlimited [Get all Messages request](/docs/reference/api/messages/get-messages/)).
Google has a quota limit of **250 per second** for each Gmail account. Each type of API request uses different amounts of your quota (for example, retrieving one Gmail message costs 5 points, while sending an email costs 100). See Google's official [Usage limits documentation](https://developers.google.com/gmail/api/reference/quota) for more information on how Google calculates your API quota.
**Solution**:
- If you hit this limit **when fetching objects**, reduce your `limit` to _20 or lower_ and [add query parameters to your request](/docs/dev-guide/best-practices/rate-limits/#filter-results-using-query-parameters) to limit the number of results Nylas returns. For example, you could add `?limit=20&starred=true` to a [Get all Messages request](/docs/reference/api/messages/get-messages/) to retrieve only the 20 most recent starred messages.
- If you hit this limit **when modifying multiple objects** (for example, changing several messages from unread to read), add at least a one second delay between each request.
- If you hit this limit **when retrying failed requests**, use an exponential backoff schedule to reduce request volume. You should randomize the backoff schedule to avoid a [thundering herd effect](https://en.wikipedia.org/wiki/Thundering_herd_problem).
## Error 429 - Application is over its MailboxConcurrency limit
Microsoft
**Cause**: The Microsoft Graph APIs allow **up to four concurrent requests**. That means you can't process more than four Nylas requests at the same time, and Microsoft returns an error if you try. For more information, see Microsoft's official [throttling limits documentation](https://learn.microsoft.com/en-us/graph/throttling-limits#limits-per-mailbox).
**Solution**: To work around this limit, try to spread out your requests, and use an exponential backoff schedule to reduce request volume. You should randomize the backoff schedule to avoid a [thundering herd effect](https://en.wikipedia.org/wiki/Thundering_herd_problem).
## Error 429 - Exchange account throttled
Microsoft
> The Exchange account has been throttled or sync has been temporarily paused.
**Cause**: You might encounter this error for one of the following reasons:
- You reached the Nylas API limits.
- A user reached their email provider's sending limit.
- The user _hasn't_ reached the Nylas API limits, but the Exchange server throttled their account to decrease load on the server. Exchange severs do this independent of the sending process.
- Nylas receives a `503` error with the following message: `The server encountered an unknown error, the device SHOULD retry later.<85>.`
- The Exchange server sends Nylas a header indicating how long to wait before syncing again.
- While Nylas is waiting to send, you will receive `429` errors for any messages you try to send. Typically, this lasts for 20 minutes.
For more information, see the following documentation:
- [Throttling for non-Microsoft accounts](/docs/api/errors/400-response/#429-account-throttled)
**Solution**:
- Try sending the message again with exponential backoff. You should randomize the backoff schedule to avoid a [thundering herd effect](https://en.wikipedia.org/wiki/Thundering_herd_problem).
- Check your Exchange server settings. If necessary, talk to the server administrator about raising the server's throttling limits.
────────────────────────────────────────────────────────────────────────────────
title: "Nylas error responses: 500-599"
description: "Nylas `500` error response codes."
source: "https://developer.nylas.com/docs/api/errors/500-response/"
────────────────────────────────────────────────────────────────────────────────
Nylas returns `500` responses when it encounters a [server-side error](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#server_error_responses).
## Error `500` - Server Error
**Cause**: An error occurred on the Nylas server.
**Solution**: If the error persists, check the [Nylas status page](https://status.nylas.com/?utm_source=docs&utm_campaign=500-errors&utm_content=error-codes) for ongoing outages.
## Error `502` - Bad Gateway
> The upstream server is unavailable, please try again...
**Cause**: An error occurred on the Nylas server.
**Solution**: If the error persists, check the [Nylas status page](https://status.nylas.com/?utm_source=docs&utm_campaign=500-errors&utm_content=error-codes) for ongoing outages.
## Error `502` - Server Error
**Cause**: An error occurred on the Nylas server.
**Solution**: If the error persists, check the [Nylas status page](https://status.nylas.com/?utm_source=docs&utm_campaign=500-errors&utm_content=error-codes) for ongoing outages.
## Error `503` - Service Unavailable
**Cause**: The [Nylas Folders API](/docs/reference/api/folders/) received too many requests.
**Solution**: Implement an exponential back-off retry strategy.
## Error `503` - Server Unavailable
> Error 503' Throttle Header, 'X-MS-ASThrottle: CommandFrequency
**Cause**: The server received too many commands.
**Solution**: If you're using a managed Microsoft Exchange account, contact your email administrator to increase the `CommandFrequency` threshold. By default, Exchange servers block requests after receiving 400 commands within 10 minutes.
## Error `503` - Server Error
**Cause**: An error occurred on the Nylas server.
**Solution**: If the error persists, check the [Nylas status page](https://status.nylas.com/?utm_source=docs&utm_campaign=500-errors&utm_content=error-codes) for ongoing outages.
## Error `504` - Provider Error
**Cause**: Nylas is having trouble connecting to the provider. The error message gives more information about the details of the failure.
In most cases, if your project implements an exponential back-off retry strategy, the request eventually succeeds. Some common reasons a request could fail with a `504` error are listed below.
### Request timed out
This error happens when a request takes too long to process. Nylas has a request SLA of 90 seconds, after which it terminates the request and sends a timeout error. You might run into timeout errors in the following scenarios:
- **Request fanout**: For Microsoft grants, a single request to the [Nylas Threads API](/docs/reference/api/threads/) can cause Nylas to make multiple Microsoft Graph API requests. Nylas has to make at least one Microsoft Graph API request per message in the thread you're working with. Because of this, the total time for all the requests can easily exceed 90 seconds. To avoid this, try to retrieve, update, and delete individual messages from a thread instead of working with the thread itself. If you're experiencing timeout errors when making a [Get all Threads request](/docs/reference/api/threads/get-threads/), try again with a smaller `limit`.
- **Server busy**: For on-prem Exchange grants, a request might time out when your Exchange server has too many requests to process. When this happens, you might also see [`429` errors](/docs/api/errors/400-response/#error-429---nylas-api-rate-limit). When an Exchange server is overloaded, it can tell new requests to wait and try again later. The wait time could be 90 seconds or longer, which means that the request might exceed Nylas' SLA. To avoid this, try making fewer concurrent requests, and implement an exponential backoff strategy.
- **Slow IMAP server**: For IMAP, a request can timeout when the email server responds slowly to large requests (for example, when you update or delete a thread). If this happens often, we recommend contacting your IMAP administrator and asking them to scale up their servers.
- **Post filtering**: Nylas supports many [request filters](/docs/dev-guide/best-practices/rate-limits/#filter-results-using-query-parameters) that provider APIs might not use, or that might be case-sensitive on the provider. In these cases, Nylas makes a request to the provider APIs without the filter, receives the response, and searches for results that match the filter in your request. This might result in a request timeout, especially if the provider returns a long list of results or there are no results that match your filter. To avoid timeouts, try searching for objects in a smaller window of time, or use a larger `limit` so Nylas can paginate through the results more quickly.
### IMAP server errors
This error happens when an IMAP server doesn't support certain operations, like renaming or removing a system folder. It can also happen if the IMAP server is unstable.
There's nothing Nylas can do in these cases, because this is an issue with the IMAP provider's server. Your best course of action is to contact your IMAP administrator and ask them to support specific IMAP commands, or find what's making the server unstable (and fix it).
### Internal errors
Sometimes, the Google or Microsoft Graph APIs return internal errors. This is usually caused by bugs on the provider. [Learn how to get support](/docs/support/) if you encounter this often.
### Spam errors
If you get an error caused by spam (for example, `554 5.7.1 nyla@example.com is sending SPAM`) don't try again. Check with your service provider instead.
## Error `550` - Service Unavailable
> The message was classified as spam and may not be delivered.
**Cause**: Some providers review all outbound messages through their spam filter before sending to preserve their email-sending reputation. Spam filters work by comparing messages to an extensive list of matching behaviors and giving each a score. If a message is blocked by a provider's spam filter, Nylas returns that in its `550` response. However, Nylas doesn't have any visibility into what exactly caused the block.
**Solution**: Take a look at our [Dealing with spam](/docs/dev-guide/best-practices/dealing-with-spam/) guide.
────────────────────────────────────────────────────────────────────────────────
title: "Nylas error responses: 700-799"
description: "Nylas `700` error response codes."
source: "https://developer.nylas.com/docs/api/errors/700-response/"
────────────────────────────────────────────────────────────────────────────────
## Error 701
**Cause**: You included a redirect URI in your code that hasn't been registered in the Nylas Dashboard.
**Solution**: Register your application's callback URI in the Hosted Auth section of the Nylas Dashboard
────────────────────────────────────────────────────────────────────────────────
title: "Error types in Nylas"
description: "Troubleshoot the types of errors that you might encounter while using Nylas."
source: "https://developer.nylas.com/docs/api/errors/event-codes/"
────────────────────────────────────────────────────────────────────────────────
This page is a reference list for error types that you might encounter when working with Nylas. For more information, see [Nylas API responses, errors, and HTTP status codes](/docs/api/errors/).
## Error types
Error messages include a JSON object that contains a standard set of attributes, including the error's `type` and a human-readable `message` string. These are designed to make debugging easier and allow for you to handle different scenarios that produce the same HTTP error code.
The table below shows the error types you might encounter while working with Nylas.
| Error Type | HTTP Code | Default Message |
| ------------------------------------------------ | --------- | --------------------------------------------------------------------------------------------------------- |
| `api.authentication_error` | `401` | Unauthorized |
| `api.internal_error` | `500` | Internal error, contact administrator. |
| `api.invalid_request_error` | `400` | Bad request |
| `api.invalid_request_payload` | `400` | Invalid JSON payload format. |
| `api.provider_error` | `504` | Provider error message. (Specific Provider HTTP code response possible.) |
| `api.not_found_error` | `404` | Resource not found. |
| `api.resource_blocked` | `423` | Resource blocked, contact administrator. |
| `api.partial_not_found_error` | `404` | Partially missing data from requested resource(s). |
| `api.partial_success_error` | `504` | One or more objects could not be handled. (Specific Provider HTTP code response possible.) |
| `api.rate_limit_error` | `429` | Rate limit error. |
| `token.unauthorized_access` | `400` | Invalid API key. |
| `token.exchange_failed` | `400` | OAuth 2.0 token exchange failed. |
| `grant.callback_uri_not_allowed` | `400` | `callback_uri` is not allowed for this connector. |
| `grant.login_id_invalid` | `400` | Login ID or request is invalid or has expired. |
| `grant.not_found` | `404` | Grant not found. |
| `grant.refresh_token_invalid` | `401` | Invalid `refresh_token` supplied to Grant. |
| `grant.provider_required` | `400` | Provider field is required. |
| `grant.reauth_email_invalid` | `400` | Email addresses did not match during re-authentication. |
| `grant.scopes_conflict` | `400` | Some requested scopes were not included in the completed hosted auth, resulting in denied authentication. |
| `grant.gmail_domain_invalid` | `400` | Gmail domain is not allowed, resulting in denied authentication. |
| `grant.access_denied` | `403` | Access to Grant denied. |
| `grant.invalid_authentication` | `400` | Authentication failed due to wrong input or credentials. |
| `grant.provider_not_responding` | `400` | Provider not responding. |
| `grant.auth_limit_reached` | `400` | Maximum number of retries reached for hosted auth. |
| `grant.imap_type_mismatch` | `400` | IMAP provider mismatch. |
| `grant.provider_mismatch` | `400` | Grant provider mismatch. |
| `grant.imap_autodetect_fail` | `400` | IMAP auto-detection failed. Please provide additional IMAP configuration (host, port). |
| `grant.hosted_login_expired` | `400` | Hosted login expired. |
| `grant.session_revoke_failed` | `400` | Session revoke failed. |
| `grant.provider_id_token_missing` | `400` | Provider did not return ID token for authorized account. |
| `connector.not_found` | `404` | Connector not found. |
| `connector.provider_not_supported` | `400` | Provider invalid or not supported. |
| `connector.provider_settings_invalid` | `400` | Provider settings not supported. |
| `connector.provider_settings_secret_required` | `400` | Provider settings and Secret both are required if one needs to change. |
| `connector.already_exists` | `400` | Connector already exists. |
| `connector.problem` | `400` | Issues found with connector's settings or configuration. |
| `credential.not_found` | `404` | Credential not found. |
| `credential.already_exists` | `400` | Credential with this name for given connector already exists. |
| `credential.missing_param` | `400` | Credential is missing some essential values in its settings. |
| `connector.no_longer_exists` | `400` | Connector no longer exists. |
| `oauth2.provider_code_request_failed` | `400` | Provider refused to return `refresh_token` using code. |
| `oauth2.oauth_failed` | `400` | Hosted OAuth failed due to rejection by provider or user refusing consent. |
| `oauth2.invalid_client` | `400` | OAuth client not found. |
| `oauth2.invalid_grant` | `400` | Error creating grant with provided OAuth parameters. |
| `oauth2.redirect_uri_mismatch` | `400` | Redirect URI not allowed. |
| `oauth2.unsupported_grant_type` | `400` | Invalid `grant_type`. |
| `oauth2.invalid_token` | `401` | Token expired or revoked. |
| `oauth2.oauth_provider_error` | `400` | Error from OAuth 2.0 provider. |
| `oauth2.origin_not_allowed` | `400` | Error origin not allowed for `callback_uri` for `platform:js`. |
| `oauth2.provider_code_exchange_failed` | `403` | Code exchange to get access/refresh token failed on provider's side. |
| `application.missing_required_parameter` | `400` | One of the platform's required parameters is missing. |
| `application.not_found` | `404` | Application not found. |
| `application.callback_uris_not_found` | `404` | Application's redirect URIs not found. |
| `application.callback_uri_is_not_valid` | `400` | Application's redirect URI is not valid. |
| `application.id_not_allowed` | `403` | Application ID not allowed. |
| `common.scope_not_allowed` | `400` | One or more provided scopes is not allowed. |
| `common.secret_not_found` | `404` | Searched Secret record not found. |
| `v3_migration.account_to_grant_migration_failed` | `400` | Account migration to a v3 grant failed. |
| `v3_migration.translate_resource_failed` | `400` | Failed to translate Nylas resource ID to Provider resource ID. |
| `v3_migration.link_apps_failed` | `400` | Failed to link v2 & v3 applications. |
| `v3_migration.app_import_failed` | `400` | Failed to import v2 application's settings to v3 application. |
| `v3_migration.job_start_failed` | `400` | Failed start migration jobs. |
| `v3_migration.get_jobs_failed` | `404` | Failed to get info of migration jobs. |
### Sample HTTP error response
The following JSON snippet is an example of an HTTP error response that you might receive from Nylas.
```json
{
"request_id": "1f58962d-9967-42de-9dd3-3f55aa1a216a",
"error": {
"type": "invalid_request_error",
"message": "The message_id parameter is required."
}
}
```
### Sample HTTP provider error response
HTTP errors include the `provider_error` parameter only when they're generated by the provider or connector, as in the following example.
```json
{
"request_id": "1f58962d-9967-42de-9dd3-3f55aa1a216a",
"error": {
"type": "invalid_request_error",
"message": "The message_id parameter is required.",
"provider_error": {
// Provider error response
}
}
}
```
────────────────────────────────────────────────────────────────────────────────
title: "Nylas errors and HTTP status codes"
description: "Nylas errors and HTTP status codes you might encounter."
source: "https://developer.nylas.com/docs/api/errors/"
────────────────────────────────────────────────────────────────────────────────
This page is a reference list of API responses, error types, and HTTP status codes that you might encounter when working with Nylas.
You can also skip to the pages for more specific pages for error codes:
- [200-299 responses](/docs/api/errors/200-response)
- [400-499 responses](/docs/api/errors/400-response)
- [500-599 responses](/docs/api/errors/500-response)
- [700-799 responses](/docs/api/errors/700-response)
## Error types
Error messages include a JSON object that contains a standard set of attributes, including the error's `type` and a human-readable `message` string. These are designed to make debugging easier and allow for you to handle different scenarios that produce the same HTTP error code.
| Error Type | HTTP Code | Default Message |
| ------------------------------------------------ | --------- | --------------------------------------------------------------------------------------------------------- |
| `api.authentication_error` | `401` | Unauthorized |
| `api.internal_error` | `500` | Internal error, contact administrator. |
| `api.invalid_request_error` | `400` | Bad request |
| `api.invalid_request_payload` | `400` | Invalid JSON payload format. |
| `api.provider_error` | `504` | Provider error message. (Specific Provider HTTP code response possible.) |
| `api.not_found_error` | `404` | Resource not found. |
| `api.resource_blocked` | `423` | Resource blocked, contact administrator. |
| `api.partial_not_found_error` | `404` | Partially missing data from requested resource(s). |
| `api.partial_success_error` | `504` | One or more objects could not be handled. (Specific Provider HTTP code response possible.) |
| `api.rate_limit_error` | `429` | Rate limit error. |
| `token.unauthorized_access` | `400` | Invalid API key. |
| `token.exchange_failed` | `400` | OAuth 2.0 token exchange failed. |
| `grant.callback_uri_not_allowed` | `400` | `callback_uri` is not allowed for this connector. |
| `grant.login_id_invalid` | `400` | Login ID or request is invalid or has expired. |
| `grant.not_found` | `404` | Grant not found. |
| `grant.refresh_token_invalid` | `401` | Invalid `refresh_token` supplied to Grant. |
| `grant.provider_required` | `400` | Provider field is required. |
| `grant.reauth_email_invalid` | `400` | Email addresses did not match during re-authentication. |
| `grant.scopes_conflict` | `400` | Some requested scopes were not included in the completed hosted auth, resulting in denied authentication. |
| `grant.gmail_domain_invalid` | `400` | Gmail domain is not allowed, resulting in denied authentication. |
| `grant.access_denied` | `403` | Access to Grant denied. |
| `grant.invalid_authentication` | `400` | Authentication failed due to wrong input or credentials. |
| `grant.provider_not_responding` | `400` | Provider not responding. |
| `grant.auth_limit_reached` | `400` | Maximum number of retries reached for hosted auth. |
| `grant.imap_type_mismatch` | `400` | IMAP provider mismatch. |
| `grant.provider_mismatch` | `400` | Grant provider mismatch. |
| `grant.imap_autodetect_fail` | `400` | IMAP auto-detection failed. Please provide additional IMAP configuration (host, port). |
| `grant.hosted_login_expired` | `400` | Hosted login expired. |
| `grant.session_revoke_failed` | `400` | Session revoke failed. |
| `grant.provider_id_token_missing` | `400` | Provider did not return ID token for authorized account. |
| `connector.not_found` | `404` | Connector not found. |
| `connector.provider_not_supported` | `400` | Provider invalid or not supported. |
| `connector.provider_settings_invalid` | `400` | Provider settings not supported. |
| `connector.provider_settings_secret_required` | `400` | Provider settings and Secret both are required if one needs to change. |
| `connector.already_exists` | `400` | Connector already exists. |
| `connector.problem` | `400` | Issues found with connector's settings or configuration. |
| `credential.not_found` | `404` | Credential not found. |
| `credential.already_exists` | `400` | Credential with this name for given connector already exists. |
| `credential.missing_param` | `400` | Credential is missing some essential values in its settings. |
| `connector.no_longer_exists` | `400` | Connector no longer exists. |
| `oauth2.provider_code_request_failed` | `400` | Provider refused to return `refresh_token` using code. |
| `oauth2.oauth_failed` | `400` | Hosted OAuth failed due to rejection by provider or user refusing consent. |
| `oauth2.invalid_client` | `400` | OAuth client not found. |
| `oauth2.invalid_grant` | `400` | Error creating grant with provided OAuth parameters. |
| `oauth2.redirect_uri_mismatch` | `400` | Redirect URI not allowed. |
| `oauth2.unsupported_grant_type` | `400` | Invalid `grant_type`. |
| `oauth2.invalid_token` | `401` | Token expired or revoked. |
| `oauth2.oauth_provider_error` | `400` | Error from OAuth 2.0 provider. |
| `oauth2.origin_not_allowed` | `400` | Error origin not allowed for `callback_uri` for `platform:js`. |
| `oauth2.provider_code_exchange_failed` | `403` | Code exchange to get access/refresh token failed on provider's side. |
| `application.missing_required_parameter` | `400` | One of the platform's required parameters is missing. |
| `application.not_found` | `404` | Application not found. |
| `application.callback_uris_not_found` | `404` | Application's redirect URIs not found. |
| `application.callback_uri_is_not_valid` | `400` | Application's redirect URI is not valid. |
| `application.id_not_allowed` | `403` | Application ID not allowed. |
| `common.scope_not_allowed` | `400` | One or more provided scopes is not allowed. |
| `common.secret_not_found` | `404` | Searched Secret record not found. |
| `v3_migration.account_to_grant_migration_failed` | `400` | Account migration to a v3 grant failed. |
| `v3_migration.translate_resource_failed` | `400` | Failed to translate Nylas resource ID to Provider resource ID. |
| `v3_migration.link_apps_failed` | `400` | Failed to link v2 & v3 applications. |
| `v3_migration.app_import_failed` | `400` | Failed to import v2 application's settings to v3 application. |
| `v3_migration.job_start_failed` | `400` | Failed start migration jobs. |
| `v3_migration.get_jobs_failed` | `404` | Failed to get info of migration jobs. |
For more information about specific error codes, see the following documentation:
- [200-299 responses](/docs/api/errors/200-response)
- [400-499 responses](/docs/api/errors/400-response)
- [500-599 responses](/docs/api/errors/500-response)
- [700-799 responses](/docs/api/errors/700-response)
### Sample HTTP error response
The following JSON snippet is an example of an HTTP error response that you might receive from Nylas.
```json
{
"request_id": "1f58962d-9967-42de-9dd3-3f55aa1a216a",
"error": {
"type": "invalid_request_error",
"message": "The message_id parameter is required."
}
}
```
### Sample HTTP provider error response
HTTP errors include the `provider_error` parameter only when they're generated by the provider or connector, as in the following example.
```json
{
"request_id": "1f58962d-9967-42de-9dd3-3f55aa1a216a",
"error": {
"type": "invalid_request_error",
"message": "The message_id parameter is required.",
"provider_error": {
// Provider error response
}
}
}
```
## HTTP status codes
Nylas uses a set of conventional HTTP response codes to indicate the success or failure of API requests.
| HTTP status code | Description |
| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200` OK | Everything worked as expected. |
| `202` Not Ready | The request was valid, but the resource wasn't ready. Retry the request with exponential backoff. |
| `400` Bad Request | The request was malformed or missing a required parameter. |
| `401` Unauthorized | Could not verify access credentials. No valid API key or `access_token` was provided. |
| `402` Request Failed or Payment Required | The request parameters were valid, but the request failed or you must add a credit card to your organization. |
| `403` Forbidden | The request includes authentication errors, blocked developer applications, or cancelled accounts. |
| `404` Not Found | The requested item doesn't exist. |
| `405` Method Not Allowed | You tried to access a resource using an invalid method. |
| `410` Gone | The requested resource has been removed from the Nylas servers. |
| `413` Request Entity too Large | The transmitted data value exceeds the capacity limit for Send or Attachments requests. |
| `418` I'm a Teapot | [🫖](https://en.wikipedia.org/wiki/Hyper_Text_Coffee_Pot_Control_Protocol) |
| `422` Sending Error | This response was returned during the sending process. |
| `429` Too Many Requests | Slow down! If you legitimately require this many requests and you have a contract with us, [contact Nylas Support](/docs/support/#contact-nylas-support). |
| `500`, `502`, and `503` Server Errors | An error occurred in the Nylas server. If this persists, see the [Nylas platform status page](https://status.nylas.com) or [learn how to get support](/docs/support/). |
| `504` Provider Error | Wait and try again later. If the problem persists, check with your service provider. If you get an error caused by spam (for example, `554 5.7.1 nyla@example.com is sending SPAM`) don't try again. Check with your service provider instead. |
:::warn
**If you make a `PUT` request that contains no body content**, Nylas returns a `400` Empty Request Body error.
:::
For more information, see Wikipedia's [list of HTTP status codes](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) or the WebFX [HTTP status codes database](https://www.webfx.com/web-development/glossary/http-status-codes/).
────────────────────────────────────────────────────────────────────────────────
title: "Nylas Python SDK v6.14.2"
description: ""
source: "https://developer.nylas.com/docs/changelogs/2026-01-16-nylas-python-v6-14-2/"
────────────────────────────────────────────────────────────────────────────────
## Fixed
- **UTF-8 encoding** — Fixed encoding for special characters (emoji, accented letters, etc.) by correctly encoding JSON request bodies as UTF-8 bytes.
────────────────────────────────────────────────────────────────────────────────
title: "Nylas Ruby SDK v6.7.1"
description: ""
source: "https://developer.nylas.com/docs/changelogs/2026-02-23-nylas-ruby-v6-7-1/"
────────────────────────────────────────────────────────────────────────────────
## Fixed
- **Large attachment handling** — Fixed an issue where large inline attachments with string keys and custom `content_id` values were not processed correctly.
────────────────────────────────────────────────────────────────────────────────
title: "Nylas Auth Service"
description: ""
source: "https://developer.nylas.com/docs/changelogs/2026-02-27-auth/"
────────────────────────────────────────────────────────────────────────────────
## Added
- **Customer-facing IMAP/SMTP validation logs** — Authentication validation failures for IMAP and SMTP connections now produce customer-visible logs, making it easier to diagnose grant creation issues.
- **Request ID forwarding** — Auth service logs now include `request_id` for improved traceability when debugging authentication flows.
## Fixed
- **Plus sign in hosted auth** — The hosted authentication UI now correctly accepts email addresses containing a `+` symbol (e.g., `user+tag@example.com`).
- **Grant re-authentication** — Fixed an issue where re-authenticating an existing grant could fail instead of updating the existing credentials.
- **Hosted auth redirect encoding** — Fixed login hint redirect encoding in the hosted authentication flow.
## Updated
- Improved authentication service performance with optimized read operations.
────────────────────────────────────────────────────────────────────────────────
title: "Nylas React SDK v3.2.0"
description: ""
source: "https://developer.nylas.com/docs/changelogs/2026-03-10-javascript-nylas-react-v3-2-0/"
────────────────────────────────────────────────────────────────────────────────
## Added
- **Scheduler editor error event** — New `nylasSchedulerEditorError` event on `` captures and re-emits errors from child components. In React, use the `onNylasSchedulerEditorError` prop to handle all editor errors in a single place.
## Updated
- Upgraded `@nylas/web-elements` to v2.5.0.
## Fixed
- Fixed scheduler editor showing the configuration list in composable mode instead of rendering slotted content.
- Fixed cancel and reschedule flows breaking when a booking reference was provided without a session ID.
- Fixed cancel-after-reschedule failing because stale booking IDs were retained — the scheduler now correctly updates to the new IDs.
- Fixed participant availability and booking calendars not populating when editing an existing configuration. Also fixed round-robin participants incorrectly showing the organizer's calendars.
- Fixed participant search: results are now properly added to the options store, the dropdown no longer disappears prematurely, and the edited participant row is excluded from duplicate filtering.
- Fixed organizer participant's `grant_id` being dropped when saving a configuration — now preserved for both organizer and non-organizer participants.
- Fixed round-robin configurations not correctly identifying the organizer, which could cause calendar selection and booking calendar assignment to fail.
────────────────────────────────────────────────────────────────────────────────
title: "Nylas Node.js SDK v8.0.5"
description: ""
source: "https://developer.nylas.com/docs/changelogs/2026-03-23-nylas-nodejs-v8-0-5/"
────────────────────────────────────────────────────────────────────────────────
## Added
- **Scheduling availability API** — New `scheduler.availability.get()` method for retrieving scheduling availability via the `/v3/scheduling/availability` endpoint.
────────────────────────────────────────────────────────────────────────────────
title: "Nylas Dashboard"
description: ""
source: "https://developer.nylas.com/docs/changelogs/2026-03-26-dashboard/"
────────────────────────────────────────────────────────────────────────────────
## Added
- **CLI authentication** — You can now authenticate with the Nylas Dashboard directly from the command line.
- **Disposable email blocking** — Registration now rejects disposable/temporary email addresses for improved account security.
## Fixed
- Resolved several authentication token validation issues that could cause intermittent login failures in certain deployment configurations.
────────────────────────────────────────────────────────────────────────────────
title: "Nylas Java SDK v2.15.1"
description: ""
source: "https://developer.nylas.com/docs/changelogs/2026-03-30-nylas-java-v2-15-1/"
────────────────────────────────────────────────────────────────────────────────
## Added
- **"Maybe" event status** — Calendar events now support `maybe` as an RSVP status, replacing the deprecated `tentative` value. Unknown status values are handled gracefully.
- **Booking deletion with JSON body** — The `destroy` method for booking deletion now accepts a JSON request body for more flexible cancellation options.
────────────────────────────────────────────────────────────────────────────────
title: "Nylas CLI v3.1.1"
description: ""
source: "https://developer.nylas.com/docs/changelogs/2026-04-04-cli-v3-1-1/"
────────────────────────────────────────────────────────────────────────────────
## Added
- **Callback URI CRUD operations** — You can now create, read, update, and delete callback URIs directly from the CLI, alongside fixes to authentication configuration for admin functions.
## Improved
- Reduced code duplication across dashboard and email authentication/pagination commands.
- Streamlined code across CLI commands and adapters for better maintainability.
────────────────────────────────────────────────────────────────────────────────
title: "API Reference: Nullable field corrections"
description: ""
source: "https://developer.nylas.com/docs/changelogs/2026-04-09-api-nullable-fields/"
────────────────────────────────────────────────────────────────────────────────
## Fixed
Updated OpenAPI specs to correctly document fields that can return `null` from the API. Previously these were typed as plain `boolean`, `string`, `integer`, or `array`, which caused typed client generation to break when `null` values appeared.
For each nullable field, the description now explains what `null` means and what default to treat it as (for example, "treat `null` the same as `false`").
### Scheduler API (8 fields)
- `event_booking.disable_emails`, `hide_participants`, `notify_participants` — boolean or null
- `requires_session_auth` — boolean or null
- `slug` — string or null
- `appearance` — object or null
- `min_booking_notice` — integer or null
- Group configurations: same fields where applicable
### Events API (5 fields)
- `busy` — boolean or null
- `reminders.use_default` — boolean or null
- `reminders.overrides` — array or null
- `calendar_id` — string or null
- `when` — object or null
### Contacts API (6 fields)
- `emails`, `groups`, `im_addresses`, `phone_numbers`, `physical_addresses`, `web_pages` — all array or null
### Availability / Free-Busy (3 fields)
- `time_slots` (availability and free/busy responses) — array or null
- `emails` (time slot) — array or null
### Attachments API
- Restored missing `is_inline` boolean field
────────────────────────────────────────────────────────────────────────────────
title: "Email Signatures API"
description: ""
source: "https://developer.nylas.com/docs/changelogs/2026-04-09-email-signatures/"
────────────────────────────────────────────────────────────────────────────────
## Added
- **Signatures API** — New endpoints to create, list, retrieve, update, and delete HTML email signatures per grant. Each grant supports up to 10 signatures for different contexts (e.g. "Work", "Personal", "Mobile").
- `POST /v3/grants/{grant_id}/signatures` — create a signature
- `GET /v3/grants/{grant_id}/signatures` — list all signatures for a grant
- `GET /v3/grants/{grant_id}/signatures/{signature_id}` — retrieve a single signature
- `PUT /v3/grants/{grant_id}/signatures/{signature_id}` — update a signature
- `DELETE /v3/grants/{grant_id}/signatures/{signature_id}` — delete a signature
- **`signature_id` on send and draft endpoints** — Pass a `signature_id` when calling Send Message, Create Draft, or Send Draft. Nylas appends the signature HTML to the end of the email body at send time, including after quoted text in replies and forwards.
- **Cross-provider support** — Signatures are stored on Nylas, not on the email provider. A signature you create once works the same across Gmail, Microsoft 365, and all other supported providers.
- **HTML with sanitization** — Signature content is HTML with full control over formatting, links, images, and layout. Nylas sanitizes HTML on input to prevent unsafe content. Images must use external URLs (no base64 inline). Maximum size is 100 KB per signature.
For full details, see the [Email Signatures documentation](/docs/v3/email/signatures/) and the [Signatures API reference](/docs/reference/api/signatures/).
────────────────────────────────────────────────────────────────────────────────
title: "Nylas React SDK v3.2.1 and Web Elements v2.5.1"
description: ""
source: "https://developer.nylas.com/docs/changelogs/2026-04-09-javascript-nylas-react-v3-2-1/"
────────────────────────────────────────────────────────────────────────────────
## Updated
- Upgraded `@nylas/web-elements` to v2.5.1.
## Fixed
- Improved error handling for authentication failures in the scheduler editor. Auth errors now display a visible error banner on the login screen instead of failing silently. The `nylasSchedulerEditorError` event is emitted with `category: 'auth'` for programmatic error handling. Session expiry detection also catches additional error patterns.
- Fixed scheduler date handling to normalize mixed date inputs (Date objects, ISO strings, and unix timestamps), preventing incorrect fallback dates like 1970 and ensuring timezone-aware selected-day comparisons remain stable across components.
- Fixed deferred initialization for booking refs in private scheduler configurations. Booking ref props (`reschedule`, `cancel`, `organizer confirmation`) no longer prematurely trigger initialization without proper auth credentials. Organizer confirmation salt is now correctly persisted when the booking ref is set dynamically.
────────────────────────────────────────────────────────────────────────────────
title: "Nylas React SDK v3.2.3 and Web Elements v2.5.3"
description: ""
source: "https://developer.nylas.com/docs/changelogs/2026-04-13-javascript-nylas-react-v3-2-3/"
────────────────────────────────────────────────────────────────────────────────
## Added
- The scheduler now automatically detects the user's browser language and displays localized content when a supported language is available. Previously, localization required explicitly setting the `?lang=` URL parameter or `defaultLanguage` prop.
- The Page Styles section in the scheduler editor now renders translated labels by default. Labels for "Company logo URL", "Primary color", "Submit button label", and "Thank you message" are available in all supported languages (en, es, fr, de, sv, zh, ja, nl, ko). The color picker placeholder is also translated.
## Updated
- Upgraded `@nylas/web-elements` to v2.5.3.
## Fixed
- Fixed `schedulerApiUrl` not being applied before the connector's first API call when using React wrappers on a full page refresh. The connector now syncs the latest `schedulerApiUrl` prop value before every data fetch, ensuring EU and other non-US regions work correctly regardless of prop timing.
- Fixed confirmation redirect URL incorrectly appending query parameters with `?` instead of `&` when the `confirmationRedirectUrl` already contains existing query parameters. URLs with pre-existing parameters (e.g., JWT tokens) now correctly preserve all original query parameters.
- Fixed deferred initialization when `rescheduleBookingRef` or `cancelBookingRef` is set via JavaScript after mount (CDN/vanilla HTML pattern). Watch handlers now emit the `bookingRefExtracted` event, include error handling for malformed booking refs, and properly coordinate with the base provider during deferred init.
────────────────────────────────────────────────────────────────────────────────
title: "Nylas Agent Accounts (Beta)"
description: ""
source: "https://developer.nylas.com/docs/changelogs/2026-04-16-agent-accounts-beta/"
────────────────────────────────────────────────────────────────────────────────
:::info
**Replaces the Inbound beta.** Agent Accounts is the productized successor to the Inbound beta. Existing Inbound grants continue to work — start with the [Agent Accounts quickstart](/docs/v3/getting-started/agent-accounts/).
:::
## Added
- **Agent Accounts** — A new grant type for agents that need their own identity instead of access to a human's inbox. An Agent Account is a real `name@company.com` mailbox that sends and receives mail, hosts and responds to calendar events, and uses the same `grant_id` contract as any connected account — so every existing Messages, Drafts, Threads, Folders, Calendars, Events, and Webhooks endpoint works against it with no new concepts. See the [Agent Accounts overview](/docs/v3/agent-accounts/) and the [quickstart](/docs/v3/getting-started/agent-accounts/).
- **Provisioning through CLI, Dashboard, or API** — Create an Agent Account with `nylas agent create`, through the Dashboard, or by calling `POST /v3/connect/custom` with the new `Nylas (Agent Account)` variant. The variant accepts `email`, `policy_id`, and an optional `app_password` so the same mailbox can be reached from an IMAP or SMTP client as well as the API. See [Provisioning and domains](/docs/v3/agent-accounts/provisioning/).
- **Policies, Rules, and Lists** — 13 new API operations for configuring agent behavior at the mailbox level. Policies define what an agent can do, Rules apply conditional logic to inbound and outbound messages, and Lists hold the values that rules reference (allow-lists, deny-lists, VIP senders, quarantine domains). All operations live under the Administration section and are marked beta:
- **Policies** — `POST`, `GET`, `GET /{id}`, `PUT /{id}`, `DELETE /{id}` under `/v3/policies`
- **Rules** — `POST`, `GET`, `GET /{id}`, `PUT /{id}`, `DELETE /{id}` under `/v3/rules`
- **Lists** — `POST`, `GET`, `GET /{id}`, `PUT /{id}`, `DELETE /{id}` under `/v3/lists`, plus `POST`, `GET`, and `DELETE` for list items at `/v3/lists/{id}/items`
- **Rule evaluations audit trail** — `GET /v3/grants/{grant_id}/rule-evaluations` returns a time-ordered record of every rule that fired on a grant, including the matched conditions and the action taken. Use it to debug why a message was blocked, routed, or modified.
- **Mail client access (IMAP and SMTP)** — Set an `app_password` on an Agent Account to connect it from a standard mail client. The [Mail clients](/docs/v3/agent-accounts/mail-clients/) page documents host and port configuration, folder mapping, and the bidirectional-sync behavior between Nylas and the connected client.
- **Supported endpoints reference** — The [Supported endpoints](/docs/v3/agent-accounts/supported-endpoints/) page lists every API endpoint and webhook trigger that works on an Agent Account grant, plus the small set that explicitly doesn't (Scheduler, Notetaker, and a handful of provider-only features).
- **AI-agent onboarding split by identity model** — The getting-started section now distinguishes between pointing an agent at a human's inbox (Share your email / Share your calendar) and giving the agent its own identity (Give your agent its own email / Give your agent its own calendar). The CLI quickstart opens with a short *Pick an identity model* decision section so you land on the right path immediately.
- **Scheduling-agent tutorial** — A full end-to-end use-case walkthrough under [Scheduling agent with a dedicated identity](/docs/v3/use-cases/act/scheduling-agent-with-dedicated-identity/) covers webhook setup, LLM parsing of inbound requests, free/busy checks against the agent's own calendar, event creation, and RSVP tracking.
- **Recipes** — Two short how-tos under `/docs/v3/guides/agent-accounts/`: [Sign an agent up for a third-party service](/docs/v3/guides/agent-accounts/sign-up-for-a-service/) and [Extract an OTP or 2FA code from an agent's inbox](/docs/v3/guides/agent-accounts/extract-otp-code/).
:::info
**Beta.** Agent Accounts, the Policies / Rules / Lists APIs, and the `Nylas (Agent Account)` BYO Auth variant are all marked beta. Shapes and semantics may change before general availability.
:::
────────────────────────────────────────────────────────────────────────────────
title: "Webhook delivery and notification updates"
description: ""
source: "https://developer.nylas.com/docs/changelogs/2026-04-16-webhook-notifications/"
────────────────────────────────────────────────────────────────────────────────
## Added
- **Compressed webhook delivery** — Webhook destinations, Amazon SNS channels, and Google Pub/Sub channels now accept a `compressed_delivery` boolean on create and update. When set to `true`, Nylas gzip-compresses the JSON payload before sending it. Two reasons to turn it on:
- **Avoids SNS's 256 KB payload limit.** Uncompressed notifications with long message bodies or large headers can be truncated; compressed delivery keeps them under the cap.
- **Bypasses WAF rules that block HTML in request bodies.** Some firewalls reject notifications because the `body` field contains raw HTML; gzipped payloads no longer trip those rules.
Configure it on [webhook destinations](/docs/reference/api/webhook-notifications/post-webhook-destinations/), [SNS channels](/docs/v3/notifications/sns-channel/), or [Pub/Sub channels](/docs/v3/notifications/pubsub-channel/).
- **`message.created.cleaned` webhook trigger** — A new trigger for projects using [Clean Conversations](/docs/v3/email/parse-messages/). When subscribed, Nylas cleans inbound messages during sync and delivers the cleaned markdown in the webhook payload's `body` field instead of the original HTML — no extra API call required. The trigger composes with the existing suffixes, so you may receive `message.created.cleaned.transformed`, `message.created.cleaned.truncated`, or `message.created.cleaned.transformed.truncated`. Subscribe once to `message.created.cleaned` and handle the suffix variants in your webhook processor. See the [notification schema](/docs/reference/notifications/messages/message-created-cleaned/) and the [parse-messages guide](/docs/v3/email/parse-messages/) for the end-to-end flow.
## Fixed
- **IMAP sync completed notification schema** — The notification reference for IMAP sync completed previously listed the field as `integartion_id`. The actual webhook payload has always shipped `integration_id`; only the schema docs and example payload carried the typo. Both are now corrected.
────────────────────────────────────────────────────────────────────────────────
title: "All changelogs"
description: "Complete changelog history across all Nylas products and SDKs."
source: "https://developer.nylas.com/docs/changelogs/all/"
────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────
title: "Changelogs"
description: "What's new across Nylas products, SDKs, and platform."
source: "https://developer.nylas.com/docs/changelogs/"
────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────────
title: "Reducing payload size with compression"
description: "Use gzip compression and field selection to cut bandwidth, speed up responses, and avoid firewall and SNS size limits across the Nylas APIs, webhooks, and notification channels."
source: "https://developer.nylas.com/docs/dev-guide/best-practices/compression/"
────────────────────────────────────────────────────────────────────────────────
Large JSON payloads cost bandwidth, slow your application down, and, when email bodies contain HTML, sometimes get blocked by firewalls and WAFs before they reach your code. Nylas supports gzip compression on API responses, webhooks, and Pub/Sub and SNS notification channels, along with field selection to strip fields you don't need. We recommend enabling compression on every surface that supports it.
## Why compress?
- **Smaller payloads, faster transfers.** Gzip typically shrinks JSON bodies by 70 to 90%, which directly reduces bandwidth costs and time-to-first-byte for your application.
- **Fewer firewall false positives.** Some firewalls and WAFs inspect request bodies and block content that contains HTML tags. Email message notifications often include HTML in the message body, which can trigger those rules. Compressed payloads are opaque binary data and pass through without being flagged.
- **Avoid SNS truncation.** Amazon SNS has a 256 KB message size limit. Compressed delivery keeps large notifications within that limit so your project receives the full object instead of a truncated one.
:::success
**Nylas recommends enabling compression on every surface that supports it**, including API responses, webhooks, and Pub/Sub or SNS channels. The only thing you need to add is decompression logic in your handler. The bandwidth and reliability wins are substantial, especially if your application processes a lot of `message.*` notifications.
:::
## Compress API responses
The Email, Calendar, Contacts, and Scheduler APIs return gzip-compressed responses when your request includes the `Accept-Encoding: gzip` header. Most HTTP libraries negotiate this automatically and decompress the response for you.
With curl, use `--compressed` to advertise support and decompress transparently:
```bash
curl --compressed \
-H "Authorization: Bearer " \
"https://api.us.nylas.com/v3/grants//messages?limit=50"
```
If you want to see the raw compressed bytes, set the header explicitly and pipe to `gunzip`:
```bash
curl -H "Accept-Encoding: gzip" \
-H "Authorization: Bearer " \
"https://api.us.nylas.com/v3/grants//messages?limit=50" \
| gunzip
```
Nylas skips compression for very small responses (under about 200 bytes) because the overhead outweighs the savings. You'll see this on error responses and single-object endpoints, and it's expected behavior.
Compression pairs well with query parameters that shrink the payload _before_ it's compressed. Use `limit` to cap list sizes and `select` to return only the fields you need:
```bash
curl --compressed \
-H "Authorization: Bearer " \
"https://api.us.nylas.com/v3/grants//messages?select=id,subject,from,date&limit=100"
```
:::info
**Response compression applies to the Email, Calendar, Contacts, and Scheduler APIs.** Administration endpoints, including grants, connectors, credentials, API keys, and auth, currently return uncompressed responses regardless of the `Accept-Encoding` header.
:::
## Compress webhook notifications
Set `compressed_delivery` to `true` when you create or update a webhook destination, and Nylas gzip-compresses each notification payload before sending the `POST` request to your endpoint. Nylas adds the `Content-Encoding: gzip` header so your handler knows to decompress.
:::warn
**The `X-Nylas-Signature` header is computed over the _compressed_ bytes.** Verify the signature against the raw request body _before_ decompressing. If you decompress first and then check the signature, verification fails.
:::
For the full walkthrough, including the request payload and signature validation pattern, see [Compressed webhook notifications](/docs/v3/notifications/#compressed-webhook-notifications).
## Compress Pub/Sub channel notifications
On Pub/Sub channels, set `compressed_delivery` to `true` and Nylas gzip-compresses each notification payload before publishing it to your topic. Nylas adds a `content_encoding: gzip` message attribute so your subscriber knows which messages to decompress.
See [Compressed Pub/Sub notifications](/docs/v3/notifications/pubsub-channel/#compressed-pubsub-notifications) for setup details.
## Compress SNS channel notifications
SNS has a hard 256 KB limit on message size, and Nylas strips message bodies from any payload that would exceed it. Enabling `compressed_delivery` on an SNS channel gzip-compresses the payload and then base64-encodes it (SNS messages must be valid UTF-8), and Nylas tags the message with a `content_encoding: gzip+base64` attribute.
:::success
**We strongly recommend enabling compressed delivery on SNS channels.** It's the single biggest lever for keeping large `message.*` notifications under the 256 KB limit. See [Compressed SNS notifications](/docs/v3/notifications/sns-channel/#compressed-sns-notifications) for the decode pattern.
:::
## Reduce payload size before compression
Compression shrinks what you send. Field selection controls what goes into the payload in the first place, and the two stack well.
For the `message.created`, `message.updated`, `event.created`, and `event.updated` webhook triggers, you can configure which fields Nylas includes in notifications from the **Customizations** section of the Nylas Dashboard. When Nylas sends a customized notification it adds the `.transformed` suffix to the trigger type (for example, `message.updated.transformed`), so make sure your handler accepts that type.
The `.transformed` suffix can also combine with `.cleaned` and `.truncated`, producing trigger types like `message.created.cleaned.transformed` or `message.created.transformed.truncated`. Your handler should match on prefix rather than exact string.
For the full walkthrough, see [Specify fields for webhook notifications](/docs/v3/notifications/#specify-fields-for-webhook-notifications).
## Related resources
- [Compressed webhook notifications](/docs/v3/notifications/#compressed-webhook-notifications)
- [Compressed Pub/Sub notifications](/docs/v3/notifications/pubsub-channel/#compressed-pubsub-notifications)
- [Compressed SNS notifications](/docs/v3/notifications/sns-channel/#compressed-sns-notifications)
- [Specify fields for webhook notifications](/docs/v3/notifications/#specify-fields-for-webhook-notifications)
- [Truncated webhook notifications](/docs/v3/notifications/#truncated-webhook-notifications)
- [Best practices for webhooks](/docs/dev-guide/best-practices/webhook-best-practices/)
────────────────────────────────────────────────────────────────────────────────
title: "Dealing with spam in Nylas"
description: "When spam occurs, and what to do if an account using your Nylas application is blocked."
source: "https://developer.nylas.com/docs/dev-guide/best-practices/dealing-with-spam/"
────────────────────────────────────────────────────────────────────────────────
:::success
**Receiving spam from a Nylas application?** [Learn how to report it](/docs/dev-guide/platform/report-abuse/).
:::
This page explains what to do if an account using your project is blocked for suspected spam.
## Blocked when sending messages
To preserve their message sending reputations, some providers will review all outbound messages through their spam filter before they're sent. Spam filters work by comparing messages to an extensive list of matching behaviors and giving each behavior a score. If the cumulative score of an outbound message exceeds a set threshold, the provider blocks the message.
Some spam filters look for automated senders like Nylas and add a score for using them. This is because spammers often use similar automated services. Because of this, some messages might go over the blocking threshold when sent using Nylas. Contact your email administrator if you have any questions about their spam filters.
If a message is blocked because of a spam filter, Nylas returns a response stating that the message was blocked. It doesn't have any visibility into what caused the message to be blocked, however.
### Message flagged as junk
"Bulking" refers to an email server's practice of accepting messages sent to its users, but routing them to a Bulk, Spam, or Junk folder or label. There are many reasons that providers do this, but Nylas has no visibility or control over the process. It often happens when a recipient's email server starts to receive a large number of messages from an IP address that's never sent to it before, or when recipients of earlier sends have flagged the messages as junk.
It's important to ramp up sending to new contacts, and to ask your recipients to mark your messages as not spam. You should also respect any unsubscribe requests and remove recipients who aren't engaging with your messages. For more information, see [Improving email deliverability with Nylas](/docs/dev-guide/best-practices/improving-email-delivery/).
### Message marked as spam
If your email records are configured incorrectly, that can cause a message to be marked as spam. The recipient's email server adds headers to messages that indicate whether the email records are configured correctly. If you see headers like `spf=pass`, `dkim=pass`, or `dmarc=pass`, this means that the sender is properly authorized. If any of the headers say `fail`, you should check with the sender's email administrator to verify that the records are configured properly.
## IP address blocked
Many Exchange servers have two SMTP servers: one for automated sending from applications like Nylas, and the other for sending messages directly from Outlook. Since one SMTP server handles the larger sends, it's more likely to be flagged as spam. This is because of the volume spikes compared to individual messages sent from the Outlook client.
Messages sent using Nylas are routed through the larger SMTP server and are more likely to get caught in any spam blocks on the server's IP address. If you see a bounce notification indicating your IP address has been blocked, bring it to your email administrator's attention. They can look into solutions, like getting a new IP address for the SMTP server. You should also review your outbound messages and make sure you're following [email deliverability best practices](/docs/dev-guide/best-practices/improving-email-delivery/) to avoid being blocked.
## Account blocked for spam
Sometimes, we receive reports from email providers about accounts that have been flagged for spam. As a preventative measure, and to comply with the [CAN-SPAM Act](https://www.ftc.gov/business-guidance/resources/can-spam-act-compliance-guide-business), the [GDPR](https://gdpr-info.eu/), and other anti-spam policies, Nylas is required to block the flagged accounts from making any API calls and report them to their respective organizations.
### How abuse reports work
When a message is marked as spam or junk, an abuse report is automatically created. The report is sent to the recipient's ISP (internet service provider) and a warning is sent to the sender's ESP (email service provider). If the message was sent using Nylas, our Customer Support team receives the warning, including...
- A copy of the sent message.
- A brief explanation that a complaint has been issued.
- The actions that must be taken to address the issue.
If Nylas doesn't address these warnings, our servers are blocked from sending messages.
## How Nylas addresses spam
To protect your reputation and our own, we carefully monitor abuse reports that we receive. If we detect that a message's content doesn't comply with the [CAN-SPAM Act](https://www.ftc.gov/business-guidance/resources/can-spam-act-compliance-guide-business), [GDPR](https://gdpr-info.eu/), [CASL](https://ised-isde.canada.ca/site/canada-anti-spam-legislation/en), or [CCPA](https://www.oag.ca.gov/privacy/ccpa) policies, we immediately block the originating account from making API requests and report it to its organization.
There are two things that happen when we block an account belonging to your organization:
- You receive a message titled "Notice: User Account Suspended" from Nylas Support. The message specified the affected grant ID and email address.
- All API requests from the grant return a [`403` error](/docs/api/errors/400-response/) until the account is unblocked.
### How to unblock grants
To get a user's grant unblocked, your organization needs to send an email confirmation that the user has been educated about anti-spam policies and that they won't engage in spam activities again.
The following guidelines can help your users avoid getting flagged for spam:
- [SendGrid: 12+ Tips to Stop Your Emails from Going to Spam](https://sendgrid.com/en-us/blog/10-tips-to-keep-email-out-of-the-spam-folder)
- [Mailchimp: How Legitimate Marketers Can Prevent Spam Complaints](https://mailchimp.com/help/how-legitimate-marketers-can-prevent-spam-complaints/)
- [WebEngage: 29 Tips To Avoid Spam Filters When Doing Email Marketing](https://webengage.com/blog/how-to-avoid-spam-filters-when-sending-emails/)
────────────────────────────────────────────────────────────────────────────────
title: "Monitoring for and handling errors in Nylas"
description: "Best practices for handling errors in your Nylas integration."
source: "https://developer.nylas.com/docs/dev-guide/best-practices/error-handling/"
────────────────────────────────────────────────────────────────────────────────
Although the Nylas APIs are highly available and robust, there's always a chance you'll encounter errors when you're using them. Most errors are transient and Nylas' retry with exponential backoff approach is successful in resolving them. Nylas works hard to ensure that outage incidents and transient errors from providers don't require intervention on your part.
:::success
**We follow industry best practices by reporting on outage incidents as soon as a problem is identified**. You can use our [status page](https://status.nylas.com/?utm_source=docs&utm_content=error-handling) to track ongoing incidents and get real-time updates on our progress resolving them.
:::
You'll need to prepare your project to handle the following types of errors:
- **Invalid credentials errors**: Generated when an account's OAuth token is expired or was revoked, or its password was changed.
- **API errors**: Generated when your project makes a request to the Nylas APIs and receives a non-`200` response, or encounters a network error.
This page describes strategies that we recommend to mitigate and resolve any errors you may come across.
## Monitor application health and status
:::success
**Nylas constantly tracks a variety of metrics across the platform and alerts an on-call engineer if it detects irregularities**.
:::
Because Nylas is a core part of many projects, it's a good practice to track errors coming from both your application and your Nylas integration. This lets you detect any problems that may arise. For example, you can track the success rate of requests sent to the Nylas APIs and alert if a certain percentage of requests fail.
We strongly recommend keeping logs of the errors you encounter to help with troubleshooting and resolving issues.
## Monitor for invalid credentials
Your users might need to re-authenticate with Nylas periodically to connect to their provider. When and how often they need to do this depends entirely on their provider's policies. Until the user re-authenticates their grant, you can still use their access token to work with their synced data. Nylas can't retrieve new data from their provider until they re-authenticate, though.
If a user originally authenticated their account by providing a username and password, they'll only need to re-authenticate when their password changes.
For detailed guidance on why grants expire, how to detect expiration, and how to build a re-authentication flow, see [Handling expired grants](/docs/dev-guide/best-practices/grant-lifecycle/).
## Monitor for API errors
Nylas follows the [HTTP standard for status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status), and returns `200 OK` responses when requests are completed without error. Other status codes, such as `4xx` or `5xx` errors, indicate that a request encountered an error.
:::info
**The Nylas SDKs raise exceptions when requests aren't successful**. If you're making your own HTTP requests, though, you should ensure your project checks status codes automatically.
:::
Nylas returns a consistent JSON object on errors. Each error object includes a `message` fields that lists details about the error. You can see more information about API errors your project has encountered in the [Nylas Dashboard](https://dashboard-v3.nylas.com/login?utm_source=docs&utm_content=error-handling) by selecting **Logs** in the left navigation.
The majority of errors you might encounter are most likely transient. Usually, Nylas' retry with exponential backoff approach is successful in resolving them. For more information, see our [error code documentation](/docs/api/errors/).
## Monitor for rate limits
[Nylas' rate limiting function](/docs/dev-guide/platform/rate-limits/) prevents a single account from affecting the reliability or performance of other accounts on the platform. Our rate limits are generous, so the Nylas API can accommodate any use case you can think of.
Nylas returns a [`429` error](/docs/api/errors/400-response/) when an account hits one of Nylas' rate limits. This prevents the account from making requests for a set amount of time. We recommend that you implement an exponential backoff strategy so accounts can recover and continue operating if they hit a rate limit.
Nylas is also subject to provider rate limits for the following activities:
- **Sending messages**: Nylas uses the email account associated with a grant to send messages through the user's provider. Different providers have different send limits, but most users never hit these limits during regular activities.
- **Creating and updating objects**: Because create and update actions are very rare, you're not likely to ever hit these limits.
- **Message attachments, raw MIME content, and contact pictures**: Nylas caches these objects internally in Amazon S3 for seven days. Requests for this data after the seven-day period require Nylas to fetch the data from the provider.
## Monitor for missed notifications
If your webhook server fails for a long period of time, Nylas marks the destination as failed. This means that Nylas stops trying to send webhook notifications for your project until the problem is fixed. See [Failing and failed webhooks](/docs/v3/notifications/#failing-and-failed-webhooks) for more information about failure limits and how Nylas sends failure notifications.
────────────────────────────────────────────────────────────────────────────────
title: "Handling expired grants"
description: "Best practices for detecting and recovering expired grants in your Nylas integration without losing data."
source: "https://developer.nylas.com/docs/dev-guide/best-practices/grant-lifecycle/"
────────────────────────────────────────────────────────────────────────────────
An expired grant does not mean something is wrong with your integration. Grants expire regularly as part of normal operation, and the vast majority are fully recoverable. Re-authenticating the user refreshes the provider tokens while preserving the grant ID, object IDs, sync state, and tracking links. In rare cases a provider issue may prevent token renewal, but even then the grant itself remains intact and can be re-authenticated once the provider resolves the issue.
:::error
**Do not delete expired grants.** Deleting an expired grant and recreating it causes permanent, irreversible data loss. Object IDs change, sync state resets, and tracking links break. Always attempt re-authentication first. See [what happens when you delete an expired grant](#what-happens-when-you-delete-an-expired-grant) for the full list of consequences.
:::
## Why grants expire
Grant expiration is a normal part of the lifecycle. When a grant expires, the provider token is invalidated, but the grant record itself remains intact in Nylas. The grant's data, configuration, and associated object IDs are all preserved.
Common causes include:
- The user changed their password.
- The user or an admin revoked your app's access.
- An organization-level policy forced a token refresh (common with Microsoft tenants).
- An Azure AD client secret expired.
- A transient provider error caused the token refresh to fail.
None of these situations require deleting the grant. Re-authentication resolves all of them.
## Re-authenticate instead of deleting
Re-authentication updates an existing grant with fresh provider tokens. The grant ID stays the same, object IDs are preserved, sync state is maintained, and active tracking links continue to work.
Nylas handles this automatically: when it receives an authentication request for an email address that already has a grant, it re-authenticates the existing grant instead of creating a new one. You do not need special logic to distinguish between first-time auth and re-auth. The flow and endpoints are identical. See [creating a grant](/docs/dev-guide/best-practices/manage-grants/#create-a-grant) for the available authentication methods.
Re-authentication also preserves your ability to catch up on missed data. If the grant was invalid for less than 72 hours, Nylas automatically backfills webhook notifications for any new or updated messages, events, and other objects that arrived during the outage. This backfill can produce a large volume of notifications, so make sure your [webhook destination can handle spikes](/docs/dev-guide/best-practices/webhook-best-practices/#building-for-scalability). If the grant was out of service for longer than 72 hours, Nylas skips the backfill. You can still recover by querying the Nylas APIs for changes that occurred between the [`grant.expired`](/docs/reference/notifications/grants/grant-expired/) and [`grant.updated`](/docs/reference/notifications/grants/grant-updated/) notification timestamps.
:::error
**Deleting an expired grant is permanent and cannot be undone.** If you delete a grant and then re-authenticate the same user, Nylas creates an entirely new grant with a new ID. You lose sync state, object IDs may change (especially for IMAP providers), and tracking links tied to the old grant stop working. Always re-authenticate instead.
:::
## What happens when you delete an expired grant
When you delete a grant and the user authenticates again, Nylas creates a new grant. This has several consequences.
**Object IDs change for IMAP providers.** Nylas generates message and thread IDs for IMAP accounts using the grant ID as part of the hash. A new grant means new IDs for every message, even ones the user received months ago. Any references your application stored to those old IDs become invalid. Google and Microsoft use provider-native IDs that are stable across grants, but even for those providers, you lose the continuity described below.
**Sync state resets.** Nylas starts a fresh sync for the new grant. Depending on mailbox size, this can take time, and your users see a gap in data until it completes.
**You lose webhook backfill for missed data.** When you re-authenticate an existing grant, Nylas backfills webhook notifications for anything that changed while the grant was invalid (within 72 hours). A new grant created after deletion has no previous sync state to compare against, so Nylas has no way to identify what changed during the gap. For Google, Microsoft, and EWS providers, the underlying data is still in the mailbox, but you would need to paginate through all messages or events to find what you missed. For IMAP providers, even that option is unreliable because the object IDs have changed.
**Tracking links break.** If you use Nylas message tracking (open tracking, link tracking, reply tracking), those tracking pixels and links are associated with the original grant ID. A deleted grant means Nylas can no longer match incoming tracking events to the correct grant, so you stop receiving [`message.opened`](/docs/reference/notifications/message-tracking/message-opened/), [`message.link_clicked`](/docs/reference/notifications/message-tracking/message-link_clicked/), and [`thread.replied`](/docs/reference/notifications/message-tracking/thread-replied/) notifications for messages sent before the deletion.
**The user goes through full auth again.** Instead of a token refresh, the user sees the complete OAuth consent screen. For enterprise accounts with admin consent requirements, this creates unnecessary friction.
## Detect expired grants
There are two signals that a grant has expired: API responses and webhooks. In practice, your application is more likely to hit a failed API request before Nylas detects the expiration through sync.
**API responses** are typically the first signal. If you make an API call using an expired grant, Nylas returns a 401 error. Your application should handle this by prompting the user to reconnect rather than treating it as a fatal error. Because this is often the earliest indication of an expired grant, every code path that calls the Nylas API should include 401 handling.
**Webhooks** provide proactive detection. Subscribe to [`grant.expired`](/docs/reference/notifications/grants/grant-expired/) notifications to receive alerts when Nylas confirms a grant is invalid. Nylas detects expired grants through periodic sync health checks, which can take up to 10 minutes depending on the provider. Without webhooks configured, you have no proactive signal at all, and may not discover the expiration for hours until your application next makes an API call for that grant.
You should implement both signals. Handle 401 responses in every API call to catch expirations immediately, and subscribe to `grant.expired` webhooks to detect expirations for grants that your application is not actively querying.
:::warn
**Avoid polling `GET /v3/grants/{id}` in a loop to check grant status.** This is inefficient and counts against your [rate limits](/docs/dev-guide/best-practices/rate-limits/). Use webhooks instead, and fall back to checking grant status only when you encounter a 401 during normal API usage.
:::
## Build a re-authentication flow
The re-authentication flow is identical to initial authentication. Use [Hosted OAuth](/docs/v3/auth/hosted-oauth-apikey/) or whichever auth method your application already uses. Nylas matches on the email address and updates the existing grant rather than creating a new one.
When you receive a `grant.expired` webhook, send the affected user an email notifying them that their connection has expired and that they need to log into your application to re-establish it. Include a direct link to your OAuth flow so the user can reconnect in as few steps as possible. The faster a user re-authenticates, the smaller the data gap and the less likely you are to exceed the 72-hour backfill window.
:::info
If you need a reliable way to deliver these re-authentication emails from your own domain without requiring a connected grant, the [Transactional Send API (Beta)](/docs/v3/getting-started/transactional-send/) lets you send email directly from a verified domain.
:::
After re-authentication succeeds, Nylas sends a [`grant.updated`](/docs/reference/notifications/grants/grant-updated/) notification. If the grant was invalid for less than 72 hours, expect a burst of backfill notifications as Nylas catches up on missed changes. If it was longer than 72 hours, query the Nylas APIs directly for changes that occurred during the outage.
## When to delete a grant
There are only two situations where deleting a grant makes sense:
- **The user explicitly wants to disconnect.** They're leaving your platform, or they want to permanently remove their account's connection to your application.
- **You need to stop billing for an abandoned account.** If a grant has been expired for an extended period and the user is clearly never coming back, deletion stops the billing. See the [billing documentation](/docs/support/billing/) for details.
In both cases, understand that deletion is irreversible. Nylas removes the grant record, revokes associated tokens, and stops all notifications. If the user comes back later, they start from scratch with a new grant.
For the deletion procedure, see [Delete a grant](/docs/dev-guide/best-practices/manage-grants/#delete-a-grant).
────────────────────────────────────────────────────────────────────────────────
title: "Improving email deliverability with Nylas"
description: "Optimize delivery of messages with Nylas."
source: "https://developer.nylas.com/docs/dev-guide/best-practices/improving-email-delivery/"
────────────────────────────────────────────────────────────────────────────────
To optimize message deliverability with Nylas, it's important to contact your user base selectively rather than sending thousands of emails per day from a single account. This page describes strategies to ensure your messages are delivered, without being tagged as spam or junk.
## Improve email deliverability
We recommend taking the following steps to improve your email deliverability:
- When you send a lot of messages in a group, space them out. We recommend you send them _at most_ once every 30 seconds.
- If a message doesn't get through (for example, the Nylas API returns a [`429` error code](/docs/api/errors/400-response/#error-429---nylas-api-rate-limit)), wait before retrying. If it fails again, use an exponential backoff approach to prevent the account from being flagged or rate-limited on the provider.
- Don't send more than the recommended 700 messages per day from a single grant. Some providers lock the user's account it if sends too many messages per day. For information on provider message limits, see [Provider rate limits](/docs/dev-guide/best-practices/rate-limits/#provider-rate-limits).
## Avoid being tagged as spam or junk
Unsolicited messages are more likely to raise flags compared to sending a message to someone you already have an email history with. Check out Mailchimp's [Most Common Spam Filter Triggers guide](https://mailchimp.com/resources/most-common-spam-filter-triggers/) for more information.
### Google sender requirements
As of February 2024, Google requires that accounts sending more than 5,000 messages per day to Gmail addresses take the following steps to verify their authenticity:
- Authenticate your email address' domain using the [Sender Policy Framework (SPF)](https://en.wikipedia.org/wiki/Sender_Policy_Framework), [DomainKeys Identified Mail (DKIM)](https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail), and [DMARC](https://en.wikipedia.org/wiki/DMARC) protocols.
- Ensure that your domain or IP has valid forward and reverse DNS records.
- Allow recipients to unsubscribe from mailing lists with a single click. The unsubscribe link needs to be clearly visible in the message body, and the request to unsubscribe must be processed within two days.
For more information, see Google's official [Email sender guidelines](https://support.google.com/a/answer/81126).
### Microsoft filters and reputation
Microsoft Outlook has a rigid filter system as well as a reputation system. If a specific email address sends a lot of messages but doesn't receive any replies, its reputation score decreases and Microsoft eventually tags it as a spam/junk sender. To avoid this, have recipients add your email address as a safe sender or as part of a safe mailing list.
If your messages are still tagged as spam/junk after a recipient marks them as safe, you might have a synchronization issue. This is usually solved by changing the account's password.
## Troubleshoot sending errors
If messages you send using Nylas are consistently bouncing or being flagged as spam/junk, there are a few troubleshooting steps you can take:
- Confirm that messages bounce or are flagged as spam/junk only when being sent using Nylas. Try sending the same message using your provider's web client.
- If the message is blocked when sent from the provider's client, the issue occurs either because of the provider's SMTP IP address or the sender's domain reputation. Contact your email administrator to troubleshoot the issue further.
- Confirm that your project isn't modifying the message headers. You should always use `Content-Type: application/json` with the [Send Message endpoint](/docs/reference/api/messages/send-message/).
- If the provider is Google or Microsoft, find the list of hostnames and IP addresses in the [message headers](/docs/support/troubleshooting/get-header-contents/) and check them using a [blacklist check tool](https://mxtoolbox.com/blacklists.aspx). If any are blacklisted, contact your email administrator and ask them to change the outbound SMTP server.
- Try sending the message with [link clicked tracking](/docs/v3/email/message-tracking/#link-clicked-tracking) disabled.
:::info
**If none of these tips fix the issue, make sure the email address isn't sending [**spam**](/docs/dev-guide/best-practices/dealing-with-spam/)**. If it is, the provider blocks sending on its own outbound server.
:::
If you need help with troubleshooting your project's deliverability, [learn how to get support](/docs/support/).
────────────────────────────────────────────────────────────────────────────────
title: "Security best practices"
description: "Best practices for securing your Nylas integration."
source: "https://developer.nylas.com/docs/dev-guide/best-practices/"
────────────────────────────────────────────────────────────────────────────────
The Nylas platform handles a lot of sensitive information, and it was built from the ground up with security in mind. Nylas implements strict access controls and auditing to make sure we're doing everything we can to protect sensitive user data and credentials. When you integrate with Nylas, you gain access to some of this sensitive data through access tokens. These tokens grant access to all of your users' account data via the Nylas APIs. The security of your users' tokens is crucial for your project.
Nylas does a lot of the work of implementing a secure process for you, especially when you use [Hosted Authentication](/docs/v3/auth/hosted-oauth-apikey/), which prevents you from directly handling and storing either credentials or OAuth tokens for your users' accounts.
This page lists some recommendations for maintaining a secure environment.
## Store secrets securely
If your project runs in a cloud environment, your infrastructure provider likely provides a secret management service that you should use. Some examples would be...
- [AWS KMS](https://aws.amazon.com/kms/)
- [Google Cloud Secret Manager](https://cloud.google.com/secret-manager/docs)
- [Azure Key Vault](https://azure.microsoft.com/en-us/services/key-vault/)
- [Heroku Config Store](https://devcenter.heroku.com/articles/config-vars)
- [Hashicorp Vault](https://www.vaultproject.io/)
When you use one of Nylas' [Hosted Authentication methods](/docs/v3/auth/hosted-oauth-apikey/), you should focus on protecting the following secrets:
- Your Nylas application's client ID and secret.
- Your Nylas access tokens.
- Your provider auth app's client ID and secret.
If you're using [Custom Authentication](/docs/v3/auth/custom/), you need to protect all of the secrets above _as well as_ users' passwords and OAuth refresh and access tokens.
If you're not using a secret manager to store these values, you should encrypt them both at rest and in transit. All requests to Nylas must be made over an encrypted TLS connection (HTTPS). We recommend you design your project so you don't send secrets outside of your own infrastructure. If you need to transmit secrets, be sure to use an encrypted connection.
Many databases have built-in encryption options, so you don't have to encrypt these secrets on your own. If you _do_ decide to encrypt the secrets in your project's code, be sure to use a well-known library like [libsodium](https://doc.libsodium.org/), or a secure library included in your programming language's standard methods.
We _don't_ recommend integrating Nylas on the client side of your project, as this gives more opportunities for credentials to be intercepted.
## Encrypt stored user data
If your project stores sensitive data from the Nylas API on its servers, you should implement some disk- and/or database-level encryption so all of the data is encrypted at rest. You should also ensure that the data is encrypted whenever it's in transit. This can usually be done by using TLS connections.
## Revoke old access tokens
Nylas' access tokens don't expire. When you detect that a user has re-authenticated their grant, you should revoke their unused tokens to minimize the number of active tokens.
We recommend you set up your project to automatically make [`POST /v3/connect/revoke` requests](/docs/reference/api/authentication-apis/revoke_oauth2_token_and_grant/) when a user re-authenticates, disconnects, or cancels their account. At any given time, your project should only hold one access token per grant.
## More security resources
The following key management and cryptographic storage cheat sheets provide a good overview of how you can protect your Nylas client secrets and access tokens.
- [Key Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Key_Management_Cheat_Sheet.html)
- [Cryptographic Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html)
The [Key Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Key_Management_Cheat_Sheet.html) is an easy to follow, high-level guide on the basics of encryption that explains the concepts required to build a secure application.
We also recommend you double-check any libraries or encryption algorithms you use to make sure they're _actually_ secure. Cryptographic libraries can have vulnerabilities in their implementations, even if they're based on secure algorithms. This applies to bindings for different languages as well, because most encryption libraries are implemented in low-level languages like C or C++.
:::success
**If you're not sure how to properly secure your data, [**contact Nylas Support**](https://support.nylas.com/hc/en-us/requests/new) and we'll help**.
:::
────────────────────────────────────────────────────────────────────────────────
title: "Managing grants"
description: "Update, re-authenticate, and delete grants."
source: "https://developer.nylas.com/docs/dev-guide/best-practices/manage-grants/"
────────────────────────────────────────────────────────────────────────────────
:::info
**Handling expired grants?** See [Handling expired grants](/docs/dev-guide/best-practices/grant-lifecycle/) for guidance on re-authenticating expired grants and avoiding common pitfalls like deleting grants unnecessarily.
:::
Grants are the main objects that power Nylas, representing your users' authenticated accounts and the scopes they've approved for your project. This page describes how to manage grants throughout their lifecycle.
## What are grants?
A grant is a record of a user's account authenticating successfully with their provider and "granting" your project access to specific parts of their account's email inbox and calendar. This access is represented by the [scopes](/docs/dev-guide/scopes/) they approve when they authenticate.
A valid grant records a unique ID for the user, the scopes that they approved during authentication, and some information about access tokens.
Each grant belongs to a specific connector, in a specific Nylas application. A grant can't be associated with multiple connectors, providers, or Nylas applications.
## Create a grant
Nylas offers multiple ways to create grants:
- [Using Hosted OAuth with an API key](/docs/v3/auth/hosted-oauth-apikey/).
- [Using Hosted OAuth with an access token](/docs/v3/auth/hosted-oauth-accesstoken/).
- [Using Custom Authentication](/docs/v3/auth/custom/).
- [Using IMAP authentication](/docs/v3/auth/imap/).
Be sure to [choose the authentication method that's right for you](/docs/v3/auth/#choose-an-authentication-method) before you start developing your project.
## Re-authenticate a grant
Grants can become invalid for many reasons (for example, the user changed their password or revoked access to your project). When this happens, Nylas loses access to the user's data and stops sending notifications about changes to their objects. You need to re-authenticate the user's grant to restore access.
When the user re-authenticates successfully, Nylas looks at when their grant was last valid. If it was less than 72 hours ago, Nylas looks for any changes that happened since the last successful sync and sends you [notifications](/docs/v3/notifications/) about those events. This can be _a lot_ of notifications, so be sure to [set up your webhook destination to handle notifications at scale](/docs/dev-guide/best-practices/webhook-best-practices/#building-for-scalability).
If the grant was out of service for more than 72 hours, Nylas doesn't send backfill notifications. When this happens, you can look for the appropriate [`grant.expired`](/docs/reference/notifications/grants/grant-expired/) and [`grant.updated`](/docs/reference/notifications/grants/grant-updated/) notifications, then query the Nylas APIs for objects that changed between those timestamps.
:::warn
**If message tracking events occur while a grant is out of service for more than 72 hours, you can't backfill the notifications**. This includes [`message.opened`](/docs/reference/notifications/message-tracking/message-opened/), [`message.link_clicked`](/docs/reference/notifications/message-tracking/message-link_clicked/), and [`thread.replied`](/docs/reference/notifications/message-tracking/thread-replied/) notifications.
:::
Re-authenticating a grant follows the same flow and uses the same endpoints as the initial authentication process. When Nylas receives an authentication request, it checks to see if a grant is already associated with the user's email address. If one exists, Nylas re-authenticates the grant instead of creating a new one.
### Monitor grants for invalid state
You can use one of the following methods to monitor grants for an invalid state:
- **(Recommended) Subscribe to `grant.*` notifications** to stay up to date with status changes. If you receive a [`grant.expired` notification](/docs/reference/notifications/grants/grant-expired/), the affected grant needs to be re-authenticated.
- **Make poll requests to the [**Get all grants endpoint**](/docs/reference/api/manage-grants/get-all-grants/)** and check each `grant_status`.
- **Log in to the [**Nylas Dashboard**](https://dashboard-v3.nylas.com/?utm_source=docs&utm_content=manage-grants)** and select **Grants** in the left navigation. Grants that need to be re-authenticated are marked as **Invalid**.
## Delete a grant
:::warn
**Before deleting a grant, make sure re-authentication isn't the better option.** Deleting a grant is permanent and causes object IDs to change, sync state to reset, and tracking links to break. See [Handling expired grants](/docs/dev-guide/best-practices/grant-lifecycle/#what-happens-when-you-delete-an-expired-grant) for details.
:::
If a user no longer needs access to your project, you can delete their grant by making a [Delete Grant request](/docs/reference/api/manage-grants/delete_grant_by_id/). Nylas also revokes the refresh token and any access tokens associated with the grant.
If you're deleting a Google grant, Nylas also revokes its provider token. For all other providers, the provider tokens remain active.
:::error
**When you make a [**Delete Grant request**](/docs/reference/api/manage-grants/delete_grant_by_id/), Nylas deletes the grant and stops sending notifications for it**. You can't re-authenticate the deleted grant. If you try to re-authenticate it, Nylas creates a new grant instead.
:::
You can also delete a grant in the [Nylas Dashboard](https://dashboard-v3.nylas.com/?utm_source=docs&utm_content=manage-grants):
1. Select **Grants** from the left navigation.
2. Find the grant that you want to delete and click the **options** symbol (`⋮`) beside it.
3. Click **Delete** and confirm that you want to delete the grant.
### Revoked versus deleted grants
A grant can be revoked in multiple scenarios (for example, the user changed their password). When this happens, the grant's token is invalidated and the user can't access your project until they re-authenticate. Nylas also can't update the data for a revoked grant.
Nylas stores the data for grants as long as they're associated with your application, even if they're revoked. Nylas deletes a grant's data only when the grant itself is deleted.
:::info
**Nylas bills for all grants associated with your application, even if they're revoked**. When you delete a grant, your organization is no longer billed for it. For more information, see our [billing documentation](/docs/support/billing/).
:::
────────────────────────────────────────────────────────────────────────────────
title: "Avoiding rate limits in Nylas"
description: "Best practices to avoid hitting rate limits while using Nylas."
source: "https://developer.nylas.com/docs/dev-guide/best-practices/rate-limits/"
────────────────────────────────────────────────────────────────────────────────
Your project needs to adhere to both Nylas- and provider-set [rate limits](/docs/dev-guide/platform/rate-limits/). This page lays out some best practices that we recommend you implement to avoid being rate-limited.
## What are rate limits?
Service providers set rate limits to cap the number of requests you can make for data over a set period of time. If the volume of requests meets or exceeds a rate limit, the provider temporarily reduces its response rate and returns an error.
When you integrate with Nylas, you make requests to the Nylas APIs for information and Nylas queries the provider on your behalf. Sometimes, a single request to the Nylas APIs can require multiple requests to the provider to return the information you're looking for. For example, a user might cause rate limits when they bulk-send messages to a group of recipients. In this case, your project makes a large number of [Send Message requests](/docs/reference/api/messages/send-message/), and Nylas makes its own requests to the provider.
When a user hits [Nylas' rate limits](/docs/dev-guide/platform/rate-limits/#nylas-rate-limits), Nylas temporarily stops responding to requests and instead returns a [`429` error code](/docs/api/errors/400-response/).
### Threads rate limits
:::warn
**The [**Return all Threads endpoint**](/docs/reference/api/threads/get-threads/) makes a significant number of calls to the provider for each request you make**. We strongly recommend using query parameters to limit the data Nylas returns.
:::
Because of the number of calls Nylas makes to the provider for each [Get all Threads request](/docs/reference/api/threads/get-threads/), you might encounter rate limits when working with large threads of messages. You can take the following steps to avoid this:
- Specify a lower `limit` to reduce the number of results Nylas returns per page.
- Add query parameters to your request to filter for specific information.
## Filter requests using query parameters
One of the best ways to avoid hitting rate limits is to use query parameters to filter the results Nylas returns. Nylas supports query parameters for each `GET` endpoint that returns a list of results.
- `limit`: Set the maximum number of results Nylas returns for your request.
- `offset`: Set a zero-based offset from Nylas' default sorting (for example, `offset=30` skips the first 30 results).
- `search_query_native`: Specify a provider-specific query string to search messages or threads.
- `select`: Specify the fields Nylas returns for your request (for example, `select=id,updated_at`).
For more information, see the [Administration](/docs/reference/api/) and [Email, Calendar, Contacts, and Notetaker](/docs/reference/api/) API references.
### Provider-native search strings for email filtering
You can search for messages using a [Get all Messages request](/docs/reference/api/messages/get-messages/) and the available query parameters. Similarly, you can search for threads by making a [Get all Threads request](/docs/reference/api/threads/get-threads/).
[The `search_query_native` query parameter](/docs/dev-guide/best-practices/search/#search-messages-and-threads-using-search_query_native) lets you add provider-specific query strings to your request (for example, you can use it to filter with the `NOT` operator).
## Reduce response size with field selection
You can use the `select` query parameter to specify which fields you want Nylas to return. This reduces response sizes, improves latency, and helps you avoid rate limiting issues and [`429` errors](/docs/api/errors/400-response/). You can also use field selection in cases where you want to avoid working with user information that you think might be sensitive.
For example, when working with potentially large objects like messages, you can have Nylas return only the fields you want to work with and skip the big ones like `body`. The following example specifies Nylas should return only the `id`, `from`, and `subject` fields of the Message object.
```bash [select-Request]
curl --request GET \
--url 'https://api.us.nylas.com/v3/grants/me/messages?select=id,from,subject' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json'
```
```json [select-Response (JSON)]
{
"request_id": "5fa64c92-e840-4357-86b9-2aa364d35b88",
"data": [
{
"id": "",
"from": "nyla@example.com",
"subject": "RE: Annual Philosophy Club Meeting"
},
{
"id": "",
"from": "electronics@example.com",
"subject": "Your order has been delivered!"
}
]
}
```
:::info
**Field selection evaluates top-level object fields only**. You can't use it to return only nested fields.
:::
You can include the `select` query parameter with all Nylas API endpoints, _except_ the following:
- All `DELETE` endpoints.
- All Attachments endpoints.
- All Smart Compose endpoints.
- All Webhooks endpoints.
- The Send Message endpoint.
- The Create a Draft endpoint.
We strongly suggest you always use field selection so you only get the data that you need.
────────────────────────────────────────────────────────────────────────────────
title: "Searching with Nylas"
description: "Search your users' data using query parameters and metadata filtering."
source: "https://developer.nylas.com/docs/dev-guide/best-practices/search/"
────────────────────────────────────────────────────────────────────────────────
Depending on the number of users authenticated to your project, Nylas might return _a lot_ of data for "Get all" requests. This page explains how you can search and filter your users' data.
## How searching works in Nylas
Generally, filtering for data follows this flow:
1. Determine the [query parameters](#query-parameters) you plan to use.
2. Make a "Get all" request (for example, [Get all Messages](/docs/reference/api/messages/get-messages/)) with your query parameters.
3. Inspect the results to find the ID of the object you want to work with.
To get more information about a specific object, you can make a `GET` request with the object's ID.
## Search for grants
Nylas supports the following standard query parameters for [Get all Grants requests](/docs/reference/api/manage-grants/get-all-grants/):
- `before`, `since`
- `grant_status`, `email`, `provider`, `ip`
- `account_id`, `account_ids`
:::info
**`account_id` and `account_ids` are populated for grants created during the v2-to-v3 migration process only**. For all other grants, these fields are blank.
:::
## Search for calendars
Calendars are tied to users' grants, so you have to specify a grant ID when you make a [Get all Calendars request](/docs/reference/api/calendar/get-all-calendars/). We don't expect users to have a large number of individual calendars, so the search options Nylas offers for calendars are minimal.
If you know that the calendar you want to work with is the user's primary calendar (for providers that support it), you can use `primary` as the calendar locator instead of searching for a calendar ID.
## Search for events
:::warn
**You can only search for events from one calendar at a time**. You need to include a calendar ID (or `primary`, for providers that support it) in your [Get all Events request](/docs/reference/api/events/get-all-events/) to search for events. Nylas returns a [`400` error](/docs/api/errors/400-response/) if you don't specify a calendar.
:::
Nylas supports the following standard query parameters for [Get all Events requests](/docs/reference/api/events/get-all-events/):
- `title`, `description`, `location`
- `start`, `end`
- `event_type` - Google only.
- `updated_before`, `updated_after` - Google, Microsoft, and EWS only.
- `ical_uid`, `master_event_id`, `busy` - Not supported for iCloud.
- `attendees` - Not supported for virtual calendars.
- `show_cancelled` - Not supported for iCloud or EWS.
### Microsoft Graph query considerations for events
When you search for events on Microsoft Graph, the number of days between the `start` and `end` values can't be greater than 1,825 days. If you need to find events over a longer time period, you'll need to make multiple requests.
### iCloud query considerations for events
If you're searching for an event within a certain time range on iCloud, the difference between `start` and `end` can't be greater than six months. If you include a time range greater than six months, Nylas returns an "Invalid request" error.
## Search for drafts
Nylas supports the following standard query parameters for [Get all Drafts requests](/docs/reference/api/drafts/get-drafts/):
- `subject`, `thread_id`
- `any_email`, `to`, `cc`, `bcc`
- `starred`, `has_attachment`
## Search for messages
Nylas supports the following standard query parameters for [Get all Messages requests](/docs/reference/api/messages/get-messages/):
- `subject`, `thread_id`
- `any_email`, `to`, `from`, `cc`, `bcc`
- `received_before`, `received_after`
- `in`, `unread`, `starred`, `has_attachment`
- `fields`
:::info
**Nylas doesn't support filtering for folders using keywords or attributes**. For example, `in:inbox` returns a [`400` error](/docs/api/errors/400-response/). Instead, you should use the folder ID with `in` to get the data you need.
:::
You can also use the [`search_query_native` parameter](#search-messages-and-threads-using-search_query_native) to define URL-encoded provider-specific query strings for Google, Microsoft Graph, EWS, and IMAP.
## Search for threads
Nylas supports the following standard query parameters for [Get all Threads requests](/docs/reference/api/threads/get-threads/):
- `subject`
- `any_email`, `to`, `from`, `cc`, `bcc`
- `latest_message_before`, `latest_message_after`
- `in`, `unread`, `starred`, `has_attachment`
:::info
**Nylas doesn't support filtering for folders using keywords or attributes**. For example, `in:inbox` returns a [`400` error](/docs/api/errors/400-response/). Instead, you should use the folder ID with `in` to get the data you need.
:::
You can also use the [`search_query_native` parameter](#search-messages-and-threads-using-search_query_native) to define URL-encoded provider-specific query strings for Google, Microsoft Graph, EWS, and IMAP.
## Search messages and threads using `search_query_native`
You can include the `search_query_native` query parameter in [Get all Messages](/docs/reference/api/messages/get-messages/) and [Get all Threads](/docs/reference/api/threads/get-threads/) requests to search using a URL-encoded provider-specific query string. Nylas supports `search_query_native` for [Google](https://support.google.com/mail/answer/7190?hl=en), [Microsoft Graph](https://learn.microsoft.com/en-us/graph/search-query-parameter?tabs=http#using-search-on-message-collections), [EWS](https://learn.microsoft.com/en-us/windows/win32/lwef/-search-2x-wds-aqsreference), and [IMAP](https://datatracker.ietf.org/doc/html/rfc3501#section-6.4.4).
:::warn
**Some IMAP providers don't support the `SEARCH` operator**. If you try to use it, you might get a [`400` error](/docs/api/errors/400-response/). In these cases, we recommend using the standard query parameters for [messages](#search-for-messages) and [threads](#search-for-threads) instead.
:::
For example, if you want to search a Google account for messages with "foo" or "bar" in the subject, you first create the provider-specific query string (`subject:foo OR subject:bar`), then URL-encode it (`subject%3Afoo%20OR%20subject%3Abar`) and include it in your request.
```bash {2}
curl --request GET \
--url "https://api.us.nylas.com/v3/grants//messages?search_query_native=subject%3Afoo%20OR%20subject%3Abar" \
--header 'Accept: application/json' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json'
```
You can also use [Microsoft Graph `$filter` queries](https://learn.microsoft.com/en-us/graph/filter-query-parameter) in the `search_query_native` parameter. For example, if you want to find messages where one of the participants is `leyah@example.com`, first create the query string (`$filter=from/emailAddress/address eq 'leyah@example.com'`), then URL-encode it (`%24filter%3Dfrom%2FemailAddress%2Faddress%20eq%20%27leyah%40example.com%27`) and include it in your request.
```bash {2}
curl --request GET \
--url "https://api.us.nylas.com/v3/grants//messages?search_query_native=%24filter%3Dfrom%2FemailAddress%2Faddress%20eq%20%27leyah%40example.com%27" \
--header 'Accept: application/json' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json'
```
If you include `search_query_native` in a [Get all Messages request](/docs/reference/api/messages/get-messages/), you can only use a limited set of query parameters with it, depending on the provider:
- **Microsoft**: `in`, `limit`, and `page_token`
- **Google**: `in`, `limit`, and `page_token`
- **EWS**: All query parameters _except_ `thread_id`
Similarly, you can only use the `in`, `limit`, and `page_token` parameters with `search_query_native` in [Get all Threads requests](/docs/reference/api/threads/get-threads/) on all providers _except_ EWS. If you include any other query parameters, Nylas returns an error.
## Search for folders
Nylas supports the `parent_id` query parameter for folders in Microsoft and EWS accounts only. You can use it to get all of the sub-folders under a specific folder.
Nylas doesn't support filtering for folders using keywords or attributes. For example, `in:inbox` returns a [`400` error](/docs/api/errors/400-response/). Instead, you should use the folder ID with `in` to get the data you need.
## Search for attachments
You can search for attachments by making a [Get all Messages](/docs/reference/api/messages/get-messages/) or [Get all Threads](/docs/reference/api/threads/get-threads/) request that includes the `has_attachment` query parameter. Nylas returns only the objects that include attachments, so you can sort through them to find the file you want to work with, then make a [Get Attachment Metadata](/docs/reference/api/attachments/get-attachments-id/) or [Download Attachment](/docs/reference/api/attachments/get-attachments-id-download/) request using the attachment ID and the associated message ID.
## Search for contacts
Nylas supports the following standard query parameters for [Get all Contacts requests](/docs/reference/api/contacts/list-contact/):
- `email`, `source`
- `phone_number` - Google only.
- `group` - Not supported for EWS.
- `recurse` - Microsoft only.
## Search for contact groups
You can search for contact groups on all providers _except_ EWS. The [Get all Contact Groups endpoint](/docs/reference/api/contacts/list-contact-groups/) only accepts the query parameters that allow you to [sort responses](/docs/dev-guide/best-practices/rate-limits/#filter-results-using-query-parameters) and those that [limit the results Nylas returns](/docs/dev-guide/best-practices/rate-limits/#reduce-response-size-with-field-selection).
## Microsoft Graph immutable identifiers
Nylas returns globally unique, immutable identifiers for messages and threads. This means that if you store a Nylas `message_id` or `thread_id` in your database, you can reliably use it to retrieve the same message or thread at any time in the future.
For Microsoft Graph–backed accounts, Nylas uses immutable identifiers to ensure consistency even if a message is moved between folders.
**Note: Draft exception**
When a draft message is sent, the provider creates a new sent message object. As a result, the draft and the resulting sent message have different identifiers. If your application stores draft `message_id` values, you should treat the sent message as a new object and update any stored references accordingly.
## Microsoft Graph mutually exclusive query parameters
When you list messages or threads for Microsoft Graph accounts, certain types of query parameters become mutually exclusive. This means that if you use any parameters from the first group, you cannot use any from the second, and vice versa.
- **Group 1**: Specific, broadly defined provider categories (`thread_id`, `unread`, and `starred`).
- **Group 2**: Specific envelope fields (`subject`, `to`, `cc`, `bcc`, and `any_email`).
For example, you can't use the `starred` query parameter while also filtering for threads `to` a specific email address.
Historically, Nylas hasn't seen many combinations of these query parameters. If this limitation is negatively impacting your experience, [contact Nylas Support](https://support.nylas.com/hc/en-us/requests/new).
## EWS query considerations
Nylas query parameters can only work for on-premises Microsoft Exchange servers if an administrator has enabled search indexing for all mailboxes, and the Advanced Query Syntax (AQS) parser is supported. If query parameters are not returning expected results, contact the server administrator to check if this setting has been enabled.
Even though Nylas accepts any Unix timestamp for `received_before`, `received_after`, `latest_message_before`, and `latest_message_after`, the filtering on EWS is limited to the same day (for example, 01/01/2001), and the results are inclusive of the specified day. For more information, see [Microsoft's notes on AQS query strings](https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/querystring-querystringtype#remarks).
The accuracy of search results using `to`, `from`, `cc`, `bcc`, or `any_email` depends on the search indexing speed of your on-premises Microsoft Exchange server. For example, if you try to query Nylas for a message that just came in, but the Exchange server hasn't indexed it yet, Nylas doesn't return it. However, the message will be available after the next search index refresh.
────────────────────────────────────────────────────────────────────────────────
title: "Best practices for webhooks"
description: "Tips and considerations when implementing webhooks with your Nylas applications."
source: "https://developer.nylas.com/docs/dev-guide/best-practices/webhook-best-practices/"
────────────────────────────────────────────────────────────────────────────────
This page includes best practices, tips, and architecture considerations to keep in mind while implementing webhooks with your Nylas application.
## Testing webhooks in a development environment
The best way to test your webhook triggers and notifications is to use a Nylas application in a development environment. This prevents you from being overwhelmed by notifications if something goes wrong, so you can test and fine-tune them before setting them up on a production-volume application.
## Building for scalability
It's important to keep scalability in mind as you build your project. For example, an application with 20 grants on the same domain and 50 shared calendars can easily generate more than 20,000 `event.updated` notifications in just a few seconds.
:::warn
**If your webhook endpoint takes more than 10 seconds to handle incoming requests, it hits Nylas' timeout threshold and the request fails**. For more information, see [Failing and failed webhooks](/docs/v3/notifications/#failing-and-failed-webhooks).
:::
### Creating ordering logic
The [Webhook specification](https://github.com/standard-webhooks/standard-webhooks/blob/main/spec/standard-webhooks.md) makes no guarantees about deliverability of webhook notifications, or the order in which they're delivered. This allows webhooks to function regardless of your project's internal architecture, external provider behavior, or transient endpoint errors.
Most of the time, webhook notifications match the order of events on the objects that triggered them. Your Nylas application should be able to handle the rare case when it receives an `.updated` or `.deleted` webhook notification before a `.created` notification for an object.
### Using asynchronous processing
We _strongly_ recommend you use asynchronous processing on your webhook endpoint, along with a queueing system. This allows notifications to be processed by a separate service that fetches data about the objects. With this infrastructure, your webhook endpoint remains responsive even during high-volume bursts of notifications (for example, when users first authenticate with your project).
### Distributing notification processing
You should prepare for your project to receive a large volume of webhook notifications at any time. One way to build for this is to put webhook processing servers behind a load balancer that's configured for round-robin distribution. This allows you to scale by adding more servers behind the load balancer during periods of heavy traffic so you can maintain high availability on your receiving system.
### Monitoring webhook endpoints for downtime
You should monitor your webhook endpoints to ensure they remain available, and to respond in the event that they become unavailable.
We recommend building your application so that if a webhook endpoint goes down, your application automatically restarts it. After the endpoint is available again, you can manually fetch the objects that were modified during the downtime and process them appropriately.
### Enabling compressed delivery
Set `compressed_delivery` to `true` when you create or update a webhook destination, and Nylas gzip-compresses each notification payload before `POST`ing it to your endpoint. This reduces bandwidth, speeds up delivery under load, and helps compressed payloads pass through firewalls and WAFs that would otherwise block requests containing HTML in email bodies. Verify the `X-Nylas-Signature` header against the raw compressed body _before_ decompressing. For the full walkthrough, see [Reducing payload size with compression](/docs/dev-guide/best-practices/compression/).
## Monitoring grant status
We recommend you subscribe to the following webhook triggers to monitor the status of your users' grants:
- [`grant.created`](/docs/reference/notifications/grants/grant-created/)
- [`grant.updated`](/docs/reference/notifications/grants/grant-updated/)
- [`grant.deleted`](/docs/reference/notifications/grants/grant-deleted/)
- [`grant.expired`](/docs/reference/notifications/grants/grant-expired/)
The `grant.expired` trigger allows your project to monitor for when a user's grant becomes invalid. We recommend that you set up your project so that when it receives this notification, it identifies the affected user and prompts them to re-authenticate. For a complete guide on detection, recovery, and what to avoid, see [Handling expired grants](/docs/dev-guide/best-practices/grant-lifecycle/).
:::warn
**Nylas can't access a user's data when their grant becomes invalid, and doesn't send you webhook notifications about it**. We recommend that when a user re-authenticates, you find the most recent `grant.expired` and `grant.updated` notifications associated with the grant and query for any data that the user might have received between those times. This lets you backfill any changes that might have happened while the grant was invalid.
:::
## Monitoring tracked messages
If your users are sending messages through your project, you can use Nylas' [message tracking webhook triggers](/docs/v3/email/message-tracking/#enable-message-tracking) to simplify how you get notifications for certain actions.
────────────────────────────────────────────────────────────────────────────────
title: "Using the Nylas Dashboard"
description: "Use the Nylas Dashboard to manage your application settings, including authentication configuration and connectors, grants, and other details."
source: "https://developer.nylas.com/docs/dev-guide/dashboard/"
────────────────────────────────────────────────────────────────────────────────
The [Nylas Dashboard](https://dashboard-v3.nylas.com/?utm_source=docs&utm_content=dashboard) is where you create and manage your Nylas applications, generate API keys, and see API key secrets.
## Create Nylas application
:::info
**If you're new to Nylas and on the Free tier, you can only create a Sandbox application**. To create an application that you can move to production, check out our [subscription options](https://www.nylas.com/pricing/?utm_source=docs&utm_content=using-dashboard) to find the plan that's right for you.
:::
To create a Nylas application...
1. Log in to the [Dashboard](https://dashboard-v3.nylas.com/login?utm_source=docs&utm_content=dashboard).
2. Expand the **application** menu at the top-left of the Dashboard.
3. Click **Create new application**.
4. Enter a **name** and **description** for the application.
5. Choose a [**data residency location**](/docs/dev-guide/platform/data-residency/). This is where Nylas stores your application and user data. This setting can't be changed after you create the application.
6. Choose an **environment**.
7. Click **Create application**.
For [GDPR](https://en.wikipedia.org/wiki/General_Data_Protection_Regulation) compliance purposes, Nylas stores all organization and Dashboard-user information in our E.U. data center.
## Get your API key
Every Nylas application lists its API keys and their expiration status on the **API keys** page. This is also where you go to create, edit, and revoke keys.

When you create an API key, you can set its **name** and **expiration time**. For security purposes, we recommend you set the expiration timeline for production API keys to _up to a year_ in the future.
When you create an API key, you specify its **name** and **expiration timeline**. For security purposes, we recommend you set the expiration timeline for API keys in your production environment for _up to a year_ in the future. Nylas generates the key and displays its secret.
:::warn
**The Dashboard only displays API key secrets once**. Make sure to [store them in a secure place](/docs/dev-guide/best-practices/security/#storing-secrets-securely), like a secrets manager. If you lose an API key secret, you can't use the key and must generate a new one.
:::
## Organization management
You can manage various organization-level settings in the [Nylas Dashboard](https://dashboard-v3.nylas.com/login?utm_source=docs&utm_content=dashboard), including [billing details](#manage-billing-details) and [members and access levels](#manage-members-and-dashboard-access-levels).
### Manage billing details
The **Billing & usage** page displays an overview of your organization's Nylas plan, any available invoices up to 2 years old, and your payment details. Here, you can download past invoices, and update the contact information and credit card information for your Nylas organization.
To access these settings, expand the **account** menu at the top-right of the Nylas Dashboard and click the **gear** symbol next to your organization's name, then choose **Billing** in the left navigation.
### Manage members and Dashboard access levels
The **Members** page shows a list of all members of your Nylas organization and their roles. If you're logged in as a user with Admin permissions, you can invite users to the organization, update members' user roles, and remove users from the organization.
Nylas offers three different user roles, each with different levels of access to Dashboard data:
- **Member**: Allows view access to Development, Staging, and Sandbox applications. Members can view the organization membership list, but can't change it or invite users.
- **Admin**: Allows access to see _and edit_ all applications, regardless of their environment. Admins can view and update the organization membership list, including changing users' roles and inviting users.
- **Support**: Allows view access to all applications' logs.
You set access roles at the organization level, and they apply to all Nylas applications in the organization.
## Set up multi-factor authentication
The Nylas Dashboard supports multi-factor authentication (MFA) to secure your account and your organization's Nylas applications. MFA requires users to provide a second verification factor along with their password to log in to their Dashboard account.
:::info
**MFA is only available for users who log in to the Dashboard with an email address and password**. If you log in using Google or Microsoft, you're using single sign-on (SSO) and don't need MFA.
:::
### Enable multi-factor authentication for individual users
If you log in to the Nylas Dashboard using an email address and password, you can set up MFA for your account even if your organization doesn't require it.
1. Log in to the [Dashboard](https://dashboard-v3.nylas.com/login?utm_source=docs&utm_content=dashboard).
2. Expand the **account** menu at the top-right of the page.
3. Click the **gear** symbol next to your account name.
4. Select **Enable MFA**.
5. Scan the QR code using your preferred authenticator app and follow the steps displayed.
### Enable multi-factor authentication for organization
If you're the administrator of your organization, you can choose to require MFA at login for any users whose accounts don't use SSO.
1. Log in to the [Dashboard](https://dashboard-v3.nylas.com/login?utm_source=docs&utm_content=dashboard) as a user with Admin permissions.
2. Expand the **account** menu at the top-right of the page.
3. Click the **gear** symbol next to your organization's name.
4. Toggle **Require multi-factor authentication (MFA)** to **on**.
The next time users sign in, they'll be prompted to set up MFA for their account. Users who are logged in when you enable this setting aren't logged out immediately, and they don't receive an email notification about the new requirement.
────────────────────────────────────────────────────────────────────────────────
title: "Developing with Nylas"
description: "Get started developing a project with Nylas."
source: "https://developer.nylas.com/docs/dev-guide/develop-with-nylas/"
────────────────────────────────────────────────────────────────────────────────
Developing a project with a Nylas integration can be divided into a few phases. This guide is here to help you along the way. 🚀
1. [Set up your Nylas account and organization](#create-a-nylas-account-and-organization).
2. [Create a Nylas application for development](#create-a-nylas-application-for-development).
3. [Plan your project](#plan-your-project).
4. [Choose how to authenticate your users](#choose-how-to-authenticate-users).
5. [Create your provider auth apps](#create-provider-auth-apps).
6. [Start developing with the Nylas APIs](#start-developing-with-nylas).
7. Set up [notifications](#set-up-notifications) and [systems for handling them at scale](/docs/dev-guide/best-practices/webhook-best-practices/).
8. [Set up grant status monitoring](#set-up-grant-status-monitoring) using webhooks.
9. [Set up error monitoring and handling](#set-up-error-monitoring-and-handling).
10. Complete our [Production Checklist](#production-checklist) to get your app through provider security reviews, published, and launched!
## Create a Nylas account and organization
When you're ready to start, [create a Nylas account](https://dashboard-v3.nylas.com/register?utm_source=docs&utm_content=dev-w-nylas). If you're the first person on your team to create an account, you can make your account the "organization" and invite colleagues who're helping with development and testing. The account that hosts the organization is the one that has billing details attached to it, so decide amongst yourselves which account should "host" the organization.
An **organization** represents a company using the Nylas platform. It's a collection of Nylas applications and Dashboard accounts which are linked together and paid for in the same way. Billing, support, data usage, and feature enablement are handled at the organization level.
:::info
**When you first sign up with Nylas, your account is on an unpaid trial**. Nylas trial environments are limited to 10 grants and don't include message tracking (analytics) features, but are otherwise the same as paid environments. If you need to test message tracking, contact your Nylas sales representative.
:::
To invite teammates to a Nylas organization...
1. Log in to the [Nylas Dashboard](https://dashboard-v3.nylas.com/?utm_source=docs&utm_content=develop-with-nylas).
2. Expand the **account** dropdown at the top-right of the page.
3. Under **Organization**, select **Add Team Members**.
4. Enter your teammate's email address and choose a role for their account.
5. Click **Send Invite**.
Nylas sends an email containing an invitation link. When your teammate clicks the link, they're prompted to create their own Nylas account. Their account is automatically associated with your organization. If you or a teammate created a Nylas account without clicking an invitation link, [contact Nylas Support](https://support.nylas.com/hc/en-us/requests/new) to add the account to your organization.
## Create a Nylas application for development
Each organization can have multiple Nylas applications registered to it. When you first create your account, Nylas creates a Sandbox application for you to use to test out the services.
:::success
**We strongly recommend you set up separate Nylas applications for your development, staging, and production environments**. Each application has a unique client ID and secret which you use to manage and [authenticate](/docs/v3/auth/) your users' grants.
:::
Your application's client ID, client secret, and API key allow you to manage grants and application settings. You should treat them like any other credentials and [store them securely](/docs/dev-guide/best-practices/#store-secrets-securely).
To create a development application...
1. Expand the application list at the upper-left of the Nylas Dashboard.
2. Click **Create new application**.
3. Give the application a **name**, a brief **description**, and choose the **data residency region** and **environment**.
4. Click **Create application**.
## Plan your project
Your project will use the Nylas APIs to access your users' accounts on their behalf, and webhook notifications to monitor activity that your application needs to know about.
Before you start integrating with Nylas, you should list the activities that you want to do in your project that require access to the service provider, and the results and changes you want to monitor to inform how your application responds. For example, if you're building a calendaring app, you know that you'll need to _read_ a user's calendar so you can pick an available time slot. You also know you want to _write_ to the calendar so you can create events. Perhaps you also want to choose from a list of the user's contacts when inviting people to the event, which requires read access to their contacts list.
But what happens if a participant declines the event invitation? Or if the creator cancels the event from outside your application? You'll want to monitor for these changes using webhook notifications, so your application can respond appropriately.
Once you have a list of objects you want to interact with and get notifications about, you can review the [list of scopes for each provider](/docs/dev-guide/scopes/) and the [webhooks references](/docs/reference/api/webhook-notifications/).
## Choose how to authenticate users
Nylas offers [two ways to authenticate grants](/docs/v3/auth/) based on your project's requirements: [Hosted Authentication](/docs/v3/auth/hosted-oauth-apikey/) and [Custom Authentication](/docs/v3/auth/custom/).
For most projects, we recommend [**Hosted Authentication**](/docs/v3/auth/hosted-oauth-apikey/). When you use Hosted Auth, Nylas automatically detects the email provider the user is authenticating with, passes the user through the auth process with that provider, and returns them to your project. The work required to integrate Hosted Auth is minimal.
If you want to completely hide Nylas' branding and your users' provider details in the auth process, you might want to use [**Custom Authentication**](/docs/v3/auth/custom/). This can require a lot of development work, however.
You might also want to read more about the authentication requirements for individual service providers:
- [Google](/docs/provider-guides/google/)
- [Microsoft](/docs/provider-guides/microsoft/)
- [IMAP providers](/docs/provider-guides/imap/)
- [Microsoft Exchange on-premises](/docs/provider-guides/exchange-on-prem/)
- [iCloud](/docs/provider-guides/icloud/)
- [Yahoo](/docs/provider-guides/yahoo-authentication/)
- [Zoom Meetings](/docs/provider-guides/zoom-meetings/)
If you need to create a provider authentication application (for example, a Google Cloud Platform project), you should start that now.
### Store user access tokens and user data securely
During the authentication process, Nylas passes a user access token to your project. Your project needs this token so it can make requests to the Nylas APIs on the user's behalf. You'll need to store this token in your project, and you might want to cache or store other user data to avoid making unnecessary API calls. This information should be encrypted using a modern algorithm, both in transit and at rest. If at all possible, you should also use a secrets manager from your infrastructure provider.
:::warn
**Failure to follow security best practices might prevent your application from passing provider verification processes**. See our [security best practices](/docs/dev-guide/best-practices/) for more information.
:::
## Create provider auth apps
If you expect to connect to Google or Microsoft accounts, you'll need to create a provider auth app to connect to their servers.
:::info
**You can use provider auth apps with internal company accounts for development and testing with no extra steps**. You'll need to get it reviewed by the provider, however, before you can "go live" with your project. We recommend you maintain a provider auth app for each of your environments so you can make changes in your development and testing environments without affecting your production users.
:::
Creating a provider auth app is straightforward, and you can create one (or several) quickly so you can start developing. The provider review can take several weeks, however, and depends entirely on the provider's review process and which scope your project requests. Be sure to plan this into your development timeline!
### Google application review
You might need to take extra steps to comply with Google's OAuth 2.0 policies and complete their verification process before you can publish your Google auth app.
Be sure you're requesting only the most restrictive [scopes](/docs/dev-guide/scopes/) that you need for your project. If you request any of [Google's restricted scopes](/docs/provider-guides/google/google-verification-security-assessment-guide/#google-scopes), Google requires your application to complete a security assessment. This could extend your verification timeline significantly or cause Google to fail your review.
For more information, see our [Google verification and security assessment guide](/docs/provider-guides/google/google-verification-security-assessment-guide/).
## Start developing with Nylas
After you get your authentication flow set up, authenticate a test grant or two so you can work with the Nylas APIs.
:::success
**Nylas maintains SDKs in [**Node.js**](/docs/v3/sdks/node/), [**Python**](/docs/v3/sdks/python/), [**Ruby**](/docs/v3/sdks/ruby/), and [**Kotlin/Java**](/docs/v3/sdks/kotlin-java/)**. You can use any of them to interact with the Nylas APIs, or use a plain HTTP library instead.
:::
If you already know what you're going to build, or if your project is already mostly finished, you can read through the [Nylas API references](/docs/reference/api/) or our guides for working with the [Email](/docs/v3/email/), [Calendar](/docs/v3/calendar/), and [Contacts](/docs/v3/email/contacts/) APIs.
If you're just starting out and you're not sure where to begin, Nylas maintains a [repository of code samples](https://github.com/nylas-samples/) and a set of [fully functioning demo applications](https://github.com/nylas/use-cases/) you can use for inspiration. You can also use our [Postman collection](/docs/v3/api-references/postman/) to test the Nylas APIs.
## Set up notifications
After you've made a couple calls to the Nylas APIs, you should think about which events you want to know about so your project can respond to them appropriately. If you completed the [planning exercise](#plan-your-project) earlier, that's a great place to start. If you're building as you go, see our [list of notification schemas](/docs/reference/notifications/) for ideas.
Nylas allows you to subscribe to notifications using [webhooks](/docs/v3/notifications/), [Pub/Sub queues](/docs/v3/notifications/pubsub-channel/), or a mix of both. You can use notifications both to run core functionality in your project and to monitor for undesirable events (like errors!) so your application can handle them gracefully.
You should also consider the volume of notifications you're likely to get from your project and plan for scaling them appropriately. See our [best practices for webhooks](/docs/dev-guide/best-practices/webhook-best-practices/) for important tips and considerations to help your setup run smoothly and scale gracefully.
## Set up grant status monitoring
Your users are the life of your project, so it makes sense to keep a close eye on the state of their grants. After you have [authentication set up](#choose-how-to-authenticate-users), make sure you subscribe to the [grant state webhook triggers](/docs/reference/notifications/#grant-notifications) so you can get alerts when users run into problems and take appropriate action. This could be re-authenticating the user, sending them a prompt to re-authenticate or accept updated scopes, using an incremental backoff approach, or other actions specific to your project and use case.
:::success
**If you're authenticating using a Google provider auth app, make sure to [**set up Pub/Sub**](/docs/provider-guides/google/connect-google-pub-sub/)**. This ensures webhook notifications are delivered in a timely manner.
:::
You can also use the timestamps from the grant state webhook notifications to check the user's data for the period their grant was experiencing problems, after the issue is solved.
You can subscribe to these triggers either [from the Nylas Dashboard](/docs/v3/notifications/#create-a-webhook-in-the-nylas-dashboard), [using the webhooks endpoints](/docs/v3/notifications/#create-a-webhook-using-the-webhooks-api), or [using Nylas' SDKs](/docs/v3/notifications/#create-a-webhook-using-the-nylas-sdks).
### User data and authentication lifecycle management
Although Nylas access tokens don't expire, you can assume that you'll need to plan for authentication changes. These may pop up because of user actions or changes to provider policies. For example, if a user explicitly disconnects from or logs out of your application, you should revoke their Nylas access token to minimize the number of active tokens. You should also revoke any unused tokens when a user re-authenticates. See [Managing grants](/docs/dev-guide/best-practices/manage-grants/) for more information.
You should also think about how you want to handle changes in permission scopes (for example, if your project adds new functionality that needs more access). Scope changes require the user to re-authenticate and explicitly confirm that they're granting access to the new scopes.
If you choose to store your users' data in your own database, you need to [store their access tokens securely](#store-user-access-tokens-and-user-data-securely).
## Set up error monitoring and handling
Nylas has robust built-in strategies for handling provider errors and other normal network weather. Despite this, there are situations you should monitor and decide how to handle.
- **Invalid credentials**: When an account's OAuth token expires, is revoked, or their password is changed.
- **API errors**: When your project makes a request to the Nylas APIs and you get a non-`200` HTTP status code response, or a network error.
- **Account sync errors**: Persistent errors that prevent Nylas from getting the latest changes from the provider or writing new updates to the provider.
See [Monitoring and error handling](/docs/dev-guide/best-practices/error-handling/) for a list of common error states and best practices for handling them.
You might also want to [monitor your webhooks for errors](/docs/dev-guide/best-practices/webhook-best-practices/) and implement retry, backoff, and restart logic based on their status.
## Production checklist
Before you go live with your project, be sure that you've...
1. [Set up authentication](/docs/v3/auth/) and created [connectors](/docs/reference/api/connectors-integrations/) for all providers you plan to support.
2. Set up [webhook](/docs/v3/notifications/) or [Pub/Sub](/docs/v3/notifications/pubsub-channel/) notifications and [systems for handling them at scale](/docs/dev-guide/best-practices/webhook-best-practices/).
3. Set up error monitoring and handling for your systems.
4. Reviewed the [scopes](/docs/dev-guide/scopes/) your project is using to ensure you're only requesting those that you need.
5. Started a provider security review for your provider auth apps. See our [Google verification and security assessment guide](/docs/provider-guides/google/google-verification-security-assessment-guide/), [Microsoft verification guide](/docs/provider-guides/microsoft/verification-guide/), and the [general provider guides](/docs/provider-guides/) for more information.
Now it's time to go live and celebrate! 🥳
────────────────────────────────────────────────────────────────────────────────
title: "Nylas glossary"
description: "A handy list of definitions for terms used when working with Nylas."
source: "https://developer.nylas.com/docs/dev-guide/glossary/"
────────────────────────────────────────────────────────────────────────────────
This page lists some terms that you'll encounter when working with Nylas and explains what they mean.
:::success
**Have a suggestion for the glossary**? Let us know!
:::
────────────────────────────────────────────────────────────────────────────────
title: "About Nylas"
description: "Get up and running with Nylas APIs, SDKs, the Nylas CLI, MCP server, AI agent tools, and developer resources."
source: "https://developer.nylas.com/docs/dev-guide/"
────────────────────────────────────────────────────────────────────────────────
Nylas offers a set of REST-style integration APIs and tools that let you quickly add communications functionality to an application you're developing. You can use the Nylas APIs to integrate using any HTTP library that can make REST-style queries. The Nylas APIs accept and return JSON objects on every endpoint, so your interactions with the platform are predictable and straightforward.
Nylas currently supports v3.x of its APIs. For the latest information about new releases and SDK features, see the [changelog](/docs/changelogs/).
:::info
**We consider additive changes to be non-breaking**. Functionally, this means that Nylas can add fields to an API response object without releasing a new API version. Make sure you build your project to handle this possibility.
:::
You can manage your Nylas application using the [Nylas Dashboard](https://dashboard-v3.nylas.com/login), and build your integration using one of the Nylas-maintained SDKs ([Node.js](/docs/v3/sdks/node/), [Python](/docs/v3/sdks/python/), [Ruby](/docs/v3/sdks/ruby/), and [Kotlin/Java](/docs/v3/sdks/kotlin-java/)) or one of the community-maintained SDKs.
## API references
The [API reference](/docs/reference/api/) covers every REST endpoint across Email, Calendar, Contacts, Notetaker, Scheduler, ExtractAI, and administration. Other reference docs cover the rest of the platform:
- [Notification reference](/docs/reference/notifications/) for webhook and Pub/Sub triggers and payloads.
- [UI reference](/docs/reference/ui/) for the Nylas Scheduler UI components and props.
- [Nylas MCP server](/docs/dev-guide/mcp/) for connecting AI agents to email, calendar, and contacts.
- [Nylas CLI](/docs/v3/getting-started/cli/) for managing grants, webhooks, and API calls from the terminal.
You can also try the APIs in the [Nylas Postman collection](https://www.postman.com/trynylas/nylas-api/overview).
For platform-level details, see [error handling](/docs/dev-guide/best-practices/error-handling/) and [rate limits](/docs/dev-guide/best-practices/rate-limits/).
## Build with AI coding agents
If you're using an AI coding agent to build with Nylas, start with one of these:
- **[Nylas skills](/docs/v3/getting-started/ai-prompts/)** pre-load Claude Code, Cursor, Codex CLI, and 40+ other agents with Nylas API, CLI, and SDK context. Install with `npx skills add nylas/skills`.
- **[Claude Code plugin](/docs/v3/getting-started/ai-prompts/#option-1-install-the-nylas-skill-recommended)** installs the Nylas skills through the Claude Code plugin marketplace: `/plugin marketplace add nylas/skills`.
- **[Nylas MCP server](/docs/dev-guide/mcp/)** gives agents live access to email, calendar, and contacts. Works with Claude Code, Cursor, Claude Desktop, and any MCP-compatible client.
- **[AI agent guides](/docs/v3/guides/ai/mcp/claude-code/)** walk through MCP setup for Claude Code, [Codex CLI](/docs/v3/guides/ai/mcp/codex-cli/), and the [OpenClaw Nylas plugin](/docs/v3/guides/ai/openclaw/install-plugin/).
- **[AI coding agent quickstart](/docs/v3/getting-started/coding-agents/)** covers provisioning, SDK setup, and a working example.
The docs are also agent-readable. Any page returns clean markdown if you pass `Accept: text/markdown`, and [`llms.txt`](https://developer.nylas.com/llms.txt) and [`llms-full.txt`](https://developer.nylas.com/llms-full.txt) are published for retrieval.
## Guides and use cases
When you need more than an endpoint reference, look at [guides](/docs/v3/guides/) and [use cases](/docs/v3/use-cases/).
- **[Guides](/docs/v3/guides/)** cover provider-specific tasks. Each one focuses on a single task for a single provider, like [listing Microsoft messages](/docs/v3/guides/email/messages/list-messages-microsoft/) or [handling Gmail labels](/docs/v3/guides/email/messages/list-messages-google/), and calls out the folder naming, sync timing, rate limits, and auth quirks for that provider.
- **[Use cases](/docs/v3/use-cases/)** are end-to-end tutorials that combine multiple Nylas APIs, like [automating meeting follow-ups](/docs/v3/use-cases/act/automate-meeting-follow-ups/), [building an interview scheduling pipeline](/docs/v3/use-cases/build/interview-scheduling-pipeline/), or [syncing calendar events into a CRM](/docs/v3/use-cases/sync/sync-calendar-events-crm/). You can also browse them [by industry](/docs/v3/use-cases/#browse-by-industry).
## Changelogs
The [changelog](/docs/changelogs/) tracks product, SDK, CLI, and API updates. Subscribe to an RSS feed for updates:
- [Combined feed](/atom.xml) for every update.
- [Changelogs only](/atom-changelogs.xml) for SDK, CLI, and API changes.
## Platform status
The [Nylas status page](https://status-v3.nylas.com/) shows current incidents and historical uptime. It publishes an [RSS feed](https://status-v3.nylas.com/history.rss) for incident and maintenance updates.
────────────────────────────────────────────────────────────────────────────────
title: "Nylas MCP server"
description: "Give AI agents access to email, calendar, and contacts through the Model Context Protocol. Connect Claude Code, Cursor, Claude Desktop, and other MCP clients in under 2 minutes."
source: "https://developer.nylas.com/docs/dev-guide/mcp/"
────────────────────────────────────────────────────────────────────────────────
The Nylas MCP server gives AI agents typed tools for email, calendar, and contacts -- no SDK integration or API calls required. Your agent asks to "list my emails" or "create an event," and the MCP server handles the Nylas API calls.
Works with any [MCP-compatible client](https://modelcontextprotocol.io/): Claude Code, Claude Desktop, Cursor, Windsurf, VS Code, OpenAI Codex CLI, and more.
## Before you begin
You need a Nylas API key and a connected account (grant). If you haven't set these up yet:
- **[Get started with the CLI](/docs/v3/getting-started/cli/)** -- run `nylas init` to create an account, generate an API key, and connect a test account in one command.
- **[Get started with the Dashboard](/docs/v3/getting-started/dashboard/)** -- do the same steps through the web UI.
## Quickstart: Nylas CLI (fastest)
If you have the [Nylas CLI](https://cli.nylas.com) installed, one command registers the MCP server with your agent:
```bash [mcpInstall-Claude Code]
nylas mcp install --assistant claude-code
```
```bash [mcpInstall-Cursor]
nylas mcp install --assistant cursor
```
```bash [mcpInstall-Windsurf]
nylas mcp install --assistant windsurf
```
```bash [mcpInstall-VS Code]
nylas mcp install --assistant vscode
```
```bash [mcpInstall-Codex CLI]
nylas mcp install --assistant codex
```
```bash [mcpInstall-All agents]
nylas mcp install --all
```
Verify it's running:
```bash
nylas mcp status
```
That's it. Your agent now has access to 16 email, calendar, and contacts tools. Skip to [available tools](#available-tools) to see what's included.
## Manual setup
If you're not using the CLI, add the Nylas MCP server config to your tool's config file. Replace `` with your actual key.
```json [manualSetup-Claude Desktop]
// ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)
// %APPDATA%\Claude\claude_desktop_config.json (Windows)
{
"mcpServers": {
"Nylas": {
"command": "npx",
"args": [
"mcp-remote",
"https://mcp.us.nylas.com",
"--transport",
"http-first",
"--header",
"Authorization: Bearer "
]
}
}
}
```
```json [manualSetup-Cursor]
// ~/.cursor/mcp.json (macOS/Linux)
// %APPDATA%\Cursor\mcp.json (Windows)
{
"mcpServers": {
"nylas": {
"type": "streamable-http",
"url": "https://mcp.us.nylas.com",
"headers": {
"Authorization": "Bearer "
}
}
}
}
```
```toml [manualSetup-Codex CLI]
# ~/.codex/config.toml (global) or .codex/config.toml (project)
# Set NYLAS_API_KEY in your environment -- don't put the key directly in this file
[mcp_servers.nylas]
url = "https://mcp.us.nylas.com"
bearer_token_env_var = "NYLAS_API_KEY"
```
After saving, restart your tool. Verify the connection:
- **Claude Desktop:** Check **Settings > Developer > Local MCP servers** -- Nylas should show as "running."
- **Cursor:** Check **Settings > Tools & MCP** -- look for a green dot next to the Nylas server.
## MCP server URLs
The MCP server URL depends on where your Nylas application stores data. Use the URL that matches your application's [data residency region](/docs/dev-guide/platform/data-residency/).
| Region | URL |
|--------|-----|
| US (default) | `https://mcp.us.nylas.com` |
| EU | `https://mcp.eu.nylas.com` |
Authentication uses a Bearer token with your Nylas API key in the `Authorization` header -- the same key you use for direct API calls.
## Available tools
The MCP server exposes these tools to your agent:
| Tool | What it does |
|------|-------------|
| `list_messages` | List and search email messages |
| `list_threads` | List and search email threads |
| `create_draft` | Create a draft email |
| `update_draft` | Edit an existing draft |
| `confirm_send_draft` | Required before sending a draft (safety confirmation) |
| `send_draft` | Send a previously created draft |
| `confirm_send_message` | Required before sending a message (safety confirmation) |
| `send_message` | Send an email directly |
| `get_folder_by_id` | Get folder details |
| `list_calendars` | List all calendars |
| `list_events` | List events in a calendar |
| `create_event` | Create a calendar event |
| `update_event` | Update an existing event |
| `availability` | Check availability across users |
| `get_grant` | Look up a grant by email address |
| `current_time` | Get current Unix timestamp |
| `epoch_to_datetime` | Convert Unix timestamp to human-readable date |
:::info
**Send confirmation is required.** The `send_message` and `send_draft` tools require a preceding call to `confirm_send_message` or `confirm_send_draft`. This two-step process prevents your agent from sending emails without explicit confirmation.
:::
## Security
:::warn
**Prompt injection is a real risk.** Malicious content in emails, documents, or calendar events can contain hidden instructions that attempt to trick your agent into sending emails, exposing credentials, or performing unauthorized actions.
You are responsible for implementing safeguards:
- Always require explicit user confirmation before sending emails
- Never expose API keys or credentials in agent responses
- Validate and sanitize content before processing
- Monitor and log all MCP tool calls
:::
:::info
**Data isolation.** The MCP server uses the same auth as the Nylas API -- your API key and grant IDs. Configure your agent's system prompt to ensure each user's data is only accessed through their own grant.
:::
## Timeouts and reconnection
The MCP server enforces a 90-second timeout per request. Connections are stateless -- each request is independent. Your client should handle timeouts gracefully and retry as needed.
## What's next
- **[Give your agent email access](/docs/v3/getting-started/agent-email/)** -- CLI commands for email operations
- **[Give your agent calendar access](/docs/v3/getting-started/agent-calendar/)** -- CLI commands for calendar operations
- **[Authentication](/docs/v3/auth/)** -- how grants and OAuth work
- **[API reference](/docs/reference/api/)** -- full endpoint documentation
- **[CLI guides](https://cli.nylas.com/guides/ai-agent-email-mcp)** -- detailed MCP setup guide on cli.nylas.com
────────────────────────────────────────────────────────────────────────────────
title: "Using metadata in Nylas"
description: "Use metadata to attach key-value data to objects."
source: "https://developer.nylas.com/docs/dev-guide/metadata/"
────────────────────────────────────────────────────────────────────────────────
Nylas lets you add key-value pairs to certain objects so you can store data against them.
## What is metadata?
You can use the `metadata` object to add a list of custom key-value pairs to [Calendars](/docs/reference/api/calendar/), [Events](/docs/reference/api/events/), [Messages](/docs/reference/api/messages/), and [Drafts](/docs/reference/api/drafts/). Both keys and values can be any string, and you can store up to 50 key-value pairs on an object. Keys can be up to 40 characters long, and values can be up to 500 characters.
Nylas doesn't support nested `metadata` objects, and doesn't generate [notifications](/docs/v3/notifications/) when you update the `metadata` object.
### Reserved metadata keys
Nylas reserves five metadata keys (`key1`, `key2`, `key3`, `key4`, and `key5`) and indexes their contents. Nylas uses `key5` to identify events that count towards the [`max-fairness` round-robin calculation for event availability](/docs/v3/calendar/group-booking/#round-robin-max-fairness-groups).
You can add values to each of these reserved keys and reference them in a query to filter the objects that Nylas returns, as in the following examples:
- `https://api.us.nylas.com/calendar?metadata_pair=key1:on-site`
- `https://api.us.nylas.com/events?calendar_id=&metadata_pair=key1:on-site`
:::warn
**You can't create a query that includes both a provider and metadata filter, other than `calendar_id`**. For example, `https://api.us.nylas.com/calendar?metadata_pair=key1:plan-party&title=Birthday` returns an error.
:::
## Add metadata to objects
You can add metadata to both new and existing objects. The following example adds the `"event-type": "meeting"` key-value pair to an existing Calendar.
```bash
curl --request POST \
--url 'https://api.us.nylas.com/v3/grants/me/calendars' \
--header 'Content-Type: application/json' \
--data '{
"name" : "Example metadata calendar",
"metadata": {
"key1": "all-meetings",
"key2": "on-site"
}
}'
```
:::warn
**Both `PUT` and `PATCH` requests overwrite the entire `metadata` object**. This means that if you update the calendar in the example above but include only `key1`, Nylas deletes `key2`.
:::
## Remove metadata from objects
To remove a key-value pair from an object, make a `PUT` or `PATCH` request that includes the metadata you want to keep. As an example, consider the following `metadata` on an existing Calendar:
```json
...
"metadata": {
"key1": "all-meetings",
"key2": "on-site"
},
...
```
If you make the following [`PUT /v3/grants//calendars/` request](/docs/reference/api/calendar/put-calendars-id/), Nylas deletes `key1` and keeps `key2`.
```bash
curl --request PUT \
--url 'https://api.us.nylas.com/v3/grants/me/calendars/' \
--data '{
"metadata": {
"key2": "on-site"
}
}'
```
## Query metadata on objects
:::warn
**You can only query for the [**Nylas-specific metadata keys**](#reserved-metadata-keys)**.
:::
You can query for specific metadata by including the `metadata` object in your request, or by using the metadata query parameters. Nylas doesn't guarantee that metadata attached to an object will be returned in a specific order, so be sure to build your parsing methods with an arbitrary order in mind.
## Metadata in webhooks
If an object has metadata, Nylas includes the `metadata` property in `*.created` and `*.updated` [webhook notifications](/docs/v3/notifications/), similar to the following example.
```json {21-24}
{
"specversion": "1.0",
"type": "event.updated",
"source": "/google/events/realtime",
"id": "",
"time": 1732575192,
"webhook_delivery_attempt": 1,
"data": {
"application_id": "",
"object": {
"busy": true,
"calendar_id": "",
"created_at": 1732573232,
"description": "Weekly one-on-one.",
"grant_id": "",
"hide_participants": false,
"html_link": "",
"ical_uid": "",
"id": "",
"location": "Room 103",
"metadata": {
"key1": "all-meetings",
"key2": "on-site"
},
"object": "event",
"organizer": {
"email": "nyla@example.com",
"name": "Nyla"
},
"participants": [
{
"email": "leyah@example.com",
"name": "Leyah Miller",
"status": "noreply"
}
],
"read_only": false,
"reminders": {
"use_default": true
},
"status": "confirmed",
"title": "One-on-one",
"updated_at": 1732575179,
"visibility": "public",
"when": {
"end_time": 1732811400,
"end_timezone": "EST5EDT",
"object": "timespan",
"start_time": 1732809600,
"start_timezone": "EST5EDT"
}
}
}
}
```
## Metadata for recurring events
Recurring events are comprised of a primary ("main") event, with child events or the recurrence attached. When working with metadata on recurring events, keep the following things in mind:
- You can add metadata to the primary event and child event.
- Metadata added to the primary event is passed to the child events.
- Metadata updates made to a child event are applied only to that specific child event and are not propagated to the primary or other instances in the series.
- If you change an event from non-recurring to recurring, any metadata from the non-recurring event is lost.
For more information about recurring events, see the [Schedule recurring events documentation](/docs/v3/calendar/recurring-events/).
────────────────────────────────────────────────────────────────────────────────
title: "Nylas data residency"
description: "Nylas' data residency options and information about how they allow you to comply with regulations relating to personally identifiable information (PII)."
source: "https://developer.nylas.com/docs/dev-guide/platform/data-residency/"
────────────────────────────────────────────────────────────────────────────────
Nylas' data residency offerings enable you to comply with legal requirements related to storing personally identifiable information (PII) in different regions around the world. As your data sub-processor, Nylas provides the tools and controls necessary to manage and configure where your users' data is stored. Nylas offers data storage in two regions: the U.S. and Europe.
Each region is completely isolated, and data can't pass between them. You need to create different applications in different regions, but with the same Nylas Organization. Your Nylas application must also be aware of which region a user belongs to so it can query the appropriate APIs.
## Data residency regions
| Region | Dashboard URL | API URL | Tracking URL |
| ---------------- | -------------------------------- | -------------------------- | ------------------------------- |
| U.S. (Oregon) | `https://dashboard-v3.nylas.com` | `https://api.us.nylas.com` | `https://tracking.us.nylas.com` |
| Europe (Ireland) | `https://dashboard-v3.nylas.com` | `https://api.eu.nylas.com` | `https://tracking.eu.nylas.com` |
All information about your Nylas organization and Dashboard users is stored in the European data center. When users in the U.S. access the Nylas Dashboard, their authorization is processed through the server in Ireland.
Your application data, connector data, and grant information is stored in the data center associated with your Nylas application.
## Get started with a new region
The steps to set up data residency with Nylas are the same for all regions:
1. Log in to the [Nylas Dashboard](https://dashboard-v3.nylas.com) and click **Create new app**.
2. Give the application a **name**, a brief **description**, and choose the **data residency region** and **environment**.
3. Click **Create app**.
## Configure base API URL in Nylas SDKs
The Nylas SDKs support changing the base API URL. Be sure to use the appropriate URL for your Nylas application's region.
```js [baseUrl-Node.js]
const NylasConfig = {
apiKey: "",
apiUri: "",
};
const nylas = new Nylas(NylasConfig);
```
```py [baseUrl-Python]
from nylas import Client
nylas = Client(
os.environ.get('NYLAS_API_KEY'),
os.environ.get('NYLAS_API_URI')
)
```
```rb [baseUrl-Ruby]
#!/usr/bin/env ruby
require 'nylas'
nylas = Nylas::Client.new(
api_key: "",
api_uri: ""
)
```
## Change data residency region
You need to take a few steps to migrate your existing Nylas application to a new region:
1. Log in to the [Nylas Dashboard](https://dashboard-v3.nylas.com) and create an application in your desired region.
2. [Set up your authentication flow](/docs/dev-guide/develop-with-nylas/#choose-how-to-authenticate-users).
3. Migrate grants to your new application. You can migrate the grants immediately, or migrate new grants first.
- **Migrate grants immediately**: Migrate all your grants within the same month that you set up the new Nylas application, then contact Nylas' Billing team to adjust your bill.
- **Migrate new grants first**: Have new users authenticate with your new Nylas application, then migrate existing grants using a targeted approach. This strategy helps to mitigate extra work when setting up new users' grants.
4. Have your existing users re-authenticate with your new Nylas application.
5. Make [`DELETE /v3/grants/` requests](/docs/reference/api/manage-grants/delete_grant_by_id/) to delete duplicate grants from your old Nylas application.
### Manage migrated data
When you migrate your users to your new Nylas application, their grants are considered to be new connections. Because of this, Nylas needs to fetch all of their data again. Nylas also creates new IDs for every object it fetches. To connect the data, you can merge the information from your old Nylas application with the objects in your new application using their unique Calendar and Message object IDs.
:::info
**Grant and object IDs are unique to each Nylas application**. Be sure to update IDs that your project directly references after you migrate your data.
:::
You'll also need to update your webhook and SDK configurations for your project's new data residency settings.
────────────────────────────────────────────────────────────────────────────────
title: "Reducing response sizes with field selection"
description: "Use field selection to control the fields Nylas returns in API responses and webhook notifications."
source: "https://developer.nylas.com/docs/dev-guide/platform/field-selection/"
────────────────────────────────────────────────────────────────────────────────
Nylas supports field selection, which allows you to choose which fields are returned in API responses and [notifications](/docs/v3/notifications/). Instead of sending all available fields, Nylas sends only the data you specify. This helps protect sensitive information, improves performance, and prevents timeouts and [rate limiting](/docs/dev-guide/platform/rate-limits/).
You can implement field selection at any of the following levels:
- **Application level for API responses**: Applies to all responses to [Messages](/docs/reference/api/messages/) or [Events](/docs/reference/api/events/) requests.
- **Application level for webhook notifications**: Applies to all [Message](/docs/reference/notifications/#message-notifications) or [Event](/docs/reference/notifications/#event-notifications) webhook notifications.
- **Request level**: Applies to the request in which you define the [`select` query parameter](#reduce-response-size-with-field-selection).
If you use both application-level and request-level field selection for a request, Nylas returns the _intersection_ of your selections. This means you receive only the fields specified at both the application and request level.
## Enable application-level field selection for responses
:::hint
**[**Contact the Nylas Sales team**](https://www.nylas.com/contact-sales/?utm_source=docs&utm_content=field-selection) to enable field selection for your application**. After we configure your settings, Nylas starts returning only the specified fields for the affected endpoints.
:::
## Enable application-level field selection for webhooks
1. Log in to the [Nylas Dashboard](https://dashboard-v3.nylas.com/?utm_source=docs&utm_content=field-selection).
2. Select **Customizations** in the left navigation.
3. Toggle either **Email message field selection for notifications** or **Calendar event field selection for notifications** on.
4. Select the fields you want to include in Nylas' responses.
5. **Save** your changes.
After you save your field selection settings, Nylas starts sending `*.transformed` notifications for the affected trigger types. For more information, see [Using webhooks with Nylas](/docs/v3/notifications/?redirect=reorg#specify-fields-for-webhook-notifications).
## Enable request-level field selection
You can specify the fields you want Nylas to return for individual API requests by including the [`select` query parameter](#reduce-response-size-with-field-selection).
```bash {2} [filter-Get all Messages request]
curl --request GET \
--url "https://api.us.nylas.com/v3/grants//messages?limit=5&select=id,subject,from,to" \
--header 'Accept: application/json' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json'
```
```bash {2} [filter-Get all Events request]
curl --request GET \
--url 'https://api.us.nylas.com/v3/grants//events?calendar_id=&select=id,title,when,location' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json'
```
────────────────────────────────────────────────────────────────────────────────
title: "Supported attachment media types"
description: "The file types you can attach to messages using the Nylas Email API."
source: "https://developer.nylas.com/docs/dev-guide/platform/file-attachment-media-types/"
────────────────────────────────────────────────────────────────────────────────
Nylas returns a `content_type` that makes it easy to detect the file type attached to a message. Below is a list of common file types you might encounter:
- .3dm x-world/x-3dmf
- .3dmf x-world/x-3dmf
- .a application/octet-stream
- .aab application/x-authorware-bin
- .aam application/x-authorware-map
- .aas application/x-authorware-seg
- .abc text/vnd.abc
- .acgi text/html
- .afl video/animaflex
- .ai application/postscript
- .aif audio/aiff
- .aif audio/x-aiff
- .aifc audio/aiff
- .aifc audio/x-aiff
- .aiff audio/aiff
- .aiff audio/x-aiff
- .aim application/x-aim
- .aip text/x-audiosoft-intra
- .ani application/x-navi-animation
- .aos application/x-nokia-9000-communicator-add-on-software
- .aps application/mime
- .arc application/octet-stream
- .arj application/arj
- .arj application/octet-stream
- .art image/x-jg
- .asf video/x-ms-asf
- .asm text/x-asm
- .asp text/asp
- .asx application/x-mplayer2
- .asx video/x-ms-asf
- .asx video/x-ms-asf-plugin
- .au audio/basic
- .au audio/x-au
- .avi application/x-troff-msvideo
- .avi video/avi
- .avi video/msvideo
- .avi video/x-msvideo
- .avs video/avs-video
- .bcpio application/x-bcpio
- .bin application/mac-binary
- .bin application/macbinary
- .bin application/octet-stream
- .bin application/x-binary
- .bin application/x-macbinary
- .bm image/bmp
- .bmp image/bmp
- .bmp image/x-windows-bmp
- .boo application/book
- .book application/book
- .boz application/x-bzip2
- .bsh application/x-bsh
- .bz application/x-bzip
- .bz2 application/x-bzip2
- .c text/plain
- .c text/x-c
- .c++ text/plain
- .cat application/vnd.ms-pki.seccat
- .cc text/plain
- .cc text/x-c
- .ccad application/clariscad
- .cco application/x-cocoa
- .cdf application/cdf
- .cdf application/x-cdf
- .cdf application/x-netcdf
- .cer application/pkix-cert
- .cer application/x-x509-ca-cert
- .cha application/x-chat
- .chat application/x-chat
- .class application/java
- .class application/java-byte-code
- .class application/x-java-class
- .com application/octet-stream
- .com text/plain
- .conf text/plain
- .cpio application/x-cpio
- .cpp text/x-c
- .cpt application/mac-compactpro
- .cpt application/x-compactpro
- .cpt application/x-cpt
- .crl application/pkcs-crl
- .crl application/pkix-crl
- .crt application/pkix-cert
- .crt application/x-x509-ca-cert
- .crt application/x-x509-user-cert
- .csh application/x-csh
- .csh text/x-script.csh
- .css application/x-pointplus
- .css text/css
- .cxx text/plain
- .dcr application/x-director
- .deepv application/x-deepv
- .def text/plain
- .der application/x-x509-ca-cert
- .dif video/x-dv
- .dir application/x-director
- .dl video/dl
- .dl video/x-dl
- .doc application/msword
- .dot application/msword
- .dp application/commonground
- .drw application/drafting
- .dump application/octet-stream
- .dv video/x-dv
- .dvi application/x-dvi
- .dwf drawing/x-dwf (old)
- .dwf model/vnd.dwf
- .dwg application/acad
- .dwg image/vnd.dwg
- .dwg image/x-dwg
- .dxf application/dxf
- .dxf image/vnd.dwg
- .dxf image/x-dwg
- .dxr application/x-director
- .el text/x-script.elisp
- .elc application/x-bytecode.elisp (compiled elisp)
- .elc application/x-elc
- .env application/x-envoy
- .eps application/postscript
- .es application/x-esrehber
- .etx text/x-setext
- .evy application/envoy
- .evy application/x-envoy
- .exe application/octet-stream
- .f text/plain
- .f text/x-fortran
- .f77 text/x-fortran
- .f90 text/plain
- .f90 text/x-fortran
- .fdf application/vnd.fdf
- .fif application/fractals
- .fif image/fif
- .fli video/fli
- .fli video/x-fli
- .flo image/florian
- .flx text/vnd.fmi.flexstor
- .fmf video/x-atomic3d-feature
- .for text/plain
- .for text/x-fortran
- .fpx image/vnd.fpx
- .fpx image/vnd.net-fpx
- .frl application/freeloader
- .funk audio/make
- .g text/plain
- .g3 image/g3fax
- .gif image/gif
- .gl video/gl
- .gl video/x-gl
- .gsd audio/x-gsm
- .gsm audio/x-gsm
- .gsp application/x-gsp
- .gss application/x-gss
- .gtar application/x-gtar
- .gz application/x-compressed
- .gz application/x-gzip
- .gzip application/x-gzip
- .gzip multipart/x-gzip
- .h text/plain
- .h text/x-h
- .hdf application/x-hdf
- .help application/x-helpfile
- .hgl application/vnd.hp-hpgl
- .hh text/plain
- .hh text/x-h
- .hlb text/x-script
- .hlp application/hlp
- .hlp application/x-helpfile
- .hlp application/x-winhelp
- .hpg application/vnd.hp-hpgl
- .hpgl application/vnd.hp-hpgl
- .hqx application/binhex
- .hqx application/binhex4
- .hqx application/mac-binhex
- .hqx application/mac-binhex40
- .hqx application/x-binhex40
- .hqx application/x-mac-binhex40
- .hta application/hta
- .htc text/x-component
- .htm text/html
- .html text/html
- .htmls text/html
- .htt text/webviewhtml
- .htx text/html
- .ice x-conference/x-cooltalk
- .ico image/x-icon
- .idc text/plain
- .ief image/ief
- .iefs image/ief
- .iges application/iges
- .iges model/iges
- .igs application/iges
- .igs model/iges
- .ima application/x-ima
- .imap application/x-httpd-imap
- .inf application/inf
- .ins application/x-internett-signup
- .ip application/x-ip2
- .isu video/x-isvideo
- .it audio/it
- .iv application/x-inventor
- .ivr i-world/i-vrml
- .ivy application/x-livescreen
- .jam audio/x-jam
- .jav text/plain
- .jav text/x-java-source
- .java text/plain
- .java text/x-java-source
- .jcm application/x-java-commerce
- .jfif image/jpeg
- .jfif image/pjpeg
- .jfif-tbnl image/jpeg
- .jpe image/jpeg
- .jpe image/pjpeg
- .jpeg image/jpeg
- .jpeg image/pjpeg
- .jpg image/jpeg
- .jpg image/pjpeg
- .jps image/x-jps
- .js application/x-javascript
- .js application/javascript
- .js application/ecmascript
- .js text/javascript
- .js text/ecmascript
- .jut image/jutvision
- .kar audio/midi
- .kar music/x-karaoke
- .ksh application/x-ksh
- .ksh text/x-script.ksh
- .la audio/nspaudio
- .la audio/x-nspaudio
- .lam audio/x-liveaudio
- .latex application/x-latex
- .lha application/lha
- .lha application/octet-stream
- .lha application/x-lha
- .lhx application/octet-stream
- .list text/plain
- .lma audio/nspaudio
- .lma audio/x-nspaudio
- .log text/plain
- .lsp application/x-lisp
- .lsp text/x-script.lisp
- .lst text/plain
- .lsx text/x-la-asf
- .ltx application/x-latex
- .lzh application/octet-stream
- .lzh application/x-lzh
- .lzx application/lzx
- .lzx application/octet-stream
- .lzx application/x-lzx
- .m text/plain
- .m text/x-m
- .m1v video/mpeg
- .m2a audio/mpeg
- .m2v video/mpeg
- .m3u audio/x-mpequrl
- .man application/x-troff-man
- .map application/x-navimap
- .mar text/plain
- .mbd application/mbedlet
- .mc$ application/x-magic-cap-package-1.0
- .mcd application/mcad
- .mcd application/x-mathcad
- .mcf image/vasa
- .mcf text/mcf
- .mcp application/netmc
- .me application/x-troff-me
- .mht message/rfc822
- .mid application/x-midi
- .mid audio/midi
- .mid audio/x-mid
- .mid audio/x-midi
- .mid music/crescendo
- .mid x-music/x-midi
- .midi application/x-midi
- .midi audio/midi
- .midi audio/x-mid
- .midi audio/x-midi
- .midi music/crescendo
- .midi x-music/x-midi
- .mif application/x-frame
- .mif application/x-mif
- .mime message/rfc822
- .mime www/mime
- .mjf audio/x-vnd.audioexplosion.mjuicemediafile
- .mjpg video/x-motion-jpeg
- .mm application/base64
- .mm application/x-meme
- .mme application/base64
- .mod audio/mod
- .mod audio/x-mod
- .moov video/quicktime
- .mov video/quicktime
- .movie video/x-sgi-movie
- .mp2 audio/mpeg
- .mp2 audio/x-mpeg
- .mp2 video/mpeg
- .mp2 video/x-mpeg
- .mp2 video/x-mpeq2a
- .mp3 audio/mpeg3
- .mp3 audio/x-mpeg-3
- .mp3 video/mpeg
- .mp3 video/x-mpeg
- .mpa audio/mpeg
- .mpa video/mpeg
- .mpc application/x-project
- .mpe video/mpeg
- .mpeg video/mpeg
- .mpg audio/mpeg
- .mpg video/mpeg
- .mpga audio/mpeg
- .mpp application/vnd.ms-project
- .mpt application/x-project
- .mpv application/x-project
- .mpx application/x-project
- .mrc application/marc
- .ms application/x-troff-ms
- .mv video/x-sgi-movie
- .my audio/make
- .mzz application/x-vnd.audioexplosion.mzz
- .nap image/naplps
- .naplps image/naplps
- .nc application/x-netcdf
- .ncm application/vnd.nokia.configuration-message
- .nif image/x-niff
- .niff image/x-niff
- .nix application/x-mix-transfer
- .nsc application/x-conference
- .nvd application/x-navidoc
- .o application/octet-stream
- .oda application/oda
- .omc application/x-omc
- .omcd application/x-omcdatamaker
- .omcr application/x-omcregerator
- .p text/x-pascal
- .p10 application/pkcs10
- .p10 application/x-pkcs10
- .p12 application/pkcs-12
- .p12 application/x-pkcs12
- .p7a application/x-pkcs7-signature
- .p7c application/pkcs7-mime
- .p7c application/x-pkcs7-mime
- .p7m application/pkcs7-mime
- .p7m application/x-pkcs7-mime
- .p7r application/x-pkcs7-certreqresp
- .p7s application/pkcs7-signature
- .part application/pro_eng
- .pas text/pascal
- .pbm image/x-portable-bitmap
- .pcl application/vnd.hp-pcl
- .pcl application/x-pcl
- .pct image/x-pict
- .pcx image/x-pcx
- .pdb chemical/x-pdb
- .pdf application/pdf
- .pfunk audio/make
- .pfunk audio/make.my.funk
- .pgm image/x-portable-graymap
- .pgm image/x-portable-greymap
- .pic image/pict
- .pict image/pict
- .pkg application/x-newton-compatible-pkg
- .pko application/vnd.ms-pki.pko
- .pl text/plain
- .pl text/x-script.perl
- .plx application/x-pixclscript
- .pm image/x-xpixmap
- .pm text/x-script.perl-module
- .pm4 application/x-pagemaker
- .pm5 application/x-pagemaker
- .png image/png
- .pnm application/x-portable-anymap
- .pnm image/x-portable-anymap
- .pot application/mspowerpoint
- .pot application/vnd.ms-powerpoint
- .pov model/x-pov
- .ppa application/vnd.ms-powerpoint
- .ppm image/x-portable-pixmap
- .pps application/mspowerpoint
- .pps application/vnd.ms-powerpoint
- .ppt application/mspowerpoint
- .ppt application/powerpoint
- .ppt application/vnd.ms-powerpoint
- .ppt application/x-mspowerpoint
- .ppz application/mspowerpoint
- .pre application/x-freelance
- .prt application/pro_eng
- .ps application/postscript
- .psd application/octet-stream
- .pvu paleovu/x-pv
- .pwz application/vnd.ms-powerpoint
- .py text/x-script.phyton
- .pyc application/x-bytecode.python
- .qcp audio/vnd.qcelp
- .qd3 x-world/x-3dmf
- .qd3d x-world/x-3dmf
- .qif image/x-quicktime
- .qt video/quicktime
- .qtc video/x-qtc
- .qti image/x-quicktime
- .qtif image/x-quicktime
- .ra audio/x-pn-realaudio
- .ra audio/x-pn-realaudio-plugin
- .ra audio/x-realaudio
- .ram audio/x-pn-realaudio
- .ras application/x-cmu-raster
- .ras image/cmu-raster
- .ras image/x-cmu-raster
- .rast image/cmu-raster
- .rexx text/x-script.rexx
- .rf image/vnd.rn-realflash
- .rgb image/x-rgb
- .rm application/vnd.rn-realmedia
- .rm audio/x-pn-realaudio
- .rmi audio/mid
- .rmm audio/x-pn-realaudio
- .rmp audio/x-pn-realaudio
- .rmp audio/x-pn-realaudio-plugin
- .rng application/ringing-tones
- .rng application/vnd.nokia.ringing-tone
- .rnx application/vnd.rn-realplayer
- .roff application/x-troff
- .rp image/vnd.rn-realpix
- .rpm audio/x-pn-realaudio-plugin
- .rt text/richtext
- .rt text/vnd.rn-realtext
- .rtf application/rtf
- .rtf application/x-rtf
- .rtf text/richtext
- .rtx application/rtf
- .rtx text/richtext
- .rv video/vnd.rn-realvideo
- .s text/x-asm
- .s3m audio/s3m
- .saveme application/octet-stream
- .sbk application/x-tbook
- .scm application/x-lotusscreencam
- .scm text/x-script.guile
- .scm text/x-script.scheme
- .scm video/x-scm
- .sdml text/plain
- .sdp application/sdp
- .sdp application/x-sdp
- .sdr application/sounder
- .sea application/sea
- .sea application/x-sea
- .set application/set
- .sgm text/sgml
- .sgm text/x-sgml
- .sgml text/sgml
- .sgml text/x-sgml
- .sh application/x-bsh
- .sh application/x-sh
- .sh application/x-shar
- .sh text/x-script.sh
- .shar application/x-bsh
- .shar application/x-shar
- .shtml text/html
- .shtml text/x-server-parsed-html
- .sid audio/x-psid
- .sit application/x-sit
- .sit application/x-stuffit
- .skd application/x-koan
- .skm application/x-koan
- .skp application/x-koan
- .skt application/x-koan
- .sl application/x-seelogo
- .smi application/smil
- .smil application/smil
- .snd audio/basic
- .snd audio/x-adpcm
- .sol application/solids
- .spc application/x-pkcs7-certificates
- .spc text/x-speech
- .spl application/futuresplash
- .spr application/x-sprite
- .sprite application/x-sprite
- .src application/x-wais-source
- .ssi text/x-server-parsed-html
- .ssm application/streamingmedia
- .sst application/vnd.ms-pki.certstore
- .step application/step
- .stl application/sla
- .stl application/vnd.ms-pki.stl
- .stl application/x-navistyle
- .stp application/step
- .sv4cpio application/x-sv4cpio
- .sv4crc application/x-sv4crc
- .svf image/vnd.dwg
- .svf image/x-dwg
- .svr application/x-world
- .svr x-world/x-svr
- .swf application/x-shockwave-flash
- .t application/x-troff
- .talk text/x-speech
- .tar application/x-tar
- .tbk application/toolbook
- .tbk application/x-tbook
- .tcl application/x-tcl
- .tcl text/x-script.tcl
- .tcsh text/x-script.tcsh
- .tex application/x-tex
- .texi application/x-texinfo
- .texinfo application/x-texinfo
- .text application/plain
- .text text/plain
- .tgz application/gnutar
- .tgz application/x-compressed
- .tif image/tiff
- .tif image/x-tiff
- .tiff image/tiff
- .tiff image/x-tiff
- .tr application/x-troff
- .tsi audio/tsp-audio
- .tsp application/dsptype
- .tsp audio/tsplayer
- .tsv text/tab-separated-values
- .turbot image/florian
- .txt text/plain
- .uil text/x-uil
- .uni text/uri-list
- .unis text/uri-list
- .unv application/i-deas
- .uri text/uri-list
- .uris text/uri-list
- .ustar application/x-ustar
- .ustar multipart/x-ustar
- .uu application/octet-stream
- .uu text/x-uuencode
- .uue text/x-uuencode
- .vcd application/x-cdlink
- .vcs text/x-vcalendar
- .vda application/vda
- .vdo video/vdo
- .vew application/groupwise
- .viv video/vivo
- .viv video/vnd.vivo
- .vivo video/vivo
- .vivo video/vnd.vivo
- .vmd application/vocaltec-media-desc
- .vmf application/vocaltec-media-file
- .voc audio/voc
- .voc audio/x-voc
- .vos video/vosaic
- .vox audio/voxware
- .vqe audio/x-twinvq-plugin
- .vqf audio/x-twinvq
- .vql audio/x-twinvq-plugin
- .vrml application/x-vrml
- .vrml model/vrml
- .vrml x-world/x-vrml
- .vrt x-world/x-vrt
- .vsd application/x-visio
- .vst application/x-visio
- .vsw application/x-visio
- .w60 application/wordperfect6.0
- .w61 application/wordperfect6.1
- .w6w application/msword
- .wav audio/wav
- .wav audio/x-wav
- .wb1 application/x-qpro
- .wbmp image/vnd.wap.wbmp
- .web application/vnd.xara
- .wiz application/msword
- .wk1 application/x-123
- .wmf windows/metafile
- .wml text/vnd.wap.wml
- .wmlc application/vnd.wap.wmlc
- .wmls text/vnd.wap.wmlscript
- .wmlsc application/vnd.wap.wmlscriptc
- .word application/msword
- .wp application/wordperfect
- .wp5 application/wordperfect
- .wp5 application/wordperfect6.0
- .wp6 application/wordperfect
- .wpd application/wordperfect
- .wpd application/x-wpwin
- .wq1 application/x-lotus
- .wri application/mswrite
- .wri application/x-wri
- .wrl application/x-world
- .wrl model/vrml
- .wrl x-world/x-vrml
- .wrz model/vrml
- .wrz x-world/x-vrml
- .wsc text/scriplet
- .wsrc application/x-wais-source
- .wtk application/x-wintalk
- .xbm image/x-xbitmap
- .xbm image/x-xbm
- .xbm image/xbm
- .xdr video/x-amt-demorun
- .xgz xgl/drawing
- .xif image/vnd.xiff
- .xl application/excel
- .xla application/excel
- .xla application/x-excel
- .xla application/x-msexcel
- .xlb application/excel
- .xlb application/vnd.ms-excel
- .xlb application/x-excel
- .xlc application/excel
- .xlc application/vnd.ms-excel
- .xlc application/x-excel
- .xld application/excel
- .xld application/x-excel
- .xlk application/excel
- .xlk application/x-excel
- .xll application/excel
- .xll application/vnd.ms-excel
- .xll application/x-excel
- .xlm application/excel
- .xlm application/vnd.ms-excel
- .xlm application/x-excel
- .xls application/excel
- .xls application/vnd.ms-excel
- .xls application/x-excel
- .xls application/x-msexcel
- .xlt application/excel
- .xlt application/x-excel
- .xlv application/excel
- .xlv application/x-excel
- .xlw application/excel
- .xlw application/vnd.ms-excel
- .xlw application/x-excel
- .xlw application/x-msexcel
- .xm audio/xm
- .xml application/xml
- .xml text/xml
- .xmz xgl/movie
- .xpix application/x-vnd.ls-xpix
- .xpm image/x-xpixmap
- .xpm image/xpm
- .x-png image/png
- .xsr video/x-amt-showrun
- .xwd image/x-xwd
- .xwd image/x-xwindowdump
- .xyz chemical/x-pdb
- .z application/x-compress
- .z application/x-compressed
- .zip application/x-compressed
- .zip application/x-zip-compressed
- .zip application/zip
- .zip multipart/x-zip
- .zoo application/octet-stream
- .zsh text/x-script.zsh
────────────────────────────────────────────────────────────────────────────────
title: "The Nylas platform"
description: "Nylas' platform architecture, processes, rate limits, and data retention policies."
source: "https://developer.nylas.com/docs/dev-guide/platform/"
────────────────────────────────────────────────────────────────────────────────
Nylas offers a set of REST-style integration APIs and tools that let you quickly add communications functionality to an application you're developing. Your project uses the Nylas APIs to create, read, update, and delete data from providers like Google and Microsoft.

To keep your users' data in sync with their provider, Nylas...
- Maintains an IMAP `IDLE` connection with the provider.
- Exchanges ActiveSync ping notifications.
- Uses webhook notifications from the provider.
- Polls the provider for new changes.
## Nylas performance metrics
:::info
**The stats below are approximations to provide a rough idea of response times**. Actual performance varies per provider. See your service agreement for specific performance guarantees.
:::
| Metric | Value | Description |
| ----------------- | ---------------- | ---------------------------------------------------------------------------- |
| API Success Rate | 99.9% | The number of requests that return successful HTTP status codes. |
| P90(request_time) | Less than 500 ms | P90 of request_time to various API endpoints. |
| TT50 | 5 min | Average time to sync the first 50 threads during an account's initial sync. |
| TT500 | 25 min | Average time to sync the first 500 threads during an account's initial sync. |
## Platform uptime SLA guarantees
For customers who require high availability, Nylas offers uptime guarantees for the Core and Plus plans. Contact your Nylas representative for more information.
## Business Associate Agreements
Nylas also offers a Business Associate Agreement (BAA) for customers who require them for HIPAA or HITECH compliance. For more details, see the [Nylas Security whitepaper](https://www.nylas.com/guides/security-white-paper/).
## Static IPs
Some email servers in secure environments only accept connections and data from a known list of IP addresses. When you add static IP support to your plan, Nylas uses only a [specific set of static IP addresses](/docs/dev-guide/platform/static-ips/) when authenticating and connecting your project's users.
Static IP routing is currently available for IMAP and Exchange on-prem servers only.
────────────────────────────────────────────────────────────────────────────────
title: "Nylas domain certificates"
description: "Let's Encrypt certificates and Nylas domains."
source: "https://developer.nylas.com/docs/dev-guide/platform/nylas-domain-certificates/"
────────────────────────────────────────────────────────────────────────────────
Most of Nylas' domains are compliant with the [Let's Encrypt chain of trust](https://letsencrypt.org/certificates/). Some devices might receive errors if they access Nylas domains because they can't access websites secured by Let's Encrypt certificates.
The following Nylas domains use Let's Encrypt certificates:
- [`nyl.as`](/docs/dev-guide/platform/what-is-nyl/)
- `nylas.com`
- `nylas.team`
- `us.nylas.com`
────────────────────────────────────────────────────────────────────────────────
title: "Restricting data access with privacy mode"
description: "Use privacy mode to restrict users' access to events created with the Nylas APIs."
source: "https://developer.nylas.com/docs/dev-guide/platform/privacy-mode/"
────────────────────────────────────────────────────────────────────────────────
Nylas' privacy mode is a security feature that restricts users' access to objects created using the Nylas APIs only. This provides a layer of protection for sensitive calendar and event data. When privacy mode is enabled, users maintain access to all of their calendars, regardless of how they were created — however, they can only access events created using Nylas.
We recommend using privacy mode in cases where your users' data privacy and access management are critical (for example, in projects where compliance requirements stipulate that only authorized, application-created events should be accessible).
## How privacy mode works
:::warn
**Nylas doesn't track how events are created before you enable privacy mode**. When you enable privacy mode, your users immediately lose access to all events created previously, regardless of _how_ they were created.
:::
When you enable privacy mode, Nylas applies the following restrictions to API requests:
- The [Get Event](/docs/reference/api/events/get-events-id/), [Get all Events](/docs/reference/api/events/get-all-events/), and [Import Events](/docs/reference/api/events/import-events/) endpoints return events created using Nylas only.
- The [Update Event endpoint](/docs/reference/api/events/put-events-id/) accesses and updates events created using Nylas only.
- The [Delete Event endpoint](/docs/reference/api/events/delete-events-id/) accesses and deletes events created using Nylas only.
If your project tries to access events created outside of Nylas, you receive a [`403` error](/docs/api/errors/400-response/).
```json
{
"error": {
"message": "Event is not accessible under privacy filter",
"type": "forbidden"
},
"request_id": "5967ca40-a2d8-4ee0-a0e0-6f18ace39a90"
}
```
You also receive [Events webhook notifications](/docs/reference/notifications/#event-notifications) for events created through Nylas only. Events created using other methods won't trigger notifications, even if they exist in the user's calendar.
### Privacy mode and recurring events
Nylas determines how to treat [recurring events](/docs/v3/calendar/recurring-events/) based on the series' parent event. If the parent event was created using Nylas, users have full access to the entire series. Updating an occurrence doesn't revoke users' access to the series, and all instances of the recurring event remain accessible.
────────────────────────────────────────────────────────────────────────────────
title: "Nylas API and provider rate limits"
description: "Provider- and Nylas-specific rate limits."
source: "https://developer.nylas.com/docs/dev-guide/platform/rate-limits/"
────────────────────────────────────────────────────────────────────────────────
Rate limits apply when you make requests to the Nylas APIs and add account information in the [Nylas Dashboard](https://dashboard-v3.nylas.com/login). For best practices to mitigate rate limits, see [Avoiding rate limits in Nylas](/docs/dev-guide/best-practices/rate-limits/).
## Nylas rate limits
The table below describes API rate limits for Nylas. These apply to all endpoints.
| API | Type | Rate limit | Expiration |
| ---------------------------------------------------------- | --------------------- | ---------------------------------- | ---------- |
| [Applications](/docs/reference/api/applications/) | General | Up to 50 requests per application. | 1 second |
| [Authentication](/docs/reference/api/authentication-apis/) | General | Up to 50 requests per application. | 1 second |
| [Calendar](/docs/reference/api/calendar/) | General | Up to 200 requests per grant. | 1 second |
| [Connectors](/docs/reference/api/connectors-integrations/) | General | Up to 50 requests per application. | 1 second |
| [Contacts](/docs/reference/api/contacts/) | General | Up to 200 requests per grant. | 1 second |
| [Grants](/docs/reference/api/manage-grants/) | General | Up to 50 requests per application. | 1 second |
| [Messages](/docs/reference/api/messages/) | General | Up to 200 requests per grant. | 1 second |
| [Send](/docs/reference/api/messages/send-message/) | `application/json` | Up to 200 requests per grant. | 1 second |
| [Send](/docs/reference/api/messages/send-message/) | `multipart/form-data` | Up to 10 requests per grant. | 1 second |
| [Webhooks](/docs/reference/api/webhook-notifications/) | General | Up to 50 requests per application. | 1 second |
### Threads rate limits
:::warn
**The [**Get all Threads endpoint**](/docs/reference/api/threads/get-threads/) makes a significant number of calls to the provider for each request you make**. We strongly recommend using [query parameters](#query-parameters) to limit the threads data you receive.
:::
Because of the number of calls Nylas makes to the provider for each [Get all Threads request](/docs/reference/api/threads/get-threads/), you might encounter rate limits when working with large threads of messages. You can take the following steps to avoid rate limits:
- Specify a lower `limit` to reduce the number of results Nylas returns.
- Add [query parameters](#query-parameters) to your request to filter for specific information.
## Provider rate limits
:::info
**Not all IMAP providers publish information about their rate limits**. If you have questions, contact your provider's customer support team.
:::
Nylas' API requests are also subject to rate limits for the underlying providers. Keep these in mind as you build your project.
### Google rate limits
:::warn
**As of February 2024, Gmail has new requirements for accounts that send more than 5,000 messages per day**. For more information, see [Google's official documentation](https://support.google.com/a/answer/81126).
:::
Google has several sets of rate limits to keep in mind:
- **Overall usage limits**: 10,000 requests per minute, per application and 600 requests per minute, per user. Google calculates these limits within a one-minute sliding window.
- **Message sending limits**: 2,000 messages per day. See Google's [Gmail sending limits in Google Workspace](https://support.google.com/a/answer/166852) documentation.
- **Gmail API limits**: Per-user rate limit of 250 quota units per second. See Google's [Gmail usage limits](https://developers.google.com/gmail/api/reference/quota) documentation.
- **Google Calendar API limits**: API usage quotas, general usage limits, and operational limits. See Google's [Calendar quotas](https://developers.google.com/calendar/api/guides/quota) documentation.
A single Nylas request might make multiple calls to Google's APIs. Nylas returns a `Nylas-Provider-Request-Count` header that shows the number of calls it's made to the Google APIs, and a `Nylas-Gmail-Quota-Usage` header for requests to Nylas' [Drafts](/docs/reference/api/drafts/), [Messages](/docs/reference/api/messages/), [Threads](/docs/reference/api/threads/), [Folders](/docs/reference/api/folders/), and [Attachments](/docs/reference/api/attachments/) endpoints that shows how much of your Google API quota Nylas used for your request. We recommend monitoring these headers and spacing out your requests to avoid being rate-limited.
### Microsoft rate limits
Microsoft has two sets of rate limits to keep in mind:
- **Overall usage limits**: 10,000 requests per 10-minute period, a maximum of 4 concurrent requests, and a maximum of 150 MB uploaded per 5-minute period. See Microsoft's [Outlook service limits](https://learn.microsoft.com/en-us/graph/throttling-limits#outlook-service-limits) documentation.
- **Message sending limits**: 30 messages per minute. See Microsoft's [Exchange Online limits](https://learn.microsoft.com/en-us/office365/servicedescriptions/exchange-online-service-description/exchange-online-limits#sending-limits-1) documentation.
A single Nylas request might make multiple calls to the Microsoft Graph APIs. Nylas returns a `Nylas-Provider-Request-Count` header that shows the number of calls it's made to the Graph APIs for your request. We recommend monitoring this header and spacing out your requests to avoid being rate-limited.
If Microsoft rate-limits a request, Nylas returns a `Retry-After` header that shows the number of seconds you have to wait before you can make another request.
### EWS rate limits
Your EWS administrator configures the rate limit for your on-premises Exchange server, so Nylas cannot know the server's actual rate limits. If your Exchange server rate-limits a request, Nylas returns a `Retry-After` header that shows the number of seconds you have to wait before the server will accept another request.
### iCloud rate limits
Apple limits the number of messages you can send to 1,000 per day. For more information, see Apple's [Mailbox size and message sending limits](https://support.apple.com/en-us/102198) documentation.
────────────────────────────────────────────────────────────────────────────────
title: "Reporting abuse of the Nylas platform"
description: "Report abuse, misuse, and spam that might originate from Nylas systems."
source: "https://developer.nylas.com/docs/dev-guide/platform/report-abuse/"
────────────────────────────────────────────────────────────────────────────────
We take great care to prevent spam and abuse of the Nylas platform. But we all know that malicious actors never sleep.
If you're receiving spam or other unwanted content that you believe originates from Nylas, [contact Nylas Support](https://support.nylas.com/hc/en-us/requests/new). In your message, include any information that could help us trace, attribute, and stop the unwanted messages. This might include...
- A brief explanation about why the content is unwanted. Is it spammy or a scam? Does it contain viruses or other malicious files?
- Examples of the unwanted messages as either `.eml` or `.txt` files containing the original message _with the full original headers_.
- Logs or reports on the timing and frequency of the unwanted messages.
- Any information you can provide about the sender.
We appreciate all reports. They help us keep our platform, our customers, and our customers' customers safe and secure! 💙
────────────────────────────────────────────────────────────────────────────────
title: "Nylas static IP addresses"
description: "A list of Nylas static IPs, suitable for allowlisting."
source: "https://developer.nylas.com/docs/dev-guide/platform/static-ips/"
────────────────────────────────────────────────────────────────────────────────
The following is a list of Nylas static IPs that traffic may originate from.
## U.S. static IPs
```text
34.67.39.103
34.67.117.182
34.67.252.55
34.70.83.96
34.122.157.170
34.122.166.13
34.123.138.135
34.133.89.88
34.133.164.121
34.133.227.251
34.134.71.20
34.134.116.130
34.134.217.67
34.134.249.164
34.135.60.227
34.136.8.102
34.136.150.230
34.136.198.56
34.170.82.10
34.171.101.162
34.171.140.159
34.171.143.250
34.171.202.71
34.172.75.151
34.172.89.235
34.172.98.72
34.172.179.208
34.173.53.83
35.188.63.45
35.188.78.243
35.192.113.172
35.192.130.13
35.192.145.204
35.193.50.12
35.193.156.3
35.224.53.151
35.224.160.23
35.224.166.183
35.225.43.58
35.225.218.9
35.232.0.99
35.232.148.243
35.238.228.54
35.239.61.110
35.239.163.136
104.154.146.112
104.154.214.119
107.178.222.216
```
## E.U. static IPs
```text
34.89.13.240
34.89.22.198
34.89.38.104
34.89.43.31
34.89.89.177
34.89.120.135
34.105.131.216
34.105.195.37
34.105.226.2
34.105.238.42
34.105.251.62
34.105.254.91
34.142.35.130
34.142.59.110
34.142.60.59
34.142.115.161
34.142.122.71
34.142.127.203
34.147.154.112
34.147.237.95
35.189.69.97
35.189.87.227
35.189.123.135
35.197.202.228
35.197.217.43
35.230.138.6
35.230.151.236
35.234.155.115
35.246.19.112
35.246.43.120
35.246.61.250
35.246.81.179
```
────────────────────────────────────────────────────────────────────────────────
title: "What is nyl.as?"
description: "Learn about the `https://nyl.as/` links you might come across."
source: "https://developer.nylas.com/docs/dev-guide/platform/what-is-nyl/"
────────────────────────────────────────────────────────────────────────────────
You might occasionally come across a link in a message or on the web that has `https://nyl.as/` in it. These links redirect to another page on the internet. Links to `nyl.as` are part of our [message tracking feature](/docs/v3/email/message-tracking/) — they generate a notification when someone clicks the link. In normal use they're not malicious or a security issue.
:::warn
**If you find a `nyl.as` link that redirects to spam or a malicious website, report it to [**Nylas Support**](https://support.nylas.com/hc/en-us/requests/new)**. We'll take immediate action to fix the issue.
:::
## `nyl.as` errors on older devices
Some devices might receive "Certificate not trusted" errors (or other related errors) if they try to access `nyl.as` links. This is because they don't support [Let's Encrypt certificates](https://letsencrypt.org/2023/07/10/cross-sign-expiration). For more information, see [Nylas domain certificates](/docs/dev-guide/platform/nylas-domain-certificates).
────────────────────────────────────────────────────────────────────────────────
title: "Using granular scopes to request user data"
description: "Use granular scopes to control the level of access your project has to your users' data."
source: "https://developer.nylas.com/docs/dev-guide/scopes/"
────────────────────────────────────────────────────────────────────────────────
As you work with Nylas, you'll need to use scopes to control the level of access Nylas has to your users' data.
## What are scopes?
Granular scopes represent sets of permissions you request from your users, on a per-provider basis. Each provider has its own set of scopes, and your users either approve or reject them when they authenticate with your Nylas application.
:::info
**IMAP connectors don't support scopes**. For more information, see [Creating grants with IMAP authentication](/docs/v3/auth/imap/).
:::
## Nylas API scopes
Each of the Nylas APIs requires different scopes to function properly. The tables in the following sections list the scopes you need to work with specific Nylas features.
All scopes must include the fully-qualified URI path for the provider. The tables shorten the full scope URIs for space reasons, so be sure to add the provider prefix when requesting scopes.
### Messages API scopes
All scopes except `https://mail.google.com/` must be prefixed with Google's URI path (`https://www.googleapis.com/auth/`).
| Endpoint | Required scopes | Other scopes |
| ------------------------------------------------------------------------------------------------------------------------------------ | ----------------- | ---------------------------------------- |
| `GET /v3/grants//messages` `GET /v3/grants//messages/` | `/gmail.readonly` | `/gmail.modify` |
| `PUT /v3/grants//messages/` | `/gmail.modify` | — |
| `DELETE /v3/grants//messages/` | `/gmail.modify` | `https://mail.google.com/` (hard-delete) |
| `POST /v3/grants//messages/smart-compose` `POST /v3/grants//messages//smart-compose` | `/gmail.readonly` | `/gmail.modify` |
| `PUT /v3/grants//messages/clean` | `/gmail.readonly` | — |
| `POST /v3/grants//messages/send` | `/gmail.send` | `/gmail.compose` `/gmail.modify` |
:::info
**You need to request the `/gmail.send` scope if you want to schedule messages to be sent in the future**. For more information, see [Schedule messages to send in the future](/docs/v3/email/scheduled-send/).
:::
| Endpoint | Required scopes | Other scopes |
| ------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------- | ------------------------------------------------------------------- |
| `GET /v3/grants//messages` `GET /v3/grants//messages/` | `Mail.Read` | `Mail.ReadWrite` `Mail.Read.Shared` `Mail.ReadWrite.Shared` |
| `PUT /v3/grants//messages/` `DELETE /v3/grants//messages/` | `Mail.ReadWrite` | `Mail.ReadWrite.Shared` |
| `POST /v3/grants//messages/smart-compose` `POST /v3/grants//messages//smart-compose` | `Mail.Read` | `Mail.ReadWrite` `Mail.ReadWrite.Shared` `Mail.Read.Shared` |
| `PUT /v3/grants//messages/clean` | `Mail.Read` | — |
| `POST /v3/grants//messages/send` | `Mail.ReadWrite` `Mail.Send` | `Mail.ReadWrite.Shared` |
:::info
**You need to request the `Mail.ReadWrite` and `Mail.Send` scopes if you want to schedule messages to be sent in the future**. For more information, see [Schedule messages to send in the future](/docs/v3/email/scheduled-send/).
:::
| Endpoint | Scopes |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- |
| `GET /v3/grants//messages` `GET /v3/grants//messages/` | `email` `mail-r` |
| `PUT /v3/grants//messages/` `DELETE /v3/grants//messages/` `POST /v3/grants//messages/smart-compose` `POST /v3/grants//messages//smart-compose` `POST /v3/grants//messages/send` | `email` `mail-r` `mail-w` |
### Drafts API scopes
All scopes must be prefixed with Google's URI path (`https://www.googleapis.com/auth/`).
| Endpoint | Required scopes | Other scopes |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------- | ---------------- |
| `GET /v3/grants//drafts` `GET /v3/grants//drafts/` | `/gmail.readonly` | `/gmail.compose` |
| `POST /v3/grants//drafts` `PUT /v3/grants//drafts/` `DELETE /v3/grants//drafts/` | `/gmail.compose` | — |
| `POST /v3/grants//drafts/` | `/gmail.compose` | `/gmail.modify` |
| Endpoint | Required scopes | Other scopes |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------- | ------------------------------------------------------------------- |
| `GET /v3/grants//drafts` `GET /v3/grants//drafts/` | `Mail.Read` | `Mail.ReadWrite` `Mail.Read.Shared` `Mail.ReadWrite.Shared` |
| `POST /v3/grants//drafts` `PUT /v3/grants//drafts/` `DELETE /v3/grants//drafts/` | `Mail.ReadWrite` | `Mail.ReadWrite.Shared` |
| `POST /v3/grants//drafts/` | `Mail.ReadWrite` `Mail.Send` | `Mail.ReadWrite.Shared` |
| Endpoint | Scopes |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- |
| `GET /v3/grants//drafts` `GET /v3/grants//drafts/` | `email` `mail-r` |
| `POST /v3/grants//drafts/` `PUT /v3/grants//drafts/` `POST /v3/grants//drafts/` `DELETE /v3/grants//drafts/` | `email` `mail-r` `mail-w` |
### Folders API scopes
All scopes must be prefixed with Google's URI path (`https://www.googleapis.com/auth/`).
| Endpoint | Required scopes | Other scopes |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------- | --------------- |
| `GET /v3/grants//folders` `GET /v3/grants//folders/` `POST /v3/grants//folders` `PUT /v3/grants/NYLAS_GRANT_ID>/folders/` `DELETE /v3/grants//folders/` | `/gmail.labels` | `/gmail.modify` |
| Endpoint | Required scopes | Other scopes |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | ------------------------------------------------------------------- |
| `GET /v3/grants//folders` `GET /v3/grants//folders/` | `Mail.Read` | `Mail.ReadWrite` `Mail.Read.Shared` `Mail.ReadWrite.Shared` |
| `POST /v3/grants//folders` `PUT /v3/grants/NYLAS_GRANT_ID>/folders/` `DELETE /v3/grants//folders/` | `Mail.ReadWrite` | `Mail.ReadWrite.Shared` |
| Endpoint | Scopes |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------- |
| `GET /v3/grants//folders` `GET /v3/grants//folders/` | `email` `mail-r` |
| `POST /v3/grants//folders/` `PUT /v3/grants//folders/` `DELETE /v3/grants//folders/` | `email` `mail-r` `mail-w` |
### Attachments API scopes
All scopes must be prefixed with Google's URI path (`https://www.googleapis.com/auth/`).
| Endpoint | Required scopes | Other scopes |
| ------------------------------------------------------------- | ----------------- | --------------- |
| `GET /v3/grants//attachments/` | `/gmail.readonly` | `/gmail.modify` |
All scopes must be prefixed with Microsoft's URI path (`https://graph.microsoft.com/`).
| Endpoint | Required scopes | Other scopes |
| ------------------------------------------------------------- | --------------- | ------------------------------------------------------------------- |
| `GET /v3/grants//attachments/` | `Mail.Read` | `Mail.ReadWrite` `Mail.Read.Shared` `Mail.ReadWrite.Shared` |
| Endpoint | Scopes |
| ------------------------------------------------------------- | -------------------- |
| `GET /v3/grants//attachments/` | `email` `mail-r` |
### Contacts API scopes
All scopes must be prefixed with Google's URI path (`https://www.googleapis.com/auth/`).
| Endpoint | Required scopes | Other scopes |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------------ |
| `GET /v3/grants//contacts` `GET /v3/grants//contacts/` `GET /v3/grants//contacts/groups` | `/contacts.readonly` `/contacts.other.readonly` `/directory.readonly` | — |
| `POST /v3/grants//contacts` `PUT /v3/grants//contacts/` `DELETE /v3/grants//contacts/` | `/contacts` | — |
:::info
**You must request the `/contacts.other.readonly` scope to access contacts from the `inbox` source, and `/directory.readonly` for contacts from the `domain` source**.
:::
| Endpoint | Required scopes | Other scopes |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ------------ |
| `GET /v3/grants//contacts` `GET /v3/grants//contacts/` `GET /v3/grants//contacts/groups` | `Contacts.Read` `People.Read` | — |
| `POST /v3/grants//contacts` `PUT /v3/grants//contacts/` `DELETE /v3/grants//contacts/` | `Contacts.ReadWrite` | — |
:::info
**You must request the `People.Read` scope to access contacts from the `inbox` and `domain` sources**.
:::
### Calendar API scopes
All scopes must be prefixed with Google's URI path (`https://www.googleapis.com/auth/`).
| Endpoint | Required scopes | Other scopes |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ------------ |
| `GET /v3/grants//calendars` `GET /v3/grants//calendars/` `POST /v3/grants//calendars/free-busy` | `/calendar.readonly` | `/calendar` |
| `POST /v3/grants//calendars` `PUT /v3/grants//calendars/` `DELETE /v3/grants//calendars/` | `/calendar` | — |
| `POST /v3/calendars/availability` | `/calendar.readonly` | `/calendar` |
:::info
**You need to request the `/calendar` scope if you want to use the `primary` keyword to reference the primary calendar associated with a grant**. For more information about the `primary` keyword, see [Find a calendar ID](/docs/reference/api/calendar/).
:::
| Endpoint | Required scopes | Other scopes |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | --------------------- |
| `GET /v3/grants//calendars` `GET /v3/grants//calendars/` `POST /v3/grants//calendars/free-busy` | `Calendars.Read` | `Calendars.ReadWrite` |
| `POST /v3/grants//calendars` `PUT /v3/grants//calendars/` `DELETE /v3/grants//calendars/` | `Calendars.ReadWrite` | — |
| `POST /v3/calendars/availability` | `Calendars.Read` | `Calendars.ReadWrite` |
### Events API scopes
All scopes must be prefixed with Google's URI path (`https://www.googleapis.com/auth/`).
| Endpoint | Required scopes | Other scopes |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | ----------------------------------------------------------- |
| `GET /v3/grants//events` `GET /v3/grants//events/` | `/calendar.events.readonly` | `/calendar.events` `/calendar` `/calendar.readonly` |
| `POST /v3/grants//events` `PUT /v3/grants//events/` `DELETE /v3/grants//events/` `POST /v3/grants//events//send-rsvp` | `/calendar.events` | `/calendar` |
| `GET /v3/grants//resources` | `/admin.directory.resource.` `calendar.readonly` | — |
:::info
**You need to request the `/calendar` scope if you want to use the `primary` keyword to reference the primary calendar associated with a grant**. For more information about the `primary` keyword, see [Find a calendar ID](/docs/reference/api/calendar/).
:::
| Endpoint | Required scopes | Other scopes |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | --------------------- |
| `GET /v3/grants//events` `GET /v3/grants//events/` | `Calendars.Read` | `Calendars.ReadWrite` |
| `POST /v3/grants//events` `PUT /v3/grants//events/` `DELETE /v3/grants//events/` `POST /v3/grants//events//send-rsvp` | `Calendars.ReadWrite` | — |
| `GET /v3/grants//resources` | `Place.Read.All` | — |
:::info
**You need to request the `OnlineMeetings.ReadWrite` scope if you want to automatically create conferencing details on events**. For more information, see [Enable autocreate for conferencing](/docs/v3/calendar/add-conferencing/#enable-autocreate-for-conferencing).
:::
:::info
**You need to request the `meeting:write:meeting`, `meeting:update:meeting`, `meeting:delete:meeting`, and `user:read:user` scopes if you want to automatically create conferencing details on events**. For more information, see [Enable autocreate for conferencing](/docs/v3/calendar/add-conferencing/#enable-autocreate-for-conferencing).
:::
### Scheduler API scopes
All scopes must be prefixed with Google's URI path (`https://www.googleapis.com/auth/`).
| Endpoint | Required scopes | Other scopes |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ------------ |
| `POST /v3/grants//scheduling/configurations` `PUT /v3/grants//scheduling/configurations/` `GET /v3/grants//scheduling/availability` | `/calendar.readonly` | `/calendar` |
| `POST /v3/grants//scheduling/bookings` `PATCH /v3/grants//scheduling/bookings/` `DELETE /v3/grants//scheduling/bookings/` | `/calendar.events` | `/calendar` |
| Endpoint | Required scopes | Other scopes |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | --------------------- |
| `POST /v3/grants//scheduling/configurations` `PUT /v3/grants//scheduling/configurations/` `GET /v3/grants//scheduling/availability` | `Calendars.Read` | `Calendars.ReadWrite` |
| `POST /v3/grants//scheduling/bookings` `PATCH /v3/grants//scheduling/bookings/` `DELETE /v3/grants//scheduling/bookings/` | `Calendars.ReadWrite` | — |
### Order Consolidation API scopes
All scopes must be prefixed with Google's URI path (`https://www.googleapis.com/auth/`).
| Endpoint | Required scopes | Other scopes |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | ------------ |
| `GET /v3/grants//consolidated-order` `GET /v3/grants//consolidated-shipment` `GET /v3/grants//consolidated-return` | `/gmail.readonly` | — |
All scopes must be prefixed with Microsoft's URI path (`https://graph.microsoft.com/`).
| Endpoint | Required scopes | Other scopes |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ------------------ |
| `GET /v3/grants//consolidated-order` `GET /v3/grants//consolidated-shipment` `GET /v3/grants//consolidated-return` | `Mail.Read` | `Mail.Read.Shared` |
## Nylas notification scopes
Each of Nylas' notification triggers requires different scopes to function properly. The tables in the following sections list the scopes you need to work with specific Nylas features.
All scopes must include the fully-qualified URI path for the provider. The tables shorten the full scope URIs for space reasons, so be sure to add the provider prefix when requesting scopes.
### Messages notification scopes
All scopes must be prefixed with Google's URI path (`https://www.googleapis.com/auth/`).
| Notification trigger | Required scopes | Other scopes |
| ------------------------------------------------ | ----------------------------------- | ------------------------------------ |
| `message.send_success` `message.send_failed` | `/gmail.send` | — |
| `message.created` `message.updated` | `/gmail.metadata` | `gmail.readonly` `/gmail.modify` |
| `message.bounce_detected` | `/gmail.readonly` `/gmail.send` | `/gmail.modify` |
:::warn
**If your account uses the `/gmail.metadata` scope, Nylas sends [**`message.*.metadata` notifications**](/docs/reference/notifications/message-metadata/message-created-metadata/) with limited information**. For more information, see [Using webhooks with Nylas](/docs/v3/notifications/#gmail-metadata-webhooks).
:::
| Notification trigger | Required scopes | Other scopes |
| ------------------------------------------------ | -------------------------------- | ------------------------------------------------------------------- |
| `message.send_success` `message.send_failed` | `Mail.ReadWrite` `Mail.Send` | — |
| `message.created` `message.updated` | `Mail.Read` | `Mail.ReadWrite` `Mail.ReadWrite.Shared` `Mail.Read.Shared` |
| `message.bounce_detected` | `Mail.Read` `Mail.Send` | `Mail.ReadWrite` |
All `message.*` notifications require the `email` and `mail-r` scopes.
### Threads notification scopes
All scopes must be prefixed with Google's URI path (`https://www.googleapis.com/auth/`).
| Notification trigger | Required scopes | Other scopes |
| -------------------- | ----------------------------------- | --------------- |
| `thread.replied` | `/gmail.readonly` `/gmail.send` | `/gmail.modify` |
| Notification trigger | Required scopes | Other scopes |
| -------------------- | --------------------------- | ---------------- |
| `thread.replied` | `Mail.Read` `Mail.Send` | `Mail.ReadWrite` |
All `thread.*` notifications require the `email` and `mail-r` scopes.
### Folders notification scopes
All scopes must be prefixed with Google's URI path (`https://www.googleapis.com/auth/`).
| Notification trigger | Required scopes | Other scopes |
| ---------------------------------------------------------- | ----------------- | ------------------------------------ |
| `folder.created` `folder.updated` `folder.deleted` | `/gmail.metadata` | `/gmail.readonly` `gmail.modify` |
:::warn
**If your account uses the `/gmail.metadata` scope, Nylas sends [**`message.*.metadata` notifications**](/docs/reference/notifications/message-metadata/message-created-metadata/) with limited information**. For more information, see [Using webhooks with Nylas](/docs/v3/notifications/#gmail-metadata-webhooks).
:::
| Notification trigger | Required scopes | Other scopes |
| ---------------------------------------------------------- | --------------- | ------------------------------------------------------------------- |
| `folder.created` `folder.updated` `folder.deleted` | `Mail.Read` | `Mail.ReadWrite` `Mail.ReadWrite.Shared` `Mail.Read.Shared` |
All `folder.*` notifications require the `email` and `mail-r` scopes.
### Contacts notification scopes
All scopes must be prefixed with Google's URI path (`https://www.googleapis.com/auth/`).
| Notification trigger | Required scopes | Other scopes |
| --------------------------------------- | ----------------------------------- | ------------ |
| `contact.updated` `contact.deleted` | `/contact.readonly` `/contacts` | — |
| Notification trigger | Required scopes | Other scopes |
| --------------------------------------- | --------------- | ------------------------------------------------------------------------------- |
| `contact.updated` `contact.deleted` | `Contacts.Read` | `Contacts.Read.Shared` `Contacts.ReadWrite` `Contacts.ReadWrite.Shared` |
### Calendar notification scopes
All scopes must be prefixed with Google's URI path (`https://www.googleapis.com/auth/`).
| Notification trigger | Required scopes | Other scopes |
| ---------------------------------------------------------------- | --------------------------- | ------------------ |
| `calendar.created` `calendar.updated` `calendar.deleted` | `/calendar.events.readonly` | `/calendar.events` |
| Notification trigger | Required scopes | Other scopes |
| ---------------------------------------------------------------- | ---------------- | ---------------------------------------------------------------------------------- |
| `calendar.created` `calendar.updated` `calendar.deleted` | `Calendars.Read` | `Calendars.Read.Shared` `Calendars.ReadWrite` `Calendars.ReadWrite.Shared` |
### Events notification scopes
All scopes must be prefixed with Google's URI path (`https://www.googleapis.com/auth/`).
| Notification trigger | Required scopes | Other scopes |
| ------------------------------------------------------- | ---------------------------------------------------- | ------------------ |
| `event.created` `event.updated` `event.deleted` | `/calendar.events.readonly` `/calendar.readonly` | `/calendar.events` |
| Notification trigger | Required scopes | Other scopes |
| ------------------------------------------------------- | ---------------- | ---------------------------------------------------------------------------------- |
| `event.created` `event.updated` `event.deleted` | `Calendars.Read` | `Calendars.Read.Shared` `Calendars.ReadWrite` `Calendars.ReadWrite.Shared` |
### ExtractAI notification scopes
All scopes must be prefixed with Google's URI path (`https://www.googleapis.com/auth/`).
| Notification trigger | Required scopes | Other scopes |
| -------------------------------------------------------------------------------------------------- | ----------------- | ------------ |
| `message.intelligence.order` `message.intelligence.tracking` `message.intelligence.return` | `/gmail.readonly` | — |
| Notification trigger | Required scopes | Other scopes |
| -------------------------------------------------------------------------------------------------- | --------------- | ------------------ |
| `message.intelligence.order` `message.intelligence.tracking` `message.intelligence.return` | `Mail.Read` | `Mail.Read.Shared` |
## Google OAuth verification
If your application accesses Google user data with the Google APIs and requests certain scopes, you might have to complete the Google verification process and a separate security assessment process. The processes that you need to complete depends on whether your application requests [_sensitive_ or _restricted_ scopes](/docs/provider-guides/google/google-verification-security-assessment-guide/#google-scopes).
| Scope type | Required processes | Google policy and requirements |
| ---------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Sensitive | Google verification | Your application must follow [Google’s API Services User Data Policy](https://developers.google.com/terms/api-services-user-data-policy). |
| Restricted | Google verification and security assessment | Your application must follow [Google’s API Services User Data Policy](https://developers.google.com/terms/api-services-user-data-policy) and meet [additional requirements for specific scopes](https://developers.google.com/terms/api-services-user-data-policy#additional_requirements_for_specific_api_scopes). |
For more information, see our [Google verification and security assessment guide](/docs/provider-guides/google/google-verification-security-assessment-guide/).
────────────────────────────────────────────────────────────────────────────────
title: "Customize branding in Nylas Hosted Authentication flow"
description: "Use your own branding in the Nylas Hosted Authentication flow. You can replace the Nylas logo on the login page and set up a custom domain name (CNAME)."
source: "https://developer.nylas.com/docs/dev-guide/whitelabeling/"
────────────────────────────────────────────────────────────────────────────────
Nylas provides a login page for Hosted Authentication that displays the Nylas logo to tell the user who is requesting access to their account. If the user isn’t expecting the Nylas logo or domain, however, they might cancel the auth process.
Any Nylas admin can add their brand logo to their user auth screens for each application, so users see your company’s branding instead of the Nylas logo.
The Nylas domain (`nylas.com`) might still appear during the OAuth process. More customization features are available to further customize the auth experience, and prevent the Nylas domain from appearing in the process. If you're on a paid tier that includes it, you can replace these by [customizing your Hosted OAuth domain](#customize-authentication-domain).
## Set up Hosted Authentication branding
You can upload your own brand logo or icon for the user-facing Hosted OAuth page so it replaces the Nylas logo. Branding settings are unique to each Nylas application.
You can change the logo using either the [Nylas Dashboard](#add-branding-using-nylas-dashboard) or the [Nylas APIs](#add-branding-using-nylas-api).
:::info
**The icon you use must be a PNG, JPG, or TIF file with a maximum size of 1MB**. Nylas automatically resizes the logo to 72x72 pixels, so it's recommended you use a square image.
:::
### Add branding using Nylas Dashboard
To upload a logo for the Hosted Auth login page, navigate to your application in the Nylas Dashboard and select **Hosted authentication** in the left navigation. Then, enter a link to your logo in the **Icon URL** field.
### Add branding using Nylas API
Make an [Update Application request](/docs/reference/api/applications/update_application/) that includes the `branding.icon_url` parameter.
```bash
curl --request PATCH \
--url 'https://api.us.nylas.com/v3/applications' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer ' \
--data '{
"branding": {
"icon_url": "www.example.com/nylas-logo.png"
}
}'
```
## Customize authentication domain
By default, Nylas uses the `nylas.com` domain in the OAuth process, even if you replace the Nylas logo. If users don’t expect to see “Nylas” during authentication, they might stop the process on security grounds.
To prevent this, you can set up a CNAME so your own domain appears instead during the auth process.
1. [Subscribe to a Nylas plan](https://www.nylas.com/pricing/?utm_source=docs&utm_campaign=&utm_content=whitelabeling) that includes custom domain name support.
2. [Add your logo to the Hosted Auth page](#set-up-hosted-authentication-branding).
3. [Set up a CNAME record for authentication](#set-up-cname-record).
4. [Contact Nylas Support](/docs/support/#contact-nylas-support) to activate your domain.
5. [Update your provider auth apps](#update-provider-auth-apps) to allow authentication from your CNAME record address.
### Set up CNAME record
To enable authentication through your custom domain, you need to create a CNAME record in your DNS settings. Be sure to choose the subdomain you want to use for the auth process (for example, `auth.example.com`) and point the CNAME record to `-auth.us.nylas.com`. This is where you start user auth requests. For users authenticating using a web browser, this URL might be displayed in the address bar, so make sure your domain is clearly included.
:::success
**Make sure to test the DNS settings for your CNAME record before you use it in production**. If it’s not set up properly, your users won’t be able to use your auth flow.
:::
After you set up your CNAME record, you can [contact Nylas Support](/docs/support/#contact-nylas-support) to activate your domain.
### Update provider auth apps
Now that you have a CNAME record, you need to add the URL to your provider auth apps as an allowed redirect URI. You can either make this an _additional_ URI, or use it to _replace_ the Nylas redirect URI. For example, you might have `api.us.nylas.com/v3/connect/callback` configured as a redirect URI, and replace it with `-auth.us.nylas.com/v3/connect/callback`.
- **Google auth apps**: Log in to the GCP portal, select **Credentials** in the left navigation, and update the appropriate credential record.
- **Azure auth apps**: Log in to the Microsoft Azure portal, search for **App registrations**, navigate to the resulting page, and update the **Redirect URI**.
## Using customized Hosted Authentication
After you set up and enable customized Hosted Authentication, you can access the auth flow using the same API methods — you just need to replace the Nylas API route with your custom domain.
For example, you might have a URL to start authentication that looks like this: `https://api.us.nylas.com/v3/connect/auth?client_id=&redirect_uri=&response_type=code&provider=google`. Using customized authentication, it would resemble `https://-auth.us.nylas.com/v3/connect/auth?client_id=&redirect_uri=&response_type=code&provider=google` instead.
────────────────────────────────────────────────────────────────────────────────
title: "Using app passwords in Nylas"
description: "Learn about app passwords and how to set them up."
source: "https://developer.nylas.com/docs/provider-guides/app-passwords/"
────────────────────────────────────────────────────────────────────────────────
App passwords (sometimes called "app-specific passwords") are randomly generated passwords that provide a secure way for users to authenticate with third parties such as Nylas, without using their regular account password.
Because every provider has a different way of creating an app password, you must direct your user to their provider's app password tool so they can create one. When that's done, they can complete the authentication process with Nylas.
:::info
**Email service providers, as a rule, don't offer APIs to allow third parties to generate app passwords on a user's behalf**. This means that this step _must_ be done manually by the user.
:::
When you use the [Detect Provider endpoint](/docs/reference/api/connectors-integrations/detect_provider_by_email/), Nylas includes a link to the detected provider's app password tool, if one is available.
## App passwords for Microsoft accounts
An app password is required if 2FA is enabled and you are authenticating without a security code.
- [Microsoft Exchange Login](/docs/provider-guides/exchange-on-prem/)
- [Using app passwords](https://support.microsoft.com/en-us/account-billing/using-app-passwords-with-apps-that-don-t-support-two-step-verification-5896ed9b-4263-e681-128a-a6f2979a7944)
## App passwords for Yahoo accounts
Yahoo Mail accounts require an app password for Nylas to authenticate. An app password gives Nylas access to the account through the single password login.
- [Yahoo Authentication](/docs/provider-guides/yahoo-authentication/)
- [Generate and manage third-party app passwords](https://help.yahoo.com/kb/learn-generate-password-sln15241.html)
## App passwords for iCloud accounts
Apple ID uses an app password for accessing information in iCloud.
- [iCloud Authentication](/docs/provider-guides/icloud/)
- [Using app-specific passwords](https://support.apple.com/en-us/HT204397)
## App passwords for other providers
The following providers also require app passwords:
- [AOL](https://help.aol.com/articles/Create-and-manage-app-password)
- [GMX](https://support.gmx.com/security/2fa/application-specific-passwords.html)
- [Zoho](https://help.zoho.com/portal/en/kb/bigin/channels/email/articles/generate-an-app-specific-password)
────────────────────────────────────────────────────────────────────────────────
title: "Authenticating Exchange on-premises accounts with Nylas"
description: "Connect Exchange on-prem accounts to Nylas, and troubleshoot connection issues."
source: "https://developer.nylas.com/docs/provider-guides/exchange-on-prem/"
────────────────────────────────────────────────────────────────────────────────
You can use the Nylas EWS connector to connect to email accounts hosted on Exchange on-prem servers so you can use the Nylas Email, Calendar, Contacts, and Notetaker APIs with them.
:::warn
**Microsoft announced the [retirement of Exchange Web Services in 2022](https://techcommunity.microsoft.com/t5/exchange-team-blog/retirement-of-exchange-web-services-in-exchange-online/ba-p/3924440) and strongly recommended that [all users migrate to use Microsoft Graph](https://techcommunity.microsoft.com/t5/exchange-team-blog/ews-exchange-web-services-to-microsoft-graph-migration-guide/ba-p/3957158).** Users on Exchange Online have already been migrated.
:::
## How is EWS different from the Microsoft connector?
Microsoft Exchange on-prem is a self-hosted application that an administrator can run on their own servers to provide email, calendar, and contacts directory features to their organization. This model predates modern cloud architecture, and requires anyone who wants to connect to this service (including Nylas) to make network requests directly to the specified server using the server address and port. While Microsoft has built some features such as [autodiscovery](#using-autodiscovery-with-exchange) to smooth this process, they are sometimes misconfigured, or not configured.
Microsoft announced the EWS retirement and is deprecating some of the services that supported it. However, Exchange is still installed on many private servers and used by many people.
Nylas uses a separate connector to handle Exchange on-prem authentication requests because although it is _technically_ a Microsoft product, it uses a totally different connection process.
If your project _only_ uses the Email APIs, you can use an IMAP connector for these accounts instead.
## Exchange on-prem minimum version
To use the Exchange on-prem connector with Nylas, the Exchange server must be running Exchange 2007 or later.
If you want to use starred messages, the server must be running Exchange 2010 or later.
## Add an EWS connector
You can add an EWS connector to your application by making a [`POST /v3/connectors` request](/docs/reference/api/connectors-integrations/create_connector/), specifying the `provider` as `ews`, and including scopes that indicate which API services you want to use.
To add the EWS connector from the Dashboard:
1. In the Nylas Dashboard, navigate to the application you want to use EWS with.
2. Click **Connectors** in the left navigation.
3. Find the EWS item, and click the plus icon (**+**).
4. Click the EWS connector and select the scopes you want to use.
You must set Nylas-defined scopes on the EWS connector to indicate which API objects you want to use. Add one or more of the following scopes to enable EWS access.
- `ews.messages`
- `ews.calendars`
- `ews.contacts`
## Connect a user with EWS and Hosted authentication
1. Send the user to the Nylas Hosted auth login page by making a [`GET /v3/connect/auth` request](/docs/reference/api/authentication-apis/get_oauth2_flow/) and specifying the `provider` as `ews`.
2. Have the user log in using their Exchange account name and password, and if necessary, the server-specific details.
3. Complete the auth flow by [exchanging a token with the provider](/docs/reference/api/authentication-apis/exchange_oauth2_token/). The API response contains the grant ID for the user, which you can use query for their data.
## Using autodiscovery with Exchange
In most scenarios, users can log in to Microsoft Exchange using their email address and password. This is because Nylas performs [autodiscovery](https://docs.microsoft.com/en-us/exchange/client-developer/exchange-web-services/autodiscover-for-exchange) by default to determine the best server settings for the login attempt.
However, autodiscovery is sometimes unable to determine the correct settings. When this happens, the user can [enter more settings in the Advanced section](#log-in-using-advanced-settings) of the login screen. If issues persist, the domain administrator can [test the Exchange server's autodiscovery settings](https://testconnectivity.microsoft.com/).
### Log in using advanced settings
If autodiscovery is unavailable when a user authenticates using [Hosted auth](/docs/provider-guides/microsoft/authentication/), they must click **Additional settings** and enter information about the Exchange server.
1. Enter the **Exchange username**, formatted as either `username@example.com` or `DOMAIN\username`. This is usually the same as the user's Windows login.
2. Enter the **Exchange server** address (for example, `mail.example.com`). This address is usually visible in the Address bar when the user logs in to the Outlook Web App.
:::info
**The user might need to contact their Exchange or IT administrator to get the correct the connection settings**.
:::

## Static IP support for Exchange on-prem accounts
Some email servers in secure environments only accept connections and data from a known list of IP addresses. If you're on a contract plan, you can use [static IP routing](/docs/dev-guide/platform/#static-ips) to connect to an Exchange on-prem server.
## Message IDs and folder moves (Microsoft Exchange via EWS)
For Microsoft Exchange mailboxes accessed via the Exchange Web Services (EWS) protocol, message IDs can change when a message is moved between folders. This is expected Exchange behavior.
This applies to Exchange on-premise servers which will have grants of type `exchange`. This **does not apply** to mailboxes hosted by Exchange Online, or hybrid Exchange servers as we use **Microsoft Graph instead of EWS**. Grants that use Microsoft Graph instead of EWS will be of type `microsoft`.
Because of this, **Nylas message IDs for Microsoft accounts should be treated as folder-specific pointers, not permanent identifiers**. If you need to track a message across folder moves, use the `InternetMessageId` (RFC `Message-ID` header) instead. This value remains stable across moves.
To get the `InternetMessageId`, [include headers in your message requests or webhooks](/docs/v3/email/headers-mime-data/) by setting the `fields` query parameter to `include_headers`.
:::info
**Multiple messages can share the same `InternetMessageId`**. Exchange allows copies of a message to exist in multiple folders, all with the same `InternetMessageId`. If you need to distinguish between copies (for example, in compliance or auditing scenarios), you should track both the `InternetMessageId` and the folder location.
:::
## EWS limitations
- Nylas currently supports self-hosted EWS instances using the `ews` provider and Hosted Authentication.
- If an account is accessible only through a corporate network, VPN, or firewall, you must allow Nylas to connect to the account.
- Be sure to turn on Exchange Web Services (EWS) and make it visible outside of the corporate network.
- Nylas uses EWS to fetch messages and calendars for on-premises Exchange servers. If EWS isn't enabled, Nylas connects to the server using IMAP and fetches messages _only_.
- If auto-discovery is available, Nylas attempts to use it. If it's not available, you must provide all settings information.
- If a user has to enter their server settings information, Nylas can't use auto-discovery.
- The EWS server must support the [Advanced Query Syntax (AQS)](https://learn.microsoft.com/en-us/windows/win32/lwef/-search-2x-wds-aqsreference) parser and have it enabled so Nylas can search and filter messages for users on that server.
### App password required for two-factor authentication
If a user has two-factor authentication (2FA) enabled for their account, they must [generate an app password](https://support.microsoft.com/en-us/help/12409/microsoft-account-app-passwords-two-step-verification).
### Exchange with private networks and VPNs
For a user to connect, the Exchange server must not be in a private network or require a VPN to access it.
### Unsupported EWS types
Nylas supports Exchange on-prem only. Nylas cannot connect to _Exchange services_ for Outlook, Microsoft 365 (previously Office 365), Live.com, or Exchange ActiveSync (EAS) accounts.
You can use the `microsoft` connector to authenticate Outlook, Microsoft 365, and Live.com users who are already using Microsoft Graph's modern OAuth system. Nylas doesn't support Exchange ActiveSync, and you cannot authenticate these accounts using EAS.
────────────────────────────────────────────────────────────────────────────────
title: "Setting up Google Pub/Sub"
description: "Set up Google Pub/Sub and connect it to your Nylas application for faster syncing of messages."
source: "https://developer.nylas.com/docs/provider-guides/google/connect-google-pub-sub/"
────────────────────────────────────────────────────────────────────────────────
[Google's Pub/Sub subscription service](https://cloud.google.com/pubsub/?hl=en) allows you to receive webhook notifications from Google in a timely manner. You can either use the [Nylas-maintained set up script](#add-pubsub-with-the-nylas-script) to add Pub/Sub to your app, or [set it up manually](#manually-add-pubsub).
If you plan to use the Nylas Email API with Google, you need to set up Pub/Sub. If you don't plan to use the Nylas Email API with your GCP app (for example, if you're creating a calendar-only project), you can skip this step.
## Before you begin
Before you set up Pub/Sub, you must have [set up a Google provider auth app](/docs/provider-guides/google/create-google-app/).
## Add Pub/Sub with the Nylas script
To simplify the process of installing Pub/Sub, Nylas maintains a script that you can run to automatically provision the GCP resources in Golang.
Before you use the script, make sure your environment is set up properly:
- [Install the Go language](https://go.dev/doc/install).
- [Install the Google Cloud CLI tool](https://cloud.google.com/sdk/docs/install-sdk).
- Ensure that the Pub/Sub and IAM APIs are enabled in your GCP app. You can do this using the `gcloud` CLI:
```bash
gcloud services enable pubsub.googleapis.com
gcloud services enable iam.googleapis.com
```
:::warn
**You must set up your Pub/Sub topic and its related resources in the Google auth app that you use to authenticate users with Nylas**.
:::
When your environment is ready, download and run the Nylas script:
1. Download the script from the [Nylas infra-setup repository](https://github.com/nylas-samples/infra-setup) and change your local directory to `google-pubsub-sync`.
```bash
git clone https://github.com/nylas-samples/infra-setup
cd infra-setup/google-pubsub-sync
```
2. Use the `gcloud` CLI to switch the project setup to your GCP app.
```bash
gcloud config set project $
```
3. Authenticate with your GCP app. Make sure that the account you authenticate with has permission to create Pub/Sub and IAM resources.
```bash
gcloud auth login
gcloud auth application-default login
```
4. Fetch the dependencies for the script.
```bash
go get .
```
5. Run the script.
```bash
go run main.go --projectId $
```
- If you want to configure your GCP app in an environment other than the U.S., use the `--env` flag, as in the code snippet below. The flag supports the `us`, `eu` and `staging` values.
```bash
go run main.go --projectId $ --env eu
```
6. Save the topic name.
If the script fails with a `403` error with a `SERVICE_DISABLED` message, make sure to enable both the IAM and Pub/Sub APIs in your project using the `gcloud` CLI.
```bash
gcloud services enable pubsub.googleapis.com
gcloud services enable iam.googleapis.com
```
## Manually add Pub/Sub
To manually add Pub/Sub to your GCP app, you must [create a service account](#create-a-google-service-account) and [subscribe to a Pub/Sub topic](#create-a-pubsub-topic).
### Create a Google service account
First, create a service account in your GCP app:
1. From the Google Cloud Platform dashboard, navigate to **IAM & admin > Service accounts**.
2. Select your project and click **Create service account**.
3. Name the account `nylas-gmail-realtime`.
:::warn
**Keep in mind**: The service account name must be _exactly_ `nylas-gmail-realtime` for the Nylas connector to work.
:::
4. Optionally, add a description to the service account.
5. Click **Create and continue**.
6. Leave the **Grant this service account access to project** section blank and click **Continue**.
7. Leave the **Grant users access to this service account** section blank.
8. Click **Done**.
The following video walks through the process of creating a service account in the Google Cloud Platform dashboard.
### Create a Pub/Sub topic
Next, create a Pub/Sub topic and subscribe to it.
:::warn
**You must set up your Pub/Sub topic and its related resources in the Google auth app that you use to authenticate users with Nylas**.
:::
1. From the Google Cloud Platform dashboard, search for "pub/sub" and select **Pub/Sub**.
2. Click **Create topic**.
3. Enter `nylas-gmail-realtime` as the topic ID, and leave everything else as it is.
:::warn
**Keep in mind**: The topic ID must be _exactly_ `nylas-gmail-realtime` for the Nylas connector to work.
:::
4. On the next page, click **Show info panel** if the panel is not already open, and select **Add principal**.
5. Enter `gmail-api-push@system.gserviceaccount.com` in the **New principals** field and set the **role** to **Pub/Sub publisher**.
6. On the Topics page, find the **Subscription** section and click `nylas-gmail-realtime-sub`.
7. Select the subscription and click **Edit**.
8. Change the **Delivery type** to **Push**.
9. Set the **Endpoint URL**:
- **For the U.S.**, use `https://gmailrealtime.us.nylas.com`.
- **For the E.U.**, use `https://gmailrealtime.eu.nylas.com`.
:::info
**If you plan to use your GCP app for multiple Nylas regions, you must create a Pub/Sub subscription for each region**.
:::
10. Select **Enable authentication** and choose the `nylas-gmail-realtime` service account.
11. Under **Expiration period**, select **Never expire**.
12. When prompted, grant the account the `roles/iam.serviceAccountTokenCreator` role. If the prompt doesn't appear, follow these steps to add the role manually:
1. From the GCP dashboard, select **IAM & admin > Service accounts**.
2. Copy the full email address for the `nylas-gmail-realtime` service account. The email address should start with `nylas-gmail-realtime`.
3. Select the service account.
4. Navigate to the **Permissions** tab, then find the **Principals** tab at the bottom of the section.
5. Find the `nylas-gmail-realtime-email` service account and click the **Edit** symbol next to it.
- If the service account isn't listed, click **Grant access** and paste the email address in the **New principals** field.
6. In the pop-up that appears, click **Add another role**.
7. Search for `service account token creator` and select the role.
8. Click **Save**.
13. Leave the other fields as they are and click **Update**. Google saves your changes, and you're returned to the Subscription page.
14. Save the topic name.
## Add topic name to the Nylas Dashboard
Now that you have a Pub/Sub topic, you can add it to the Nylas Dashboard:
1. From the Nylas Dashboard, select the Nylas application you want to attach the Pub/Sub topic to.
2. Select **Connectors** from the left navigation.
3. Select your Google connector and enter the topic you created in the **Google Pub/Sub topic name** field (for example, `projects/nylas-test/topics/nylas-gmail-realtime`).
4. Save your changes.
Repeat these steps for each Nylas application that needs real-time Gmail message sync.
:::success
**If you use the same GCP application for all of your Nylas applications, you can use the same Pub/Sub topic for faster email notifications**.
:::
────────────────────────────────────────────────────────────────────────────────
title: "Creating a Google auth app"
description: "Create and configure a Google Cloud Platform (GCP) application to use with Nylas."
source: "https://developer.nylas.com/docs/provider-guides/google/create-google-app/"
────────────────────────────────────────────────────────────────────────────────
This page explains how to create and configure a Google Cloud Platform (GCP) application to use with your Nylas project.
:::info
**Don't want to create your own GCP project?** The [Nylas Shared GCP App](/docs/provider-guides/google/shared-gcp-app/) lets you skip GCP setup and Google's verification process entirely. Nylas manages the GCP project for you.
:::
## Before you begin
Before you create your GCP application, you need to plan a couple fundamental parts of your project:
- [Choose your authentication method](#choose-authentication-method).
- [Decide whether the application will be external or internal](#choose-external-or-internal-application).
### Choose authentication method
First, you need to decide which authentication method works for you: Hosted OAuth or Bring Your Own (BYO) Authentication.
:::warn
**If you want to switch authentication methods later, you'll need to create and set up a new Google provider auth app**. Your users will also have to re-authenticate with the new app.
:::
[**Hosted OAuth**](/docs/v3/auth/hosted-oauth-accesstoken/) is the fastest way to get started. If you're not interested in customizing your application, or you want to test with a few users, Nylas recommends you use Hosted OAuth.
[**BYO Authentication**](/docs/v3/auth/bring-your-own-authentication/) lets you customize your application's auth process. This means your users will see your company name instead of "Nylas" on the OAuth screen. If you choose to use BYO Authentication, you must have an existing Nylas application and a callback URI.
### Choose external or internal application
You also need to decide if you want to make your GCP application available to anyone (external) or only users that are part of your organization (internal).
If your GCP app needs to go through Google's security verification process, create an **external application**. This option allows users who aren't from your organization to authenticate with your application. When external users authenticate with your application, they're shown an "Unverified application" warning.
Google limits unverified external GCP applications to 100 authenticated accounts. To raise this limit, you need to complete Google's security verification process. For more information, see Google's official [Unverified apps documentation](https://support.google.com/cloud/answer/7454865).
If you're creating a development or production app for internal use only, Nylas recommends you create an **internal application**. Only users who have accounts within your organization (for example, any user with an `@nylas.com` email address) will be able to access the application.
Internal GCP applications allow you to skip Google's verification and security review process. If anyone outside your organization needs to authenticate with your app, you'll need to go through Google's security review.
## Create Google provider auth app
:::success
**Nylas recommends you use separate GCP applications for your production and test environments**. Even small changes on a verified GCP app could trigger a new verification process. Having a separate app for your test environment gives you flexibility to test without interrupting your production users.
:::
1. Go to the [Google Cloud Console Create Project page](https://console.cloud.google.com/projectcreate).
2. Give your project a **name**.
3. Select your project's **Organization** and **Location**.

It might take several minutes for Google to create your project. When the process is finished, Google redirects you to the dashboard and displays a Create Project notification.

## Enable required APIs
You need to enable certain APIs for your Google provider auth app to work with Nylas:
1. From the Google Cloud Platform dashboard, select **APIs and services**.
2. Click **Enable APIs and services**.

3. Search for and enable the following APIs:
- **Gmail API**: Required to read and send messages. Also required for the Threads, Drafts, Folders, and Files endpoints.
- **People API**: Required to use the Contacts endpoints.
- **Admin SDK API**: Optional. Grants access to room information for calendar events.
## Google authentication scopes
You might need to take extra steps to comply with Google's OAuth 2.0 policies and complete their verification process before you can publish your GCP project.
Be sure to request the most restrictive [scopes](/docs/dev-guide/scopes/) that you need for your project. If you request any of [Google's restricted scopes](/docs/provider-guides/google/google-verification-security-assessment-guide/#google-scopes), Google will require your application to complete a security assessment. This could extend your verification timeline significantly, or cause Google to fail your review.
For more information, see Nylas' [Google verification and security assessment guide](/docs/provider-guides/google/google-verification-security-assessment-guide/).
:::warn
**Nylas doesn't allow the all-access `mail.google.com` scope**. This scope grants complete access to all Gmail features. Google automatically rejects verification for applications that include it, and makes you break down the access into individual, more granular scopes to complete verification.
:::
| Google scope URI | Description |
| ---------------------------------------------------------- | ------------------------------------------------------ |
| `https://www.googleapis.com/auth/userinfo.email` | Required Google scope. |
| `https://www.googleapis.com/auth/userinfo.profile` | Required Google scope. |
| `openid` | Required Google scope. |
| `https://www.googleapis.com/auth/gmail.modify` | Read, compose, and send messages from a Gmail account. |
| `https://www.googleapis.com/auth/gmail.readonly` | View messages. |
| `https://www.googleapis.com/auth/gmail.labels` | View and edit Gmail labels. |
| `https://www.googleapis.com/auth/gmail.compose` | Create drafts and send messages. |
| `https://www.googleapis.com/auth/gmail.send` | Send messages. |
| `https://www.googleapis.com/auth/gmail.metadata` | Get message metadata. |
| `https://www.googleapis.com/auth/calendar` | View, create, edit, and delete calendars and events. |
| `https://www.googleapis.com/auth/calendar.readonly` | View calendars and events. |
| `https://www.googleapis.com/auth/calendar.events` | View and edit events on all calendars. |
| `https://www.googleapis.com/auth/calendar.events.readonly` | View events on all calendars. |
:::info
**If your GCP project uses the `gmail.readonly` or `gmail.labels` scopes, you need to [**set up Pub/Sub**](/docs/provider-guides/google/connect-google-pub-sub/)**. This ensures that you get real-time updates from your app.
:::
### Automatically include previously granted scopes
Nylas includes Google's [`include_granted_scopes` feature flag](https://developers.google.com/identity/protocols/oauth2/web-server#obtainingaccesstokens) when authenticating with Google OAuth 2.0. This feature flag tells Google to include any scopes that the user already approved on the specific GCP app (assuming the scopes are still valid). This simplifies the auth process for your users, because they're no longer required to re-select the scopes they already approved when they authenticate again.
## Configure Google OAuth page
You can configure the OAuth page for both [internal](#configure-internal-oauth-page) and [external](#configure-external-oauth-page) GCP applications. This is the page that your users are directed to when they authenticate with your Nylas application.
### Configure internal OAuth page
1. From the Google Cloud Platform dashboard, select **OAuth consent screen**.
2. Choose the **Internal** user type and click **Create**.
3. Fill out the required OAuth consent information and enter `nylas.com` as an **Authorized domain**.
4. Click **Save and continue**.
5. Select **Add or remove scopes**, and add the `.../auth/userinfo.email`, `.../auth/userinfo.profile`, and `openid` scopes.
6. Select the [scopes](#google-authentication-scopes) needed for your application.
7. Review the **Summary** and ensure the information is correct.
### Configure external OAuth page
1. From the Google Cloud Platform dashboard, select **OAuth consent screen**.
2. Choose the **External** user type and click **Create**.
3. Fill out the required OAuth consent information and enter `nylas.com` as an **Authorized domain**.
4. Click **Save and continue**.
5. Select **Add or remove scopes**, and add the `.../auth/userinfo.email`, `.../auth/userinfo.profile`, and `openid` scopes.
6. Select the [scopes](#google-authentication-scopes) needed for your application.
7. Skip the **Test users** step for now.
8. Review the **Summary** and ensure the information is correct.
9. Click **Back to dashboard**.
10. Under **Publishing status**, click **Publish app**.

When you publish your Google provider auth app, you must _authorize_ your users with the Nylas APIs instead of adding them to Google individually as test users. The app is listed as unverified until you complete Google's [security review process](/docs/provider-guides/google/google-verification-security-assessment-guide/).
## Create Google application credentials
You need your GCP app's client ID and client secret to use the application with the Nylas APIs.
1. From the Google Cloud Platform dashboard, select **Credentials**.
2. Click **Create credentials** and choose **OAuth client ID** from the list.

3. Set the **Application type** to **Web application**.
4. Give the application a name.
5. Update the **Authorized redirect URIs**:
- **U.S. Hosted auth**: `https://api.us.nylas.com/v3/connect/callback`
- **E.U. Hosted auth**: `https://api.eu.nylas.com/v3/connect/callback`
- **Custom auth**: Your project's callback URI.
6. Click **Create**. The client ID and secret are displayed in the **OAuth client created** notification.
:::warn
**Be sure to save your client ID and secret somewhere safe, like a secrets manager**. For best practices, see [Store secrets securely](/docs/dev-guide/best-practices/#store-secrets-securely).
:::
## Add Nylas to your Google application
Nylas recommends that you add the Nylas Support team to your GCP app as an application owner. This helps the team diagnose any issues that you might encounter.
1. From the Google Cloud Platform dashboard, open the navigation menu and select **IAM & admin > IAM**.

2. Click **Add**.
3. Add `support@nylas.com` as an owner.
4. Click **Save**.
## Add the "Sign in with Google" button
Your GCP project needs to include a "Sign in with Google" button that meets [Google's branding guidelines](https://developers.google.com/identity/branding-guidelines). This applies to the OAuth flow for both personal Gmail (`@gmail.com`) and Workspace email addresses.
For Hosted authentication, Nylas recommends you do one of the following:
- Configure the OAuth login prompt by setting the `prompt` parameter with `select_provider` or `detect,select_provider`. For more information, see [Configuring the OAuth login prompt](/docs/v3/auth/customize-login-prompt/).
- If you add a `login_hint` that's a personal Gmail or Workspace email address and you don't configure a `prompt` during the Hosted auth flow, the user is immediately directed to the Google OAuth screen, without clicking the "Sign in with Google" button. This can result in delays or failure in verification.
- Use the pre-approved "Sign in with Google" button with the “Connect your account” button or other provider login buttons in your application. For more information, see Google's official [Sign in with Google branding guidelines](https://developers.google.com/identity/branding-guidelines).
For Bring Your Own Authentication, use the pre-approved "Sign in with Google" button with the “Connect your account” button or other provider login buttons in your application.
For more information, see the [Google verification and security assessment guide](/docs/provider-guides/google/google-verification-security-assessment-guide/).
## Add a connector to your Nylas application
:::warn
**If you plan to use the Nylas Email API with Google, you need to [**set up Google Pub/Sub**](/docs/provider-guides/google/connect-google-pub-sub/) before you create a connector**. If you don't plan to use the Nylas Email API with your GCP app (for example, if you're creating a calendar-only project), you can skip this step.
:::
Your Nylas application communicates with external provider auth apps using [connectors](/docs/reference/api/connectors-integrations/). You can create a Google connector by copying the cURL request below and substituting your client ID, secret, and Pub/Sub topic name.
```bash
curl -X POST 'https://api.us.nylas.com/v3/connectors' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"name": "google example",
"provider": "google",
"settings":
{
"client_id": "",
"client_secret": "",
"topic_name": ""
},
"scope": [
"openid",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/calendar",
"https://www.googleapis.com/auth/gmail.compose",
"https://www.googleapis.com/auth/gmail.modify"
]
}'
```
────────────────────────────────────────────────────────────────────────────────
title: "Google verification and security assessment guide"
description: "Complete Google's verification and security assessment processes for your Google Cloud Platform (GCP) application."
source: "https://developer.nylas.com/docs/provider-guides/google/google-verification-security-assessment-guide/"
────────────────────────────────────────────────────────────────────────────────
:::info
**Want to skip verification entirely?** The [Nylas Shared GCP App](/docs/provider-guides/google/shared-gcp-app/) uses a Nylas-owned Google Cloud Platform project that is already verified and has passed the CASA security assessment. You can go to production with Google without completing any of the steps on this page.
:::
Google APIs use the [OAuth 2.0 protocol](https://datatracker.ietf.org/doc/html/rfc6749) for user permissions and consent. If your application accesses Google user data with Google APIs, you might have to take additional steps to comply with Google’s OAuth 2.0 policies and complete the verification process before you publish your application.
In this guide, you’ll learn about the Sign in with Google branding guidelines and Google OAuth verification.
## Sign in with Google branding guidelines
To complete the brand verification process, your application must have the "Sign in with Google" button that meets [Google's branding guidelines](https://developers.google.com/identity/branding-guidelines). This applies to the OAuth flow for both personal Gmail (`@gmail.com`) and Workspace email addresses.
For Hosted authentication, Nylas recommends you do one of the following:
- Configure the OAuth login prompt by setting the `prompt` parameter with `select_provider` or `detect,select_provider`. For more information, see [Configuring the OAuth login prompt](/docs/v3/auth/customize-login-prompt/).
- If you add a `login_hint` that's a personal Gmail or Workspace email address and you don't configure a `prompt` during the Hosted auth flow, the user is immediately directed to the Google OAuth screen, without clicking the "Sign in with Google" button. This can result in delays or failure in verification.
- Use the pre-approved "Sign in with Google" button with the “Connect your account” button or other provider login buttons in your application. For more information, see Google's official [Sign in with Google branding guidelines](https://developers.google.com/identity/branding-guidelines).
For Bring Your Own Authentication, use the pre-approved "Sign in with Google" button with the “Connect your account” button or other provider login buttons in your application.
## Google OAuth verification
:::warn
**The Google verification and security assessment processes can take several weeks or longer**. Be sure to plan your development timeline around this.
:::
If your application accesses Google user data with the Google APIs and requests certain scopes, you might have to complete the Google verification process and a separate security assessment process. The processes that you need to complete depends on whether your application requests [_sensitive_ or _restricted_ scopes](/docs/provider-guides/google/google-verification-security-assessment-guide/#google-scopes).
| Scope type | Required processes | Google policy and requirements |
| ---------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Sensitive | Google verification | Your application must follow [Google’s API Services User Data Policy](https://developers.google.com/terms/api-services-user-data-policy). |
| Restricted | Google verification and security assessment | Your application must follow [Google’s API Services User Data Policy](https://developers.google.com/terms/api-services-user-data-policy) and meet [additional requirements for specific scopes](https://developers.google.com/terms/api-services-user-data-policy#additional_requirements_for_specific_api_scopes). |
- If your app requests one or more sensitive scopes and doesn't meet any of the criteria for an [exception](#exceptions-to-verification-and-security-assessment), you need to complete a **Google verification** process.
- If your app requests one or more restricted scopes and doesn't meet any of the criteria for an [exception](#exceptions-to-verification-and-security-assessment), you need to complete **both Google verification and security assessment** processes. For the security assessment process, Google will assign either Tier 2 or Tier 3 to your app and provide instructions and tools to complete the assessment.
For more information, see [Google's OAuth API verification FAQs](https://support.google.com/cloud/answer/13463817#Verification_Process).
### Google scopes
The following are the Google scopes that Nylas projects use:
| Scope type | Scope | Description | Verification | Security assessment |
| ---------- | -------------------------- | -------------------------------------------------------------------------------------------------------- | ------------ | ------------------- |
| Sensitive | `gmail.send` | Send messages only. No read or modify privileges on mailbox. | ☑️ | — |
| Sensitive | `calendar` | See, edit, share, and permanently delete all calendars you can access using Google Calendar. | ☑️ | — |
| Sensitive | `calendar.readonly` | See and download any calendar you can access using Google Calendar. | ☑️ | — |
| Sensitive | `calendar.events` | See and edit events on all your calendars. | ☑️ | — |
| Sensitive | `calendar.events.readonly` | See events on all your calendars. | ☑️ | — |
| Sensitive | `contacts` | See, edit, download, and permanently delete your contacts. | ☑️ | — |
| Sensitive | `contacts.readonly` | See and download your contacts. | ☑️ | — |
| Sensitive | `contacts.other.readonly` | See and download contacts that are saved in your "Other Contacts". | ☑️ | — |
| Sensitive | `directory.readonly` | See and download your organization's Google Workspace directory. | ☑️ | — |
| Restricted | `gmail.readonly` | Read all resources and their metadata. No write operations. | ☑️ | ☑️ |
| Restricted | `gmail.modify` | All read/write operations except immediate, permanent deletion of threads and messages, bypassing Trash. | ☑️ | ☑️ |
| Restricted | `gmail.compose` | Create, read, update, and delete drafts. Send messages and drafts. | ☑️ | ☑️ |
Nylas projects also use the `gmail.labels` scope, which is neither sensitive or restricted and requires no Google verification or security assessment. The `gmail.labels` scope allows apps to create, read, update, and delete labels.
### Exceptions to verification and security assessment
- Apps that are not shared with anyone else or that access fewer than 100 Gmail accounts
- Apps that are set to "Testing" and not "In production"
- Apps that are configured to work only with internal Google accounts within your organization
- Apps that have been allowed by Google Workspace admins
For more information, see [Google's OAuth API verification FAQs](https://support.google.com/cloud/answer/13463817#Verification_Process).
## Google OAuth verification guide
The Google verification and security assessment processes can be daunting, but our Google OAuth verification guide can help you understand what needs to be done and provide step-by-step instructions on how to do it.
────────────────────────────────────────────────────────────────────────────────
title: "Setting up Google service accounts"
description: "Set up service accounts for your Google application."
source: "https://developer.nylas.com/docs/provider-guides/google/google-workspace-service-accounts/"
────────────────────────────────────────────────────────────────────────────────
A service account is a special type of Google account. It represents a non-human user that needs to authenticate and be authorized to access data in the Google APIs.
:::info
**Service accounts are supported for Google Calendar only**.
:::
This page describes how to set up a service account and authorize users.
## Create a service account
Follow these steps to create a Google service account:
1. From the Google Cloud Platform dashboard, navigate to **IAM & admin > Service Accounts**.
2. Select your project and click **Create service account**.
3. Enter a **name**, **ID**, and **description** for the Service Account.
4. Click **Create and continue**.

5. (Optional) Grant the service account access to your GCP app.
6. (Optional) Grant users access to the service account.
7. Click **Done**.
### (Optional) Create a service account key
If you choose to delegate domain-wide authority, you'll need the client ID for your GCP app. You can access it in two ways:
- Using the [service account key](#optional-create-a-service-account-key), if you made one.

- From the Details page for your GCP app.

After you have your client ID, follow these steps to delegate domain-wide authority:
1. From the Google Cloud Platform dashboard, navigate to **Security > Access and data control > API controls**.
2. In the **Domain wide delegation** pane, select **Manage domain wide delegation**.
3. Click **Add new**.
4. Enter your GCP app's **client ID**.
5. Enter the following **OAuth scopes**:
- `https://www.googleapis.com/auth/userinfo.email`
- `https://www.googleapis.com/auth/userinfo.profile`
- `https://www.googleapis.com/auth/calendar`
- `https://www.googleapis.com/auth/admin.directory.user.readonly`
6. Click **Authorize**.
## Authenticate users with a service account
To authenticate a user with a service account's credentials, make a [Bring Your Own Authentication request](/docs/reference/api/manage-grants/byo_auth/). Pass the user's `email_address`, and include the service account's `credential_id`.
:::info
**You must use a real account, _not_ an alias, when authenticating users with service accounts**. The domain names for the service account and the user's email address must match. For example, if the Service Account credential is `service@example-1.com` and the user's email address is `leyah@example-2.com`, the auth process will fail.
:::
```bash
curl --request POST \
--url 'https://api.us.nylas.com/v3/connect/custom' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"provider": "google",
"settings":
{
"email_address": "user@gmailworkspace.com",
"credential_id": ""
},
"scope": [
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile"
],
"state": "my-state"
}'
```
Currently, you cannot use a service account to bulk authenticate room resources.
────────────────────────────────────────────────────────────────────────────────
title: "Using Google accounts and data with Nylas"
description: "Build and maintain a Google auth app and connector for your Nylas application."
source: "https://developer.nylas.com/docs/provider-guides/google/"
────────────────────────────────────────────────────────────────────────────────
You can create a Google connector in your Nylas application, then use that connector to authenticate your users' Google accounts. This lets your application access their Gmail, Google Calendar, and Google Contacts information using the [OAuth 2.0 protocol](https://auth0.com/intro-to-iam/what-is-oauth-2).
## Set up your Google auth app
First, you need to connect your Nylas application to a Google provider auth app. This lets your users authenticate to your application with their Google accounts, and provides your project access to the data you specify in the Google API. Follow the steps in [Create a Google provider auth app](/docs/provider-guides/google/create-google-app/) to set up a Google Cloud Platform project.
### Use the Nylas Shared GCP Project
Nylas maintains a GCP project that supports all the scopes your application might need. This lets you use Google authentication in your project without having to create a GCP project or go through Google's security review and verification process. This can help accelerate your go-to-market timelines.
For setup instructions and details, see [Using the Nylas Shared GCP App](/docs/provider-guides/google/shared-gcp-app/). To get access, reach out to your Account Manager or [contact our Sales Team](https://www.nylas.com/contact-sales/).
## Google verification and security assessment
:::warn
**The Google verification and security assessment processes can take several weeks or longer**. Be sure to plan your development timeline around this.
:::
You might need to take extra steps to comply with Google's OAuth 2.0 policies and complete their verification process before you can publish your GCP project.
Be sure to request the most restrictive [scopes](/docs/dev-guide/scopes/) that you need for your project. If you request any of [Google's restricted scopes](/docs/provider-guides/google/google-verification-security-assessment-guide/#google-scopes), Google will require your application to complete a security assessment. This could extend your verification timeline significantly, or cause Google to fail your review.
For more information, see Nylas' [Google verification and security assessment guide](/docs/provider-guides/google/google-verification-security-assessment-guide/).
### "Sign in with Google" branding guidelines
Your GCP project needs to include a "Sign in with Google" button that meets [Google's branding guidelines](https://developers.google.com/identity/branding-guidelines). This applies to the OAuth flow for both personal Gmail (`@gmail.com`) and Workspace email addresses.
### Google OAuth verification
When you create your Google Cloud Platform project, you need to list the scopes that your Nylas application will use.
If your application accesses Google user data with the Google APIs and requests certain scopes, you might have to complete the Google verification process and a separate security assessment process. The processes that you need to complete depends on whether your application requests [_sensitive_ or _restricted_ scopes](/docs/provider-guides/google/google-verification-security-assessment-guide/#google-scopes).
| Scope type | Required processes | Google policy and requirements |
| ---------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Sensitive | Google verification | Your application must follow [Google’s API Services User Data Policy](https://developers.google.com/terms/api-services-user-data-policy). |
| Restricted | Google verification and security assessment | Your application must follow [Google’s API Services User Data Policy](https://developers.google.com/terms/api-services-user-data-policy) and meet [additional requirements for specific scopes](https://developers.google.com/terms/api-services-user-data-policy#additional_requirements_for_specific_api_scopes). |
## Google provider limitations
- The Gmail API has a set of usage limits that apply to all requests made from your Nylas application. This includes the number of messages you can send per day. For more information, see Google's official [Usage limits documentation](https://developers.google.com/gmail/api/reference/quota).
- The Google Calendar API has two sets of usage limits: the number of requests your application can make each minute, and the number of requests your application can make _per user_ each minute. For more information, see Google's official [Manage quotas documentation](https://developers.google.com/calendar/api/guides/quota).
- If an attachment file name includes non-ASCII characters (for example, accented characters like `ü`), Google can't detect its content type. Because of this, Nylas returns an empty `content_type` field.
### One-click unsubscribe headers
As of February 2024, Google requires that users who send more than 5,000 messages per day to Gmail email addresses include one-click unsubscribe headers in their marketing and subscribed messages (see Google’s official [Email sender guidelines](https://support.google.com/a/answer/81126?visit_id=638454429489933730-1375591047&rd=1#subscriptions)). This is along with the visible unsubscribe links that must be in the body content of all marketing and subscribed messages.
To set up one-click unsubscribe headers using Nylas, include the `custom_headers` object in your [Send Message](/docs/reference/api/messages/send-message/) or [Create Draft](/docs/reference/api/drafts/post-draft/) request. This object accepts a set of key-value pairs, each of which represents the header’s `name` and its `value`. You must include the following headers:
- `List-Unsubscribe-Post`: `List-Unsubscribe=One-Click`
- `List-Unsubscribe`: The unsubscribe link (for example, a `mailto` link that uses the user’s email address, or a link to your list management software).
```json
"custom_headers":[
{
"name": "List-Unsubscribe-Post",
"value": "List-Unsubscribe=One-Click"
},
{
"name": "List-Unsubscribe",
"value": ", "
}
]
```
## What's next
- [List Gmail emails from the CLI](https://cli.nylas.com/guides/list-gmail-emails) - Read and search Gmail messages from the terminal after setup
────────────────────────────────────────────────────────────────────────────────
title: "Working with delegated mailboxes and Google Groups"
description: "How to work with delegated mailboxes and Google Groups in Nylas."
source: "https://developer.nylas.com/docs/provider-guides/google/shared-accounts/"
────────────────────────────────────────────────────────────────────────────────
Google doesn't have traditional "shared mailboxes" like other email providers. Instead, Google Workspace offers two different ways to share email access among users: [**delegated mailboxes**](https://support.google.com/mail/answer/138350?hl=en) and [**Google Groups**](https://support.google.com/groups/answer/46601?hl=en&ref_topic=9216&sjid=17169568418520337759-NC).
**Delegated mailboxes** are regular Google accounts whose account owner has granted access permissions to other users. Users with delegated permissions can read, send, and manage messages on behalf of the mailbox owner.
**Google Groups** are distribution lists that can receive messages at a shared address (for example, `support@example.com`). Multiple users can join the group and receive messages sent to the group email address.
## Authenticate delegated mailbox
You can authenticate delegated mailboxes to Nylas just like any other Google account, using the mailbox owner's credentials. The mailbox owner must complete the authentication process — a delegate can't authenticate the mailbox using their credentials.
For more information, see our [authentication documentation](/docs/v3/auth/).
## Use Google Groups with Nylas
:::warn
**Because Google Groups aren't actual user accounts, you can't authenticate them directly**.
:::
If you use Google Groups for access to shared messages, you have two options for integrating with Nylas:
- **Authenticate individual group members**: Every user who needs access to the Group can authenticate their Google account with Nylas. They'll receive messages sent to the Group in their personal mailbox.
- **Create a dedicated Google account**: You can convert the Group to an individual Google account, [set up delegation](https://support.google.com/mail/answer/138350?hl=en) for users who need access, then [authenticate the account with Nylas].
────────────────────────────────────────────────────────────────────────────────
title: "Using the Nylas Shared GCP App"
description: "Use the Nylas Shared Google Cloud Platform (GCP) project to skip Google's OAuth verification and security assessment process and get to production faster."
source: "https://developer.nylas.com/docs/provider-guides/google/shared-gcp-app/"
────────────────────────────────────────────────────────────────────────────────
Google requires applications that access Gmail with restricted scopes to complete an [OAuth verification and CASA security assessment](/docs/provider-guides/google/google-verification-security-assessment-guide/) before going to production. This process can take several weeks, and for many teams it becomes the single biggest delay in shipping a Nylas integration.
The Nylas Shared GCP App removes that bottleneck. Nylas maintains a fully verified Google Cloud Platform project that has already passed Google's Tier 3 CASA assessment. When you enable it, your users authenticate through Nylas' verified OAuth application instead of one you build and verify yourself.
## Why use the Shared GCP App
### Skip the CASA security assessment
If your application uses restricted Gmail scopes like `gmail.modify` or `gmail.compose`, Google requires a [CASA (Cloud Application Security Assessment)](https://appdefensealliance.dev/casa) before you can go to production. This is a Tier 2 or Tier 3 security audit conducted by a [Google-authorized third-party assessor](https://appdefensealliance.dev/casa/casa-assessors), and the process involves:
- **Hiring an authorized assessor** to audit your application's security controls
- **Remediating any findings** before Google approves your application
- **Repeating the assessment annually** to maintain your verified status
The Nylas Shared GCP App has already completed the most rigorous Tier 3 CASA assessment. Nylas handles every annual re-assessment going forward, so your team never has to engage a security assessor, prepare for an audit, or track renewal deadlines.
### Skip Google OAuth verification
Even without restricted scopes, Google requires OAuth verification for any application using sensitive scopes (like `calendar` or `contacts`). This includes preparing a demo video, configuring branding requirements, and waiting for Google to review your submission. The verification process alone can take several weeks.
The Shared GCP App is already fully verified for all Google scopes that Nylas supports. You skip the entire process.
### Go to production faster
With the Shared GCP App, you can go live with Google authentication the same day you enable it. There is no GCP project to create, no APIs to enable, no OAuth consent screen to configure, and no verification to wait for.
### Reduce ongoing maintenance
Owning a GCP project means managing OAuth credentials, monitoring Google's policy changes, and maintaining your verified status year over year. The Shared GCP App offloads all of this to Nylas.
If you need whitelabeled OAuth (your company name on the consent screen instead of "Nylas") or credential isolation for compliance, you should [create your own Google auth app](/docs/provider-guides/google/create-google-app/) instead.
## Before you begin
The Shared GCP App is available on Contract plans. It is not available on Sandbox or pay-as-you-go plans. To get access, reach out to your Account Manager or [contact the Nylas Sales team](https://www.nylas.com/contact-sales/). Once your contract includes the Shared GCP App, Nylas enables the feature for your organization.
After it is enabled, it can take a few minutes before the option appears in your Nylas Dashboard.
## Enable the Shared GCP App on a connector
:::warn
**If you already have users authenticated through your own GCP project**, enabling the Shared GCP App means those users will need to re-authenticate. Make sure you have a re-authentication flow in your application before you enable this. See [Migrate existing users to the Shared GCP App](#migrate-existing-users-to-the-shared-gcp-app) for details.
:::
Once the feature is enabled for your organization, you can turn it on when you create or edit a Google connector in the Nylas Dashboard.
1. Log in to the [Nylas Dashboard](https://dashboard-v3.nylas.com).
2. Select the application where you want to use the Shared GCP App. The application can be any environment type (Development, Staging, or Production).
3. Navigate to **Connectors** and either create a new Google connector or edit your existing one.
4. In the Google connector settings, you will see a toggle to use the **Nylas Google OAuth Credentials**. The toggle appears greyed out by default.
5. Click the toggle to enable it, then click **Save**.
The following video walks through the steps to enable the Shared GCP App in the Nylas Dashboard:
:::info
**The toggle may look greyed out even after the feature is enabled for your organization.** This is the default "off" state. Click the toggle to switch it on, then save your connector settings.
:::
After you save, Nylas configures the Google connector to use the Shared GCP App credentials. Your users will see "Nylas" on the OAuth consent screen when they authenticate.
## Select your Google scopes
When using the Shared GCP App, you still choose which Google scopes your application requests. Select only the scopes your application actually needs.
:::info
**Use parent scopes when possible.** For example, selecting the `calendar` parent scope covers both read and write access, so you don't need to also select `calendar.readonly`. Using parent scopes simplifies the consent screen and reduces the number of permissions your users have to review and approve.
:::
For the full list of available scopes, see [Google authentication scopes](/docs/provider-guides/google/create-google-app/#google-authentication-scopes).
## How it works
When you enable the Shared GCP App, Nylas configures your Google connector to use credentials from a Nylas-owned, Nylas-verified Google Cloud Platform project. Here's what that means:
| Component | Who owns it |
| --------------------------------------- | ---------------------------- |
| Google Cloud Platform project | Nylas |
| OAuth consent screen and branding | Nylas |
| OAuth client ID and client secret | Nylas |
| Google verification and CASA assessment | Nylas (already completed) |
| Token storage and refresh | Nylas |
| Scope selection | You (in the Nylas Dashboard) |
| API integration and data access | You (through the Nylas APIs) |
Your users go through a standard OAuth flow. The only visible difference is that the consent screen shows "Nylas" as the application name rather than your own branding.
## Migrate existing users to the Shared GCP App
If you already have users authenticated through your own Google Cloud Platform project and you switch to the Shared GCP App, those users need to re-authenticate. Nylas cannot automatically migrate OAuth tokens between different GCP projects because the tokens are tied to the specific OAuth client that issued them.
To migrate your users:
1. Enable the Shared GCP App on your Google connector (see [above](#enable-the-shared-gcp-app-on-a-connector)).
2. Prompt your users to re-authenticate when they next access your application. This connects them to the Shared GCP App.
3. After re-authentication, Nylas issues new grant IDs for the migrated users. Update your application to use the new grant IDs.
Your existing API calls remain the same once the new authentication is in place. The only change is the grant IDs associated with each user.
:::info
**You don't have to migrate all users at once.** You can use [multiple provider applications](/docs/v3/auth/using-multiple-provider-applications/) to run your own GCP credentials alongside the Shared GCP App. This lets you migrate users gradually while keeping both configurations active.
:::
## Switch to your own GCP project later
You can switch from the Shared GCP App to your own Google Cloud Platform project at any time. Create your own [Google auth app](/docs/provider-guides/google/create-google-app/), then update your connector with your own credentials using the [Connector Credentials API](/docs/v3/auth/using-multiple-provider-applications/). Your existing grants continue to work, and users are migrated to the new credentials when they next re-authenticate.
## What's next
- [Google authentication scopes](/docs/provider-guides/google/create-google-app/#google-authentication-scopes) - Review available scopes for your application
- [Using multiple provider applications](/docs/v3/auth/using-multiple-provider-applications/) - Use your own GCP credentials alongside the Shared GCP App
- [Google verification and security assessment guide](/docs/provider-guides/google/google-verification-security-assessment-guide/) - Understand what the Shared GCP App replaces
────────────────────────────────────────────────────────────────────────────────
title: "Authenticating iCloud accounts with Nylas"
description: "Use the Nylas iCloud connector to connect to iCloud accounts."
source: "https://developer.nylas.com/docs/provider-guides/icloud/"
────────────────────────────────────────────────────────────────────────────────
You can use the Nylas iCloud connector to connect to iCloud accounts, so you can use both the Nylas Email and Calendar APIs. iCloud provides an IMAP email service, and a WebDav/CalDav calendar service.
:::warn
**You can allow iCloud users to log in using generic IMAP credentials, but calendar features are not available if they use IMAP**. You must both create an iCloud connector and use it for user authentication to get access to a user's iCloud calendar.
:::
Apple requires an [app-specific password](https://support.apple.com/en-us/HT204397) when you authenticate iCloud accounts. For more information, see the [app passwords documentation](/docs/provider-guides/app-passwords/).
## Before you begin
Before you start authenticating iCloud accounts, make sure you understand [how Nylas authenticates](/docs/v3/auth/). You also need to create at least one Nylas application.
## Add an iCloud connector
1. In the Nylas Dashboard, navigate to the application you want to use iCloud with.
2. Click **Connectors** in the left navigation.
3. Find the iCloud item, and click the plus icon (**+**).
No further connector configuration is required, and iCloud doesn't require that you request scopes.
## Have the user create an app password
Next, direct your user to the [Apple ID log in page](https://appleid.apple.com/account/home) and have them log in.
Have them follow the instructions to [generate an app-specific password for iCloud](https://support.apple.com/en-us/102654). They will use this password when authenticating with your app instead of using their main account password.
:::info
🔍 **This step must be done manually by the user**, as Apple doesn't provide an API for generating app passwords.
:::
## iCloud Hosted authentication
To authenticate your users' iCloud accounts using Hosted auth, follow these steps:
1. Direct your user to [create an iCloud app password](#have-the-user-create-an-app-password). This step is required.
2. Redirect the user to the Nylas Hosted auth login page by making a [`GET /v3/connect/auth` request](/docs/reference/api/authentication-apis/get_oauth2_flow/).
3. Have the user log in using their iCloud account and the app-specific password they created.
4. Complete the auth flow by [exchanging a token with the provider](/docs/reference/api/authentication-apis/exchange_oauth2_token/). The API response contains the grant ID for the user, which you can use query for their data.
## iCloud Bring Your Own Authentication
To authenticate users with iCloud accounts using Bring Your Own (BYO) Authentication, follow these steps:
1. Direct your user to [create an iCloud app password](#have-the-user-create-an-app-password). This step is required.
2. [Create your custom login page](/docs/v3/auth/bring-your-own-authentication/#create-a-bring-your-own-authentication-login-page) as you normally would.
3. Make a [BYO Authentication request](/docs/reference/api/manage-grants/byo_auth/) and provide the user's app-specific `username` and `password`.
```bash {7-8}
curl -X POST 'https://api.us.nylas.com/v3/connect/custom' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"provider": "icloud",
"settings": {
"username": "",
"password": ""
}
}'
```
Nylas returns a grant ID that you then use in other queries for the user's data.
## iCloud provider limitations
By default, Nylas stores messages on iCloud and IMAP providers in a cache for 90 days after they're received or created. You can access messages older than 90 days by setting the `query_imap` parameter to `true` when you make a request to the following endpoints: [Get Message](/docs/reference/api/messages/get-messages-id/), [Get all Messages](/docs/reference/api/messages/get-messages/), [Get Draft](/docs/reference/api/drafts/get-draft-id/), [Get all Drafts](/docs/reference/api/drafts/get-drafts/), and the [Attachments endpoints](/docs/reference/api/attachments/). This directly queries the IMAP server instead of Nylas' cache.
Nylas doesn't send webhook notifications for changes to messages that are older than 90 days.
### iCloud rate limits
For iCloud, there are several rate limits you should keep in mind:
- You can send **1,000 messages per day**.
- You can send messages to **1,000 recipients per day**.
- You can include up to **500 recipients per message**.
- You can send messages up to **20MB in size**.
For more information, see the [official Apple documentation](https://support.apple.com/en-gb/102198).
## What's next
- [List iCloud Mail from the CLI](https://cli.nylas.com/guides/list-icloud-emails) - Read and filter iCloud messages from the terminal
────────────────────────────────────────────────────────────────────────────────
title: "Using IMAP accounts and data with Nylas"
description: "Work with IMAP accounts and data in Nylas."
source: "https://developer.nylas.com/docs/provider-guides/imap/"
────────────────────────────────────────────────────────────────────────────────
IMAP (the [Internet Message Access Protocol](https://www.rfc-editor.org/rfc/rfc9051.html)) is one of the foundational protocols of the internet age. It's still commonly used both by small private email providers and large ones such as AOL, Yahoo, and iCloud.
When you use Nylas to connect to a user's IMAP provider, Nylas uses IMAP to get and monitor for new messages, and uses SMTP (the [Simple Mail Transfer Protocol](https://www.rfc-editor.org/rfc/rfc5321.html)) to actually _send_ emails. Nylas doesn't support calendars for standard IMAP accounts.
:::success
**Nylas also offers connectors for Yahoo, Exchange on-prem, and iCloud accounts**. For more information, see the [Yahoo authentication guide](/docs/provider-guides/yahoo-authentication/), the [Exchange on-prem guide](/docs/provider-guides/exchange-on-prem/), and the [iCloud auth guide](/docs/provider-guides/icloud/).
:::
## How Nylas works with IMAP
When a user authorizes a connection to Nylas, the Nylas servers begin syncing their mailboxes and the last 90 days of email history. You don't receive webhook notifications for historical messages in Nylas.
:::info
**When an IMAP account connects to Nylas, Nylas synchronizes and stores messages from the past 90 days in a cache for faster access**. Nylas uses a rolling 90-day retention period for IMAP messages and deletes messages after that period. You can still retrieve older messages by [querying the provider directly](/docs/reference/api/messages/).
:::
Nylas also makes two low-bandwidth "[IMAP idle](https://www.rfc-editor.org/rfc/rfc2177)" connections, similar to a heartbeat, to the user's IMAP provider when they connect. These connections listen for changes to the Inbox and Sent folders. Nylas also makes other short-lived connections to download new or changed messages, and to modify folders or their contents. These connections close before Nylas returns an API response.
See [Create grants with IMAP authentication](/docs/v3/auth/imap/) for information on setting up IMAP auth and creating grants for your users.
Nylas doesn't generate an "Emailed Events" calendar for IMAP accounts, and IMAP accounts don't have calendars natively. More specific connectors are available for [Yahoo](/docs/provider-guides/yahoo-authentication/), [Exchange on-prem](/docs/provider-guides/exchange-on-prem/), and [iCloud](/docs/provider-guides/icloud/) if you need access to an account's calendar.
### Use `query_imap` to access older messages
You can access messages older than 90 days by setting the `query_imap` parameter to `true` when you make a request to the following endpoints: [Get Message](/docs/reference/api/messages/get-messages-id/), [Get all Messages](/docs/reference/api/messages/get-messages/), [Get Draft](/docs/reference/api/drafts/get-draft-id/), [Get all Drafts](/docs/reference/api/drafts/get-drafts/), and the [Attachments endpoints](/docs/reference/api/attachments/). This directly queries the IMAP server instead of Nylas' cache.
:::warn
**Requests that include the `query_imap` parameter might take longer to complete because they're querying the IMAP server directly**. Be sure to consider any [rate limits](/docs/dev-guide/platform/rate-limits/) or performance implications for your project when using this parameter.
:::
## Static IP support for IMAP accounts
Some email servers in secure environments only accept connections and data from a known list of IP addresses. When you add static IP support to your plan, Nylas uses only a [specific set of static IP addresses](/docs/dev-guide/platform/static-ips/) when authenticating and connecting your project's users.
Static IP routing is currently available for IMAP and Exchange on-prem servers only.
## IMAP provider limitations
You should keep the following limitations in mind when using Nylas to work with IMAP providers:
- Nylas, and the Nylas APIs, are subject to the throughput and traffic limitations configured by each provider. This means that — especially for smaller providers — their availability can negatively affect the freshness, completeness, and availability of data in the Nylas systems. It also means that excessive API requests might trigger [rate limiting](#provider-rate-limits) from the provider.
- Attachment sizes are subject to individual providers' file size limits.
- If the provider has high latency, or it can't support IMAP idle connections, webhook notifications about events on the provider are delayed.
- Messages stored in different folders might experience different webhook latency because of provider limitations.
- Messages must be encoded using UTF-8 or ASCII. Other encodings are _not_ supported, and they might not be retrievable or might appear with an empty body.
- All messages must conform to the [Internet Message Format (IMF)](https://datatracker.ietf.org/doc/html/rfc5322), and must have the `Message-ID` and `Reference` fields at minimum. Nylas ignores malformed messages.
- If you have email accounts on an on-premises Microsoft Exchange server, you might want to authenticate them as IMAP grants. To do so, your server must be configured to accept IMAP and SMTP connections, and must support either the `PLAIN` (recommended) or `LOGIN` authentication scheme.
- When you use the `search_query_native` query parameter to [list messages](/docs/reference/api/messages/get-messages/), the search results returned might not be what you expect due to individual provider limitations. Some examples are:
- Yahoo IMAP search doesn't support `NOT` syntax. The search results returned might still contain the messages you want to exclude.
- Microsoft Exchange IMAP doesn't support searching by the `BCC` field. The search results returned will not contain any results that meet your `BCC` query.
### Provider rate limits
In most cases, rate limiting for IMAP connections is configured by your administrator. For some larger providers, however, these limits are set by default.
For iCloud, there are several limits you should keep in mind:
- You can send **1,000 messages per day**.
- You can send messages to **1,000 recipients per day**.
- You can include up to **500 recipients per message**.
- You can send messages up to **20MB in size**.
For more information, see the [official Apple documentation](https://support.apple.com/en-gb/102198).
Yahoo doesn't publicize its sending limits for messages. If you encounter a rate limit notification, you must wait until the limit expires to send messages. Usually, the duration of the limit is included in the notification. For more information, see the [official Yahoo documentation](https://help.yahoo.com/kb/limits-sending-email-yahoo-mail-sln3353.html).
## UIDVALIDITY for IMAP providers
IMAP providers use the `UID` field as an identifier for messages in a folder. Technically, `UID`s should not change, but this is not always the case because of the mechanics of IMAP providers.
Providers use a `UIDVALIDITY` field that is updated to indicate that a folder's `UID` has been changed. Nylas checks the `UIDVALIDITY` field every five minutes. When Nylas detects that the field changed, it removes all cached folder `UID`s associated with the grant and re-indexes them.
Because of provider latency, the re-indexing process can take a long time. During the process, Nylas might return inconsistent or stale information.
:::warn
IMAP providers that are unable to provide reasonable response times during a `UIDVALIDITY` re-index are considered not supported by Nylas.
:::
Incorrectly configured IMAP providers might return a different `UIDVALIDITY` value for every session, which makes it impossible for Nylas to sync data consistently. See [Troubleshoot `UIDVALIDITY` errors](/docs/provider-guides/imap/troubleshooting/#troubleshoot-uidvalidity-errors) for more information.
## Contact data for IMAP and iCloud
:::info
**By default, the Nylas Contacts API and all [`contact.*` notifications](/docs/reference/notifications/#contact-notifications) are disabled for IMAP and iCloud grants**. If you have a contract with us, [contact Nylas Support](/docs/support/#contact-nylas-support) to enable these notifications for IMAP and iCloud grants.
:::
Because IMAP is an email protocol, you can't retrieve contact information directly from IMAP servers. You can infer it from the name-email address pairs in email headers, however.
```http
From: "Nylas"
To: "Leyah Miller"
CC: "Kaveh"
BCC: Nyla
Reply-To: "Nylas Support"
```
Nylas parses six contacts from this example, and adds them to the user's contacts list with the `inbox` source. You can then access these contacts using the Nylas API.
Nylas supports iCloud contacts in the same way as other IMAP providers. It parses Contact objects from messages, instead of from iCloud directly.
## What's next
- [List IMAP emails from the terminal](https://cli.nylas.com/guides/list-imap-emails) - Read and export IMAP messages using the Nylas CLI
────────────────────────────────────────────────────────────────────────────────
title: "Troubleshooting IMAP configuration"
description: "Troubleshoot issues that you might encounter when working with IMAP accounts in Nylas."
source: "https://developer.nylas.com/docs/provider-guides/imap/troubleshooting/"
────────────────────────────────────────────────────────────────────────────────
This page describes common issues you might encounter when using IMAP accounts with Nylas and how to troubleshoot them.
## Passwords and character encoding
Nylas currently can't authenticate an IMAP account if its password contains characters that are not in the [ASCII character encoding](https://en.wikipedia.org/wiki/ASCII). If you encounter an error during authentication, check if the account's password contains characters outside the ASCII range. If it does, advise the user to update their password.
## Troubleshoot `UIDVALIDITY` errors
When syncing messages with a provider, Nylas requires a persistent unique identifier across sessions. This ensures data remains consistent and up-to-date. When Nylas syncs an IMAP account, it uses two important identifiers to link the locally cached messages with those on the IMAP server:
- [`UID`](https://www.rfc-editor.org/rfc/rfc3501#section-2.3.1.1)
- [`UIDVALIDITY`](https://www.rfc-editor.org/rfc/rfc3501#section-2.3.1.1)
If any `UID`s changed between sessions, the provider uses the `UIDVALIDITY` value to signal that you need to clear your cache and look for the new `UID`s.
:::warn
**For misconfigured providers, the `UIDVALIDITY` value might change with every session**. Nylas uses several concurrent sessions to monitor IMAP accounts, and if each one has a different set of `UID`s, maintaining data consistency is impossible. In these cases, Nylas stops syncing and presents a ["Stopped due to too many `UIDVALIDITY` resyncs" error](#error-stopped-due-to-too-many-uidvalidity-resyncs).
:::
### Error: Stopped due to too many `UIDVALIDITY` resyncs
> Resynced more than MAX_UIDINVALID_RESYNCS in a row. Stopping sync.
If an account is in a Stopped state and the mailsync logs return the error above, this indicates that Nylas stopped syncing the account because of inconsistent `UIDVALIDITY` values between sessions. Because Nylas syncs across multiple sessions for an account, Nylas can't link IMAP `UID`s if the `UIDVALIDITY` value changes constantly.
:::error
**Servers with inconsistent `UIDVALIDITY` are not supported until they adhere to the standards set forth in [**the RFC standard document**](https://www.rfc-editor.org/rfc/rfc3501#section-2.3.1.1)**. Nylas cannot work around the issue.
:::
### `UIDVALIDITY` and empty folders
In some cases, the `UIDVALIDITY` error is triggered on folders that contain no messages (and so have no `UIDVALIDITY` values). If this happens, the user can either...
- Delete any empty folders.
- Add at least one message to every empty folder and allow their account to resync.
### `UIDVALIDITY` and Amazon WorkMail
If you connected an Amazon WorkMail account to Nylas using IMAP, your account might be in a Stopped state and you might find the following error in the mailsync logs.
> Resynced more than MAX_UIDINVALID_RESYNCS in a row. Stopping sync.
The error message indicates that the email server doesn't maintain consistent `UIDVALIDITY` values, and is therefore incompatible with Nylas.
You might be able to solve this issue by authenticating your Amazon WorkMail account using [Microsoft Exchange's advanced login settings](/docs/provider-guides/exchange-on-prem/#log-in-using-advanced-settings) and specifying one of the following server addresses, depending on your account region:
- `mobile.mail.eu-west-1.awsapps.com`
- `mobile.mail.us-west-2.awsapps.com`
- `mobile.mail.us-east-1.awsapps.com`
────────────────────────────────────────────────────────────────────────────────
title: "Integrating providers with Nylas"
description: "Connect your Nylas application to email and calendar providers."
source: "https://developer.nylas.com/docs/provider-guides/"
────────────────────────────────────────────────────────────────────────────────
Nylas supports a number of common providers that you can integrate into your project. After you [set up your authentication flow](/docs/v3/auth/#set-up-authentication), your users can authenticate with one of the providers you have a connector for.
## Supported providers
Nylas supports the following providers:
- [Google](/docs/provider-guides/google/)
- [iCloud](/docs/provider-guides/icloud/)
- [IMAP](/docs/provider-guides/imap/)
- [Microsoft](/docs/provider-guides/microsoft/)
- [Microsoft Exchange (Exchange Web Services)](/docs/provider-guides/exchange-on-prem/)
- [Virtual calendars](/docs/v3/calendar/virtual-calendars/)
- [Yahoo](/docs/provider-guides/yahoo-authentication/)
- [Zoom Meetings](/docs/provider-guides/zoom-meetings/)
:::warn
**Nylas has limited support for Microsoft Exchange**. You should use it as a provider only if you have users who haven't upgraded to [Microsoft modern authentication](https://learn.microsoft.com/en-us/exchange/plan-and-deploy/post-installation-tasks/enable-modern-auth-in-exchange-server-on-premises?view=exchserver-2019).
:::
────────────────────────────────────────────────────────────────────────────────
title: "Configuring Microsoft admin approval"
description: "Adjust your user settings or API permissions to control how users authenticate against your application."
source: "https://developer.nylas.com/docs/provider-guides/microsoft/admin-approval/"
────────────────────────────────────────────────────────────────────────────────
:::error
**As of November 20, 2020, Microsoft requires you to be a verified publisher, otherwise your users are presented with an error**. You must complete the verification process before you change your user settings. For more information, see Microsoft's official [Publisher verification guide](https://learn.microsoft.com/en-us/entra/identity-platform/publisher-verification-overview) and Nylas' [Microsoft verification guide](/docs/provider-guides/microsoft/verification-guide/). Keep in mind that a verified publisher is _not_ the same as a verified domain — you'll need to go through both steps.
:::
Microsoft allows you to adjust your user settings and API permissions to control how users authenticate against your application. This page describes the settings and Nylas' recommended configuration.
## Require admin approval to authenticate
You can control whether users can authenticate themselves against your Nylas application, or an administrator needs to approve their authentication attempt.
1. From the Microsoft Entra admin center, search for **User consent settings** and navigate to the resulting page.
2. Select **Allow user consent for apps from verified publishers, for selected permissions**.
3. Save your changes.
## Grant admin approval to authenticate
Some Microsoft applications require administrator approval before users authenticate against them. If a user tries to auth with an application and its admin hasn't granted their consent, Microsoft displays a notification that prompts them to either continue without permission, or log in as an admin and grant permission.

There are two ways administrators can grant permissions:
- Log in to the Microsoft Entra admin center and update the **Admin consent requests** settings.
- Set **Users can request admin consent to apps they are unable to consent to** to **Yes**.
- Configure the **Consent request expires after** time.

- Create a session and sign in to the application as an admin to grant permission.
## Authorize an application as an administrator
As an administrator, you can authenticate users to your application on their behalf. In some cases, users might not be able to authenticate without permission from an administrator or the company. When this happens, users can submit approval requests from the "Approval required" notification:
1. The user enters their reason for requesting access and clicks **Request approval**.
2. Microsoft emails the administrator to notify them that a user has requested approval.
3. The administrator logs in to the Microsoft Entra admin center and navigates to their **Admin consent requests**.
4. The administrator reviews their pending requests and either grants or denies access.
After the email administrator approves their request, the user can restart the authentication process and connect their account to Nylas.
## Grant admin approval for API permissions
For certain Nylas features, the Microsoft API permissions that Nylas requires need approval from an administrator. For example, the `Place.Read.All` permission required an administrator to grant their approval.
To grant admin consent for API permissions, follow these steps:
1. Log in to the Microsoft Entra admin center and select **Applications > Enterprise applications** in the left navigation.
2. Select the application you want to work with.
3. Choose **Permissions** in the left navigation.
4. Follow the steps on the page to grant admin consent.

────────────────────────────────────────────────────────────────────────────────
title: "Authenticating Microsoft accounts with Nylas"
description: "Authenticate Microsoft accounts with Nylas using Hosted and Bring Your Own Authentication."
source: "https://developer.nylas.com/docs/provider-guides/microsoft/authentication/"
────────────────────────────────────────────────────────────────────────────────
After you [create an Azure application](/docs/provider-guides/microsoft/create-azure-app/), your next step is deciding how to authenticate your users to Nylas.
:::info
**Nylas Hosted Auth follows the OAuth 2.0 flow, and Nylas takes care of the underlying authentication process**. To set up your auth flow, you must first configure Hosted Auth using either an [API key](/docs/v3/auth/hosted-oauth-apikey/) or an [access token](/docs/v3/auth/hosted-oauth-accesstoken/).
:::
## Before you begin
Before you choose an authentication method, Nylas recommends you read the following documentation:
- [Hosted Authentication with an API key](/docs/v3/auth/hosted-oauth-apikey/)
- [Hosted Authentication with an access token](/docs/v3/auth/hosted-oauth-accesstoken/)
- [Bring Your Own Authentication](/docs/v3/auth/bring-your-own-authentication/)
You also need to complete the following prerequisites for your production application:
- [Complete Microsoft's domain verification process](https://docs.microsoft.com/en-us/microsoft-365/admin/setup/add-domain?view=o365-worldwide).
- [Become a Microsoft verified publisher](https://docs.microsoft.com/en-us/azure/active-directory/develop/publisher-verification-overview).
### Authenticate Exchange accounts
:::warn
**Microsoft [**announced the retirement of Exchange Web Services**](https://techcommunity.microsoft.com/t5/exchange-team-blog/retirement-of-exchange-web-services-in-exchange-online/ba-p/3924440) in 2022 and [**strongly recommended that all users migrate to use Microsoft Graph**](https://techcommunity.microsoft.com/t5/exchange-team-blog/ews-exchange-web-services-to-microsoft-graph-migration-guide/ba-p/3957158)**. Users on Exchange Online have already been migrated.
:::
Nylas includes an EWS connector that you can use to authenticate accounts hosted on Exchange on-premises servers. Other types of Exchange accounts must upgrade to use Microsoft Graph scopes, then authenticate using the Microsoft connector.
For more information, see [Authenticate Exchange on-prem servers with Nylas](/docs/provider-guides/exchange-on-prem/).
### Authenticate Microsoft shared mailboxes
[Microsoft's shared mailboxes](https://learn.microsoft.com/en-us/microsoft-365/admin/email/about-shared-mailboxes?view=o365-worldwide) are individual mailboxes that multiple users can access. Each shared mailbox has its own email address and password.
:::info
**Shared mailboxes might not have a set password when they're created**. In this case, you'll need to use Microsoft's password reset process to create a password before you can authenticate the shared mailbox with Nylas.
:::
After you set a password for the shared mailbox, you can authenticate it with Nylas like any other Microsoft account. It functions as a regular user account with a grant in your Nylas integration.
## Set up Bring Your Own Authentication
Microsoft supports [modern authentication/OAuth](https://learn.microsoft.com/en-us/microsoft-365/enterprise/hybrid-modern-auth-overview?view=o365-worldwide#what-is-modern-authentication) only. The flow follows these basic steps:
1. Your Nylas application completes the OAuth process with Microsoft and receives a `refresh_token` for the user's account.
2. Your application makes a [Bring Your Own Authentication request](/docs/reference/api/manage-grants/byo_auth/) to Nylas using the user's `refresh_token`.
```bash
curl --request POST
--url 'https://api.us.nylas.com/v3/connect/custom' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer '\
--header 'Content-Type: application/json' \
--data '{
"provider": "microsoft",
"settings": {
"refresh_token":""
},
"state": ""
}'
```
3. Nylas creates a grant for the user and returns its details.
────────────────────────────────────────────────────────────────────────────────
title: "Creating an Azure auth app"
description: "Create and configure a Microsoft Azure auth app."
source: "https://developer.nylas.com/docs/provider-guides/microsoft/create-azure-app/"
────────────────────────────────────────────────────────────────────────────────
This page explains how to create and configure a Microsoft Azure OAuth application to use with Nylas.
## Calculating scopes
If you're authenticating with Microsoft, you must use Microsoft Graph scopes (also sometimes called "feature permissions" or "API permissions").
If you're starting a new project, Nylas recommends you make a list of the APIs your project uses, then compile a list of the scopes you need using the [scopes documentation](/docs/dev-guide/scopes/). It's a security best practice to only request scopes that you actually use, however for development purposes, you might choose broader scopes than your production app needs.
You'll add these scopes to your Azure auth app's Entra ID system (previously "Azure ID") in the [Enable required APIs](#enable-required-apis) step below. For more information, see Microsoft's official [Configure Azure AD Graph permissions for an app registration guide](https://learn.microsoft.com/en-us/graph/migrate-azure-ad-graph-configure-permissions).
As you work with Nylas, you might need to update your scopes for specific APIs (for example, you might want Write permissions for your users' messages). You can find API-specific scope information throughout this documentation:
- [Email API scopes](/docs/dev-guide/scopes/#email-api-scopes)
- [Calendar API scopes](/docs/dev-guide/scopes/#calendar-and-events-api-scopes)
- [Scheduler API scopes](/docs/dev-guide/scopes/#scheduler-api-scopes)
- [Contacts API scopes](/docs/dev-guide/scopes/#contacts-api-scopes)
- [Notification scopes](/docs/dev-guide/scopes/)
## Create an Azure OAuth application
:::success
**If you don't already have one, [**create your free Microsoft Azure account**](https://azure.microsoft.com/en-us/free/)**. You'll use this account to create the Microsoft developer application that you use to authenticate users using OAuth with Nylas.
:::
First, you need to create an Azure OAuth app:
1. In the Microsoft Azure Portal, search for and click **App registrations**, then **New registration**.
2. Give your application a name. This name will be visible to your users.
3. Set the audience for the app to **Accounts in my organizational directory and personal Microsoft accounts**. This allows your user to log in using any Microsoft account.
If you're building an internal application (used only by members of your organization), you can restrict access to internal accounts only by setting the audience to **Accounts in this organizational directory only**.
4. Set the **Redirect URI platform** to **Web** and enter your project's redirect URI.
- **Hosted Auth**: `https://api.us.nylas.com/v3/connect/callback` (U.S. region) or `https://api.eu.nylas.com/v3/connect/callback`. (E.U. region).
- **Bring Your Own Authentication**: Your project's callback URI.
5. Review Microsoft's Platform Policies, then click **Register**.

## Enable required APIs
:::success
**You can now enable the APIs that Nylas requires without modifying the manifest in your Azure app**. If you prefer to use the manifest, you can follow the instructions in [Enable required APIs with manifest](#optional-enable-required-apis-with-manifest).
:::
After you [create your OAuth app](#create-an-azure-oauth-application), you must add the required permissions to your Azure app. This enables the APIs that your application requires.
1. In the Microsoft Azure Portal, go to **Home > App registrations** and select your application.
2. From the left navigation menu, select **API permissions**.
3. Click **Add a permission**.
4. Select **Microsoft Graph** from the list of APIs.
5. Select **Delegated permissions**.
- If you plan to use bulk authentication, select **Application permissions** and add all Microsoft Graph scopes that your project needs access to. For more information, see [Use a Microsoft bulk authentication grant](/docs/v3/auth/bulk-auth-grants/#use-a-microsoft-bulk-authentication-grant).
6. Enable the following permissions:
- `offline_access`: Read and update user data, even when the user is offline.
- `openid`: Sign users in to the app.
- `profile`: View users' basic profiles.
- `User.Read`: Allow users to sign in to the app, and allow the app to read their profiles.
- [At least one feature permission](/docs/dev-guide/scopes/): These permissions, also known as "scopes", allow Nylas to read data from the provider.
7. Click **Add permissions**.
If your Azure app was previously registered with a manifest, you might get the following error message:
> One or more of the following permission(s) are currently not supported: EWS.AccessAsUser.All. Please remove these permission(s) and retry your request.
If this happens, you can either [enable the required APIs with a manifest](#optional-enable-required-apis-with-manifest) or [create a new Azure auth app](#create-an-azure-oauth-application).
For more information, see [Microsoft's official permissions reference](https://learn.microsoft.com/en-us/graph/permissions-reference).
### (Optional) Enable required APIs with manifest
If you use the application manifest, you can update an Azure app directly by editing its JSON. For more information, see [Microsoft's official AD Manifest documentation](https://learn.microsoft.com/en-us/entra/identity-platform/reference-app-manifest?WT.mc_id=Portal-Microsoft_AAD_RegisteredApps).
To enable the required APIs using the application manifest, follow these steps:
1. In the Microsoft Azure Portal, select **Manifest** from the left navigation menu.
1. Find `requiredResourceAccess` in the code panel.
1. Update `requiredResourceAccess` to include the following permissions:
- `offline_access`
- `openid`
- `profile`
- `User.Read`
- [At least one feature permission](/docs/dev-guide/scopes/)
1. Click **Save**.
## Create OAuth credentials
Next, create your OAuth credentials:
1. In the Microsoft Azure Portal, search for and click **App registrations** and select your application.
2. Select **Certificates & secrets** from the left navigation.
3. Click **New client secret**, enter a short description, and set the expiration date to **730 days (24 months)**.
4. Click **Add**.
5. Copy the value from the Azure Client Secrets page and save it to your secrets manager.
:::warn
⚠️ **Be sure to save the client secret value somewhere secure**. Azure shows the value only once, and if you navigate away from this page you _cannot_ retrieve the key value. For best practices, see [Storing secrets securely](/docs/dev-guide/best-practices/#store-secrets-securely).
:::

6. Navigate to the **App registrations** page and copy the **Application (client) ID** for your app.
All Azure credentials include an expiration date. When they expire, you'll need to refresh or regenerate them.
## Add a Microsoft connector to Nylas
Finally, you need to add a Microsoft connector to your Nylas application. You can create a connector either [using the Nylas Dashboard](#create-connector-using-the-nylas-dashboard), or by [making an API request](#create-connector-using-the-nylas-api).
### Create connector using the Nylas Dashboard
1. Log in to the Nylas Dashboard, and navigate to the Nylas application you're creating the connector for.
1. Select **Connectors** from the left navigation.
1. In the **Microsoft** tile, click the add symbol (**+**).
1. Under **Microsoft credentials**, enter your **Azure client ID** and **Azure client secret**.
- Set the **Azure tenant** to `common` to allow authentication for accounts that are outside of your organization.
1. Under **Authenticate scopes**, select the required scopes.
1. Click **Save**.
### Create connector using the Nylas API
To add a connector using the Nylas API, make a [Create Connector request](/docs/reference/api/connectors-integrations/create_connector/). The following code sample demonstrates how to use your Azure app's client ID and secret to add the Microsoft connector to Nylas.
```bash
curl -X POST 'https://api.us.nylas.com/v3/connectors' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"name": "microsoft example",
"provider": "microsoft",
"settings":
{
"client_id": "",
"client_secret": "",
"tenant": "common"
},
"scope": [
"offline_access",
"openid",
"profile",
"User.Read",
"Calendars.Read",
"Calendars.ReadWrite",
"Mail.ReadWrite",
"Mail.Send"
]
}'
```
:::success
**Tip**: Use `tenant: "common"` to allow authentication for accounts that are outside of your organization.
:::
## Update your Azure client secret
Microsoft's Azure client secrets expire after two years. When a secret expires, it invalidates the associated Nylas grants. For best practices on updating your Azure client secret, see [How to renew Microsoft Azure client secret for your Nylas application](https://support.nylas.com/hc/en-us/articles/11833396105757-How-to-Renew-Microsoft-Azure-Client-Secret-for-Your-Nylas-Application).
────────────────────────────────────────────────────────────────────────────────
title: "Using Microsoft accounts and data with Nylas"
description: "Build and maintain a Microsoft provider auth app and connector for your Nylas application, and work with Exchange, Outlook.com, and Microsoft 365 accounts."
source: "https://developer.nylas.com/docs/provider-guides/microsoft/"
────────────────────────────────────────────────────────────────────────────────
The Nylas platform drastically reduces the effort it takes to use Microsoft accounts with your application. With just a few lines of code, you can add full email, calendar, and contacts features to your project.
This page introduces you to Microsoft provider auth apps.
## Supported Microsoft providers
Nylas supports the following Microsoft providers:
- Exchange Server 2003+
- Exchange Online
- Microsoft 365
- Personal accounts (for example, those from hotmail.com, [msn.com](https://msn.com/), and [outlook.com](https://outlook.live.com/owa/))
### Bulk authentication grants
You can use [Microsoft bulk authentication grants](/docs/v3/auth/bulk-auth-grants/#use-a-microsoft-bulk-authentication-grant) to make and authorize requests to the Nylas APIs for applications or cloud provider compute workloads. Keep the following things in mind when working with bulk auth grants:
- You must use [Bring Your Own Authentication](/docs/v3/auth/bring-your-own-authentication/) and create a Service Account connector credential.
- Be sure to [invite Nylas to your Azure auth app](/docs/dev-guide/provider-guides/microsoft/troubleshooting/#invite-nylas-to-your-azure-app) to help with any troubleshooting you might need to do.
### Distribution lists
Nylas allows you to send messages to or from distribution lists and groups by adding them to messages as a participant. For example, if you want to send a message to the `nylas-test@example.com` distribution list, you can add it to the `to`, `cc`, or `bcc` fields in your [Send Message request](/docs/reference/api/messages/send-message/). To send messages from a distribution list, set its email address in the `from` and `reply_to` fields.
:::warn
**Nylas does not create grants for Microsoft distribution lists or groups**. They can only be included on messages as participants.
:::
### Microsoft national clouds
Nylas currently _does not_ support accounts provisioned on [national cloud environments](https://docs.microsoft.com/en-us/azure/active-directory/develop/authentication-national-cloud) (for example, accounts for the U.S. government, China, or Germany). These environments use different Microsoft Entra ID (formerly "Azure Active Directory") endpoint URLs for the authentication process.
Nylas supports accounts authenticated using the following Microsoft Entra ID (global services) endpoint URLs only:
- `microsoftonline.com`
- `office365.com`
## Message IDs and folder moves (Microsoft Exchange via EWS)
For Microsoft Exchange mailboxes accessed via the Exchange Web Services (EWS) protocol, message IDs can change when a message is moved between folders. This is expected Exchange behavior.
This applies to Exchange on-premise servers which will have grants of type `exchange`. This **does not apply** to mailboxes hosted by Exchange Online, or hybrid Exchange servers as we use **Microsoft Graph instead of EWS**. Grants that use Microsoft Graph instead of EWS will be of type `microsoft`.
Because of this, **Nylas message IDs for Microsoft accounts should be treated as folder-specific pointers, not permanent identifiers**. If you need to track a message across folder moves, use the `InternetMessageId` (RFC `Message-ID` header) instead. This value remains stable across moves.
To get the `InternetMessageId`, [include headers in your message requests or webhooks](/docs/v3/email/headers-mime-data/) by setting the `fields` query parameter to `include_headers`.
:::info
**Multiple messages can share the same `InternetMessageId`**. Exchange allows copies of a message to exist in multiple folders, all with the same `InternetMessageId`. If you need to distinguish between copies (for example, in compliance or auditing scenarios), you should track both the `InternetMessageId` and the folder location.
:::
## Microsoft provider limitations
Keep the following limitations in mind when you work with Microsoft accounts:
- Microsoft Graph has a set of service-specific throttling limits, and an overall rate limit of **130,000 requests every 10 seconds**. For more information, see the [official Microsoft documentation](https://learn.microsoft.com/en-us/graph/throttling-limits).
- Microsoft Graph doesn't support custom HTML tags in messages.
- You can only use Microsoft's modern authentication/OAuth to authenticate Microsoft 365 accounts. For authentication instructions, see [Authenticate Microsoft accounts with Nylas](/docs/provider-guides/microsoft/authentication/).
- You can't authenticate Microsoft account aliases, distribution groups, or Microsoft 365 group lists to Nylas. You can authenticate individual mailboxes and [shared mailboxes](/docs/provider-guides/microsoft/authentication/#authenticate-microsoft-shared-mailboxes).
- As of October 1, 2022, Microsoft has deprecated Basic authentication for all Exchange Online accounts.
- Nylas can't sync email accounts that are in admin groups.
- Nylas no longer supports **service accounts** for Exchange on-premises providers.
You can also review Nylas' [Microsoft authentication guide](/docs/provider-guides/microsoft/authentication/) for information on authenticating Microsoft users with your Nylas application. For a list of EWS-specific limitations, see our [Authenticate with Exchange on-prem guide](/docs/provider-guides/exchange-on-prem/#ews-limitations).
## What's next
- [List Outlook emails from the CLI](https://cli.nylas.com/guides/list-outlook-emails) - Read and filter Outlook messages from the terminal
────────────────────────────────────────────────────────────────────────────────
title: "Suggested Microsoft 365 settings"
description: "Recommended Microsoft 365 settings to ensure the best compatibility with Nylas."
source: "https://developer.nylas.com/docs/provider-guides/microsoft/microsoft-365-settings/"
────────────────────────────────────────────────────────────────────────────────
:::info
**As of January 2023, Microsoft has renamed "Office 365" to "Microsoft 365"**. For more information, see [Microsoft's official FAQs](https://www.microsoft.com/en-us/microsoft-365/business/microsoft-365-frequently-asked-questions).
:::
This page outlines the Microsoft 365 settings Nylas recommends to ensure the best compatibility between the two platforms.
## Before you begin
Before you start, you must have a Microsoft 365 organization. Log in to [Microsoft Office](https://office.com) and select **Admin** in the left navigation.
## Calendar sharing settings
Nylas recommends your organization's default sharing policy is set to allow individual calendar sharing.
1. From the Microsoft 365 admin center home page, select **Settings > Org settings** in the left navigation.
2. Select **Calendar** from the list of services.
3. Enable **Let your users share their calendars with people outside of your organization who have Office 365 or Exchange**.
4. **Save** your changes.

## Enable malware filter
Nylas recommends you enable the Microsoft malware filter for messages.
1. From the Microsoft 365 admin center home page, select **Settings > Org settings** in the left navigation.
2. Select **Mail** from the list of services.
3. Click **Anti-malware policies**.
4. Verify that the **Malware detection response** is set to **Delete all attachments**.
5. Verify that **Sender notifications** are enabled for both internal and external senders.
6. **Save** your changes.

## Enable connection filter
Nylas recommends you use the default connection filter settings for all messages.
1. From the Microsoft 365 admin center home page, select **Settings > Org settings** in the left navigation.
2. Select **Mail** from the list of services.
3. Click **Connection filter policies**.
4. Verify that you're using the default settings from Microsoft.

## Set mobile device access rules
Nylas recommends you update the mobile device access rules to allow iPhones and Nylas support devices (devices with the `python-EAS-Client 1.0` user agent).
1. From the Microsoft Exchange admin center home page, select **Mobile** in the left navigation.
2. Under **Quarantined devices**, verify that the user agent `python-EAS-Client 1.0` is not listed. This is the dummy mobile device Nylas uses to connect.
3. Under **Device access rules**, verify that all iPhone devices are allowed.

## Set mobile device mailbox policies
Nylas recommends you use the default mobile device mailbox policies.
1. From the Microsoft Exchange admin center home page, select **Mobile** in the left navigation.
2. Verify that you're using the default settings from Microsoft.
────────────────────────────────────────────────────────────────────────────────
title: "Shared Outlook folders"
description: "How to share Microsoft Outlook folders and import folders shared from other people."
source: "https://developer.nylas.com/docs/provider-guides/microsoft/shared-folders/"
────────────────────────────────────────────────────────────────────────────────
:::info
**As of January 2023, Microsoft has renamed "Office 365" to "Microsoft 365"**. For more information, see [Microsoft's official FAQs](https://www.microsoft.com/en-us/microsoft-365/business/microsoft-365-frequently-asked-questions).
:::
Microsoft Outlook allows users to share folders with other people in their organization. This page explains how to share Outlook folders and how to access folders that have been shared with you using the Nylas API.
## Before you begin
To work with shared folders in Nylas, you need:
- A Microsoft 365 account with folder sharing permissions
- A Nylas grant with the appropriate scopes for accessing shared folders
- The email address or grant ID of the person who shared the folder
## Required scopes
To access shared folders, you must request one of the following Microsoft scopes when authenticating:
- **`Mail.Read.Shared`**: Read-only access to shared folders
- **`Mail.ReadWrite.Shared`**: Read and write access to shared folders
These scopes allow your application to access folders that have been shared with the authenticated user. For more information about scopes, see [Using scopes to request user data](/docs/dev-guide/scopes/).
:::info
**The `Mail.Read.Shared` and `Mail.ReadWrite.Shared` scopes are Microsoft-specific**. They work alongside the standard `Mail.Read` and `Mail.ReadWrite` scopes to provide access to shared resources.
:::
## Share folders in Microsoft Outlook
Before you can access a shared folder through Nylas, the folder owner must share it with you in Microsoft Outlook. The process varies depending on whether you're using Outlook on the web or the desktop application.
### Share a folder in Outlook on the web
1. Sign in to [Outlook on the web](https://outlook.office.com).
2. Right-click the folder you want to share in the folder list.
3. Select **Permissions** or **Share folder**.
4. Enter the email address of the person you want to share the folder with.
5. Select the permission level (for example, **Reviewer**, **Editor**, or **Owner**).
6. Click **Share**.
### Share a folder in Outlook desktop
1. Open Outlook desktop application.
2. Right-click the folder you want to share in the folder list.
3. Select **Properties**.
4. Go to the **Permissions** tab.
5. Click **Add** and enter the email address of the person you want to share the folder with.
6. Select the permission level and click **OK**.
For more information about sharing folders in Microsoft Outlook, see [Microsoft's documentation](https://support.microsoft.com/en-us/office/share-an-outlook-calendar-or-folder-with-other-people-353ed2c1-3d5c-4b9e-a5f8-7d78287af2e7).
## View shared folders in Outlook (optional)
:::info
**Viewing shared folders in the Outlook UI is optional**. You don't need to import or add shared folders in Outlook to access them through the Nylas API. As long as the folder has been shared with you and your grant has the appropriate scopes (`Mail.Read.Shared` or `Mail.ReadWrite.Shared`), you can access shared folders directly through the API.
:::
If you want to view shared folders in your Outlook client, you can add them to your folder list. The process varies depending on which version of Outlook you're using.
### View shared folders in Outlook on the web
1. Sign in to [Outlook on the web](https://outlook.office.com).
2. In the left navigation pane, right-click the area labeled **Shared with me** (or right-click your mailbox name).
3. Select **Add shared folder or mailbox**.
4. Enter the email address of the person who shared the folder with you.
5. Click **Add**. The shared folders appear in your folder list under the owner's name.
### View shared folders in Outlook desktop (New Outlook)
1. Open Outlook desktop application.
2. Go to **File → Account Info** or **Settings → Accounts → Shared with me**.
3. In the **Shared with me** pane, you'll see a list of mailboxes or folders shared with you.
4. To display a shared folder in the folder pane, select **+ Add** or **Add shared folder or mailbox**.
5. Enter the email address or name of the folder owner.
6. The shared folder appears in your folder list under **Shared with me**.
### View shared folders in Outlook desktop (Classic Outlook)
1. Open Outlook desktop application.
2. Go to **File → Account Settings → Account Settings**.
3. Select your account and click **Change**.
4. Click **More Settings**.
5. Go to the **Advanced** tab.
6. Click **Add** under **Open these additional mailboxes**.
7. Enter the email address of the person who shared the folder with you.
8. Click **OK** to close all dialog boxes.
### Important notes about viewing shared folders
- **Subfolders**: To view shared subfolders, the parent folder (and sometimes the top-level mailbox) must have at least "Folder Visible" permission. Without this permission on parent levels, subfolders may not appear in your folder list.
- **Permission propagation**: It can take some time (sometimes hours) for new shared permissions to fully propagate. If you don't see folders immediately, try restarting Outlook or waiting for the server to sync.
- **Not required for API access**: Remember that adding shared folders in the Outlook UI is optional. You can access shared folders through the Nylas API without adding them to your Outlook client.
For more information about viewing shared folders in Outlook, see [Microsoft's documentation](https://support.microsoft.com/en-us/office/share-and-access-another-person-s-mailbox-or-folder-in-outlook-a909ad30-e413-40b5-a487-0ea70b763081).
## Access shared folders with Nylas
After a folder has been shared with you, you can access it through the Nylas API using your grant. Microsoft has specific limitations for accessing shared folders that you must follow.
### List folders shared by a specific owner
:::warning
**Microsoft does not support listing all shared folders from all accounts**. You must specify the folder owner's email address or grant ID using the `shared_from` query parameter.
:::
To list folders shared by a specific owner, make a [Get all Folders request](/docs/reference/api/folders/get-folder/) with the `shared_from` parameter:
```bash
curl --request GET \
--url 'https://api.us.nylas.com/v3/grants//folders?shared_from=' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer '
```
The `shared_from` parameter accepts:
- An email address of the person who shared the folder
- A grant ID associated with the folder owner
When you use `shared_from`, Nylas returns only the folders shared by that specific owner.
Your own folders are not included in the response. For example, if you have folder A and B,
and someone shares a folder C with you,
you'll only see the folder C when you pass `shared_from` with the owner's email address.
### Work with shared folders
When using `shared_from`, you can perform all operations on folders shared by the specified owner:
- [Get all Folders request](/docs/reference/api/folders/get-folder/) requires `shared_from`
- [Get Folder request](/docs/reference/api/folders/get-folders-id/) requires `shared_from`
- [Create Folder request](/docs/reference/api/folders/post-folder/) requires `shared_from`
- [Update Folder request](/docs/reference/api/folders/put-folders-id/) requires `shared_from`
- [Delete Folder request](/docs/reference/api/folders/delete-folders-id/) requires `shared_from`
All operations are performed on the folder owner's account, not on your own account.
### Access messages in shared folders
:::warning
**Microsoft does not support listing messages across all shared folders, even if they are from the same owner**. You must specify both the `in` parameter (folder ID) and the `shared_from` parameter.
:::
To list messages in a shared folder, you must provide both the folder ID and the owner's email address or grant ID:
```bash
curl --request GET \
--url 'https://api.us.nylas.com/v3/grants//messages?in=&shared_from=' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer '
```
All other message endpoints support shared folders as long as you pass the `shared_from` parameter.
### Work with threads in shared folders
Thread operations in shared folders have specific requirements:
- [Get all Threads request](/docs/reference/api/threads/get-threads/) requires both `in` (folder ID) and `shared_from` parameters
- [Get Thread request](/docs/reference/api/threads/get-threads-id/) requires `shared_folder_id` along with `shared_from`
- [Update Thread request](/docs/reference/api/threads/put-threads-id/) requires `shared_folder_id` along with `shared_from`
- [Delete Thread request](/docs/reference/api/threads/delete-threads-id/) requires `shared_folder_id` along with `shared_from`
:::warning
**Nylas does not support listing, retrieving, updating, or deleting threads across shared folders**. You must specify a specific folder and owner for each operation.
:::
## Limitations
Keep the following limitations in mind when working with shared folders:
- **Scope requirements**: You must request `Mail.Read.Shared` or `Mail.ReadWrite.Shared` scopes during authentication to access shared folders.
- **Owner specification required**: Microsoft does not support listing all shared folders from all accounts. You must always specify the folder owner's email address or grant ID using the `shared_from` parameter.
- **Folder isolation**: When using `shared_from`, you only see folders from that specific owner. Your own folders are not included in the response.
- **Message listing**: To list messages in shared folders, you must provide both the `in` parameter (folder ID) and the `shared_from` parameter. Microsoft does not support listing messages across all shared folders.
- **Thread operations**: Listing threads requires both `in` and `shared_from`. Retrieving, updating, or deleting threads requires `shared_folder_id` along with `shared_from`. Nylas does not support listing, retrieving, updating, or deleting threads across shared folders.
- **Subfolders**: If a folder is shared, its subfolders are not automatically shared. Each subfolder must be shared separately.
- **Deleting messages and threads**: To delete messages or threads from a shared folder, the folder owner must also share the "Deleted Items" folder with you. Without access to the Deleted Items folder, deletion operations will fail.
- **Microsoft-only feature**: Shared folder access through the `shared_from` parameter is only available for Microsoft grants.
- **Permission levels**: The actions you can perform on shared folders depend on the permission level granted by the folder owner (for example, read-only vs. read-write access).
────────────────────────────────────────────────────────────────────────────────
title: "Troubleshooting Microsoft configuration"
description: "Troubleshoot common issues that you might encounter when using Microsoft accounts with Nylas."
source: "https://developer.nylas.com/docs/provider-guides/microsoft/troubleshooting/"
────────────────────────────────────────────────────────────────────────────────
This page describes common issues you might encounter when using Microsoft accounts with Nylas and how to troubleshoot them.
## Gather Exchange logs
Sometimes, Nylas can't sync because of internal errors on the Exchange server. Because we can't access any logging information, it can be difficult to determine why the Exchange server is experiencing these errors.
If you need help troubleshooting your Exchange server and you have a contract with us, you can share more detailed error information from the Exchange server with us.
1. Log in to [Outlook on the web](https://outlook.live.com/).
2. On the menu bar, click the **Settings** symbol.
3. Select **General > Mobile devices** in the left navigation.
4. Find the mobile device that you want to enable logging for an click the **pencil** symbol to view its details.

5. Review the device's details and confirm that the **User agent** is `python-EAS-client 1.0`. This is the name that Nylas uses to connect to your application.
6. Click the **Enable logging** symbol, and click **Save**.
7. Reproduce the issue you experienced. If you have a general sync issue, try sending a test message and let the logger gather data for about 10 minutes.
8. Check your inbox for a message titled "Exchange ActiveSync Mailbox Logs".
9. Download the message and include it as an attachment when you [reach out for support](/docs/support/#contact-nylas-support).
For more information on mobile device options in Outlook, see [Microsoft's official documentation](https://support.microsoft.com/en-us/office/mobile-devices-options-on-outlook-com-6777abf4-0430-4392-bea0-9c169d85b14d).
## Invite Nylas to your Azure app
If you need help troubleshooting your Microsoft OAuth settings and you have a contract with us, you can give the Nylas Support team permissions to access your Azure auth app. This lets the team review your app's settings, give feedback on potential authentication issues, and suggest next steps.
### Invite Nylas Support to your Azure app
1. Log in to the [Microsoft Azure Portal](https://portal.azure.com) as an administrator.
2. Search for **Microsoft Entra ID** and navigate to the resulting page.
3. Select **Manage > Users** in the left navigation.
4. Click **New user**, then **Invite external user**.
5. Add `support@nylas.com` and click **Review + invite**.

### Grant admin permissions to Nylas Support
After you invite the Nylas Support team to your Azure auth app, you can give them administrator permissions. This lets the team access your app's settings for troubleshooting purposes.
1. From the Azure Portal home page, search for **Microsoft Entra ID** and navigate to the resulting page.
2. Click **Manage > Roles and administrators**.
3. Select **Application administrator** from the list of roles.
4. Click **Add assignments**.
5. Search for `support@nylas.com` and click **Add**.
────────────────────────────────────────────────────────────────────────────────
title: "Microsoft publisher verification guide"
description: "Complete Microsoft's publisher verification process."
source: "https://developer.nylas.com/docs/provider-guides/microsoft/verification-guide/"
────────────────────────────────────────────────────────────────────────────────
In this guide, you'll learn about Microsoft's publisher verification and how to complete the process.
## What is publisher verification?
Microsoft's publisher verification gives application users and organization administrators information about the authenticity of the developer's organization. When the publisher of an application has been verified, a blue badge appears in the Microsoft consent prompt for the app.
If you already meet the [requirements](https://learn.microsoft.com/en-us/entra/identity-platform/publisher-verification-overview#requirements), you can complete the verification process in minutes. Microsoft doesn't charge developers for publisher verification, and you don't need a license to become a verified publisher.
## Why is publisher verification required?
As of November 2020, if [risk-based step-up consent](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/configure-risk-based-step-up-consent) is enabled, users can't consent to most newly registered multi-tenant applications that haven't been verified. Microsoft displays a warning on the consent page informing users that the apps are risky because they're from unverified publishers.
Microsoft recommends restricting user consent to allow users to consent for applications from verified publishers only, with specific permissions. For apps that don't meet this policy, your organization's IT team is responsible for making any decisions. This means that if you don't complete the verification process, you'll likely need admin consent from Microsoft 365 organizations before users can connect their individual accounts. This can slow or block adoption.
For more information on Microsoft's publisher verification, check out [Microsoft's official documentation](https://docs.microsoft.com/en-us/azure/active-directory/develop/publisher-verification-overview).
## Publisher verification process
To complete the publisher verification process, follow these steps:
1. [Create an Azure auth app](/docs/provider-guides/microsoft/create-azure-app/) for your project.
1. [Join the Microsoft AI Cloud Partner Program](https://partner.microsoft.com/en-us/partnership).
1. [Configure your app's publisher domain](https://learn.microsoft.com/en-us/entra/identity-platform/howto-configure-publisher-domain).
1. [Mark your app as publisher verified](https://learn.microsoft.com/en-us/entra/identity-platform/mark-app-as-publisher-verified).
Your app is now verified! Make sure that you see a blue badge next to your **Publisher display name**, under **Branding & properties**.
If you run into any issues, see [Microsoft's official troubleshooting steps](https://learn.microsoft.com/en-us/entra/identity-platform/troubleshoot-publisher-verification).
────────────────────────────────────────────────────────────────────────────────
title: "Authenticating Yahoo accounts with Nylas"
description: "Connect Yahoo accounts to Nylas using Yahoo OAuth or Nylas' Hosted IMAP authentication."
source: "https://developer.nylas.com/docs/provider-guides/yahoo-authentication/"
────────────────────────────────────────────────────────────────────────────────
Nylas supports two ways to authenticate users who have Yahoo as their provider: using [Yahoo's OAuth and Nylas' Bring Your Own (BYO) Authentication](#set-up-yahoo-oauth-and-nylas-bring-your-own-authentication), or by having them [create an app password](#create-yahoo-app-password) and using that password with [Nylas' BYO or Hosted IMAP authentication](#authenticate-yahoo-grants-with-app-password)
:::info
**We strongly recommend using Yahoo's OAuth method instead of authenticating using IMAP**. This gives you more secure access to your users' data.
:::
## Set up Yahoo OAuth and Nylas Bring Your Own Authentication
Before you authenticate users with Yahoo's OAuth and Nylas' BYO Authentication, you need to set up your environment and authentication flow:
1. [Request access to Yahoo data](#request-access-to-yahoo-data).
2. [Set up an OAuth-client endpoint](#set-up-oauth-client-endpoint) that can perform an OAuth handshake.
3. [Create and configure a Yahoo auth app](#create-yahoo-auth-app).
4. [Create a Yahoo connector](#create-yahoo-connector).
5. Use information from the OAuth process to [make BYO Authentication requests to Nylas](#create-grants-with-yahoo-oauth) and create grants for your users.
### Request access to Yahoo data
1. Create a Yahoo account that only your organization's administrators can access.
2. [Submit a Yahoo Mail API Access form to Yahoo](https://senders.yahooinc.com/developer/developer-access-mail-form/). This is _required_ if you want to use OAuth to access Yahoo's IMAP and SMTP servers. Make sure you mention somewhere in the form that you're using Nylas to connect.
- **Email address**: Enter the email address that you created in step 1.
- **API required**: Select **IMAP**.
- **Your YDN account**: Enter the email address that you created in step 1.
3. Yahoo sends you a **Yahoo Mail Products Commercial Access Agreement**. Review the form, sign it, and send it back to Yahoo.
Yahoo sends you a message to notify you when they approve your data access request, or to ask for more information (if needed).
### Set up OAuth-client endpoint
After you [request access to Yahoo data](#request-access-to-yahoo-data), you need to set up an OAuth-client endpoint (also called a "redirect URI") in your project. This endpoint must be able to accept requests from Yahoo, extract information from the requests to complete an OAuth handshake process, then use the resulting refresh token to create a Nylas grant using BYO Authentication.
Take note of your OAuth-client endpoint URI. You'll need it when you [create your Yahoo auth app](#create-yahoo-auth-app).
### Create Yahoo auth app
1. Sign in to the [Yahoo Apps dashboard](https://developer.yahoo.com/apps/) using your admin Yahoo account.
2. Select **Create an app** and fill out the information.
- **Application name**: Enter a brief, descriptive name for your application.
- **Description**: Describe your application (for example, the region you'll be using it for).
- **Homepage URL**: (Optional) Enter your application's homepage URL.
- **Redirect URI(s)**: Enter your [OAuth-client endpoint URI](#set-up-oauth-client-endpoint). Registering a redirect URI might take _up to 24 hours_. You might experience inconsistencies when trying to log in to your Yahoo account during that time.
- **OAuth client type**: Select **Confidential client**.
- **API permissions**:
- Select **Mail**. If you plan to use Nylas to send or modify messages, select **Read/Write**. If you don't send or modify messages, select **Read**.
- Select **OpenID connect permissions**, then select **Email** and **Profile**.
3. Click **Create app**.
4. On the next page, Yahoo displays your app's client ID and secret. Take note of them, because you'll need them when you [create a Yahoo connector](#create-yahoo-connector).
:::warn
**Be sure to save the client secret value somewhere secure, like a secrets manager**. For best practices, see [Store secrets securely](/docs/dev-guide/best-practices/#store-secrets-securely).
:::
### Create Yahoo connector
After you [create a Yahoo auth app](#create-yahoo-auth-app), you can create a Yahoo connector for your Nylas application.
To create a connector using the Nylas API, make a [Create Connector request](/docs/reference/api/connectors-integrations/create_connector/) that specifies `"provider": "yahoo"`.
:::info
**Your `scope` array must match the scopes you request in your Yahoo auth app**. If you request Mail Read/Write in your auth app, specify `mail-w` in your request. If you request Mail Read, specify `mail-r` instead. If you try to request both `mail-w` and `mail-r`, Nylas returns an error.
:::
```bash {5,10-13} [group_1-cURL]
curl -X POST 'https://api.us.nylas.com/v3/connectors' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"provider": "yahoo",
"settings": {
"client_id": "