# Nylas v3 diff view

Source: https://developer.nylas.com/docs/new/in-v3/tldr-diff/

This page provides a terse, high-level description of the changes between Nylas v2.7 and v3.0.0. It's not intended to be a thorough description of how to [upgrade and migrate your Nylas application](/docs/v2/upgrade-to-v3/), but a high-level list suitable for helping with scoping tasks, and to be used as a checklist.

## Terminology changes in v3


We've taken the opportunity to clarify some of the language we use to refer to parts of the Nylas system. While some of these changes are not yet available at the API level (meaning the API endpoints still reflect the v2 name), the documentation and Nylas UIs are being updated to use the clearer language.

- The **integration** object that you create in your Nylas application to store provider details is now called a **connector**.
- **Provider integration applications** (for example, your Google Cloud Platform project or Azure app) are now called **provider auth apps**.
- **Native** authentication is now called **Custom** authentication.
- **Service accounts** (sometimes called "app permissions") are now called **bulk authentication grants** to better reflect their use.
- The `redirect_uri` set in Nylas applications that use Hosted authentication is now called the `callback_uri`. This helps to distinguish it from the Nylas `redirect_uri` set in provider auth apps.
  - The `callback_uri` used by webhook subscriptions is now called `webhook_url` to be more explicit about its use.


## Changes to API format and use in v3


The Nylas API endpoints and production domains have changed in v3. They now follow the `[service].[region].nylas.com` schema:

- `api.nylas.com` → `api.us.nylas.com`
- `canada.api.nylas.com` → `api.us.nylas.com`
- `ireland.api.nylas.com` → `api.eu.nylas.com`


You must now include the version code in the endpoint URI, and Nylas v3 ignores the `Nylas-API-Version` header.

## Changes to provider auth apps in v3

> **Error:** 
> ⛔️ **Do not use production provider auth apps to test your upgrades to Nylas v3**. This might prevent your end users from re-authenticating using the methods available in v2.x, and may invalidate your Support SLAs. Make these changes only on _non-production apps_ until you're ready for full migration.

In Nylas v3, each Nylas application can have only one connector (previously "integration") for each provider. This might limit your ability to connect to legacy auth systems.

If you're upgrading from Nylas v2.7 to v3, keep the following things in mind:

- You can use the same Google auth app as long as you have Pub/Sub set up.
- You can reuse your Azure auth app if you remove any EWS/EAS scopes, add Graph scopes, and include personal accounts in the supported account types.
> **Warn:** 
> ⚠️ **Adding Graph scopes to your Azure app might prevent existing EWS or EAS accounts from re-authenticating**. Make this change only on _non-production apps_ until you're ready for full migration.
- You must update your redirect URIs for any provider auth apps you create so they use the v3-specific endpoints.

## New Hosted authentication methods

Most v2 Nylas applications that use Hosted authentication should implement the new Hosted OAuth method when you migrate them. This method involves storing and sending the application's API key only once. This returns a code that you can exchange for an access token, as in Nylas v2.7. Access tokens now expire after one hour, so you can choose to receive a refresh token as well to help re-authenticate when the access token expires.

Additional PKCE options are available to use with single page applications (SPAs) and mobile apps.

To access your end users' data using pure OAuth, pass the access token as the Bearer token in your request's auth header.

## Refactored Nylas SDKs

The Nylas SDKs have been updated, improved, and refactored for v3. For more information, see the SDK documentation:

- [Kotlin/Java SDK v2](/docs/v3/sdks/kotlin-java/)
- [Node.js SDK v7](/docs/v3/sdks/node/)
- [Python SDK v6](/docs/v3/sdks/node/)
- [Ruby SDK v6](/docs/v3/sdks/ruby/)

## Deprecated APIs

- `/delta`: No longer needed with v3 architecture.
- `/job-statuses`: No longer needed with v3 architecture.
- `/components`: Deprecated.
- `/outbox`: Most functionality replaced by scheduled send.
- Generate ICS file: `POST /events/to-ics`

## Removed Nylas scopes

Nylas v3 removes [Nylas scopes](/docs/v2/developer-guide-v2/authentication/authentication-scopes/) to reduce complexity and give you more control. Instead, you specify provider scopes only.

You can either create a login button for each provider that you support, or use the [`/v3/providers/detect` endpoint](/docs/api/v3/admin/#post-/v3/providers/detect) to determine which provider an end user is authenticating with, so you can request the correct set of provider scopes.

## Nylas application management in v3

You can create and manage v3 applications, access their `client_id`s, and generate API keys from the v3 Nylas Dashboard. You _cannot_ create applications using the API.

> **Info:** 
> 🔍 **The v3 Nylas Dashboard no longer displays client secret values for applications**. Where you would previously use the `client_secret` in requests, you should now use your application's API key.

As of May 2024, the v3 Dashboard now supports both v2 and v3 Nylas applications, but doesn't include a version switcher. In v3 and later, the major version is encoded in the endpoint route.

### Callback and redirect URIs

The `redirect_uri` used in the Hosted authentication flow has been renamed to `callback_uri` in Nylas v3. This helps to distinguish it from the Nylas `redirect_uri`, which provider auth apps use to forward OAuth requests to Nylas. The `callback_uri` used by webhook subscriptions is now called `webhook_url` to be more explicit.

In short, you'll encounter the following URIs in v3:

- The **callback URI** is used during the Hosted authentication flow, and is set in your Nylas application.
- The **redirect URI** is used during the provider OAuth flow, and is set in your provider auth app.
- The **webhook URL** is part of a webhook subscription. This determines where Nylas sends webhook notifications.

### New application endpoints

- Get a list of applications: [`GET /v3/applications`](/docs/api/v3/admin/#get-/v3/applications)
- Add callback URI to application: [`POST /v3/applications/redirect-uris`](/docs/api/v3/admin/#post-/v3/applications/redirect-uris)
- Get all application callback URIs: [`GET /v3/applications/redirect-uris`](/docs/api/v3/admin/#get-/v3/applications/redirect-uris)
- Get a specific callback URI: [`GET /v3/applications/redirect-uris/<ID>`](/docs/api/v3/admin/#get-/v3/applications/redirect-uris/-id-)
- Delete a callback URI: [`DELETE /v3/applications/redirect-uris/<ID>`](/docs/api/v3/admin/#delete-/v3/applications/redirect-uris/-id-)
- Update a callback URI: [`PATCH /v3/applications/redirect-uris/<ID>`](/docs/api/v3/admin/#patch-/v3/applications/redirect-uris/-id-)

### Removed application endpoints

- Return application details: `GET /a/<NYLAS_CLIENT_ID>`
- Update application details: `PUT /a/<NYLAS_CLIENT_ID>`
- Get webhook IP addresses: `GET /a/<NYLAS_CLIENT_ID>/ip_addresses`

## Connectors (previously called "integrations")

You must create a connector to store information about authentication sources for all v3 Nylas applications (including those using Native or Custom authentication, and any using virtual calendars). Connectors are currently available for Google, Microsoft Graph, and IMAP providers.

A v3 Nylas application can have only one connector per external provider, including one each for Google and Microsoft Graph. You can [configure the default scopes for each provider](/docs/v3/auth/#create-a-connector).

### New connector endpoints

- List connectors: [`GET /v3/connectors`](/docs/api/v3/admin/#get-/v3/connectors)
- Create a connector: [`POST /v3/connectors`](/docs/api/v3/admin/#post-/v3/connectors)
- Get a connector: [`GET /v3/connectors/<provider>`](/docs/api/v3/admin/#get-/v3/connectors/-provider-)
- Delete a connector: [`DELETE /v3/connectors/<provider>`](/docs/api/v3/admin/#delete-/v3/connectors/-provider-)
- Update a connector: [`PATCH /v3/connectors/<provider>`](/docs/api/v3/admin/#patch-/v3/connectors/-provider-)

### Migrated connector endpoints

- Detect provider: `POST /connect/detect-provider` → [`POST /v3/providers/detect`](/docs/api/v3/admin/#post-/v3/providers/detect)

## "Connected accounts" changed to "grants"

In Nylas v3, the concept of "grants" (as in "the end user _granted_ you this access") replaces the concept of "connected accounts". This name better reflects the new offering and lays the groundwork for future enhancements and features.

### Re-authenticating grants and webhook notifications


Nylas doesn't produce webhook notifications for events that happened before a user authenticated with your application. When a user's grant expires, Nylas stops sending webhook notifications for changes because it can no longer access the account's data.

If the grant expires then becomes valid _within 72 hours_, Nylas produces webhook notifications for the period that the grant was out of service. This means that your application may experience a high volume of incoming webhooks while Nylas syncs the events. The [best practices guide](/docs/dev-guide/best-practices/webhook-best-practices/) includes suggestions for how to prepare to process a large number of incoming webhooks.

If the grant expires and becomes valid after that 72 hour period, Nylas doesn't send backfill notifications for events that occurred while their grant was out of service. In this case, look for the `grant.expired` and `grant.updated` notifications and query the Nylas APIs for objects that changed between those timestamps.


### Accounts endpoints migrated to grants

- Return all accounts → List all grants (`GET /a/<NYLAS_CLIENT_ID>` → [`GET /v3/grants`](/docs/api/v3/admin/#get-/v3/grants))
- Return a specific account → Get a specific grant (`GET /a/<NYLAS_CLIENT_ID>/accounts/<NYLAS_ACCOUNT_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>`](/docs/api/v3/admin/#get-/v3/grants/-grantId-))
- Delete an account → Revoke a grant (`DELETE /a/<NYLAS_CLIENT_ID>/accounts/<NYLAS_ACCOUNT_ID>` → [`DELETE /v3/grants/<NYLAS_GRANT_ID>`](/docs/api/v3/admin/#delete-/v3/grants/-grantId-))

### New grants endpoints

- Update a grant: [`PATCH /v3/grants/<NYLAS_GRANT_ID>`](/docs/api/v3/admin/#patch-/v3/grants/-grantId-)
- Get the current grant: [`GET /v3/grants/me`](/docs/api/v3/admin/#get-/v3/grants/me)

### Removed account endpoints

- Cancel an account: `POST /a/<NYLAS_CLIENT_ID>/accounts/<NYLAS_ACCOUNT_ID>/downgrade`
- Reactivate an account: `POST /a/<NYLAS_CLIENT_ID>/accounts/<NYLAS_ACCOUNT_ID>/upgrade`
- Revoke all tokens: `POST /a/<NYLAS_CLIENT_ID>/accounts/<NYLAS_ACCOUNT_ID>/revoke-all`
- Return token info: `POST /a/<NYLAS_CLIENT_ID>/accounts/<NYLAS_ACCOUNT_ID>/token-info`
- Revoke an access token: `POST /oauth/revoke`
- Return account details: `GET /account`

## Changes to authentication in v3

The following sections describe changes to authentication in Nylas v3.

### New authentication endpoints

- Hosted OAuth - Revoke an OAuth token: [`POST /v3/connect/revoke`](/docs/api/v3/admin/#post-/v3/connect/revoke)

### Migrated authentication endpoints

- Hosted auth - Authenticate user → Hosted OAuth - Authorization request (`GET /oauth/authorize` → [`GET /v3/connect/auth`](/docs/api/v3/admin/#get-/v3/connect/auth))
- Hosted auth - Send authorization code → Hosted OAuth - Token exchange (`POST /oauth/token` → [`POST /v3/connect/token`](/docs/api/v3/admin/#post-/v3/connect/token))
- Native auth → Custom auth (`POST /connect/token` → [`POST /v3/connect/custom`](/docs/api/v3/admin/#post-/v3/connect/custom))

### Removed authentication endpoints

[//]: # "TODO: these are listed as being Native auth, but are these equivalent to the server side-only Hosted endpoints? Does the “native auth” line item below take over for any of these?"

Native authentication has been renamed to "Custom authentication" in Nylas v3. Because of this change, the following auth endpoints have been removed:

- Native auth - Send Authorization: `POST /connect/authorize`. Use the [`/v3/connect/custom` endpoint](/docs/api/v3/admin/#post-/v3/connect/custom) instead.
- Native auth - Exchange Token: `POST /connect/token`

## Changes to webhooks in v3

Nylas v3 introduces _many_ improvements and changes to webhooks that are beyond the scope of this brief diff view. See [Webhooks in v3](/docs/new/in-v3/webhooks-changes/) for more details.

### "Callback URI" changed to "webhook URL"

The `callback_uri` used by webhook subscriptions is now called `webhook_url` to make it explicit what this address is used for. This also helps distinguish it from the `callback_uri` and `redirect_uri` used in Hosted authentication.

### New webhooks endpoints

- Rotate a webhook secret: [`POST /v3/webhooks/rotate-secret/<WEBHOOK_ID>`](/docs/api/v3/admin/#post-/v3/webhooks/rotate-secret/-id-)
- Get a mock payload: [`POST /v3/webhooks/mock-payload`](/docs/api/v3/admin/#post-/v3/webhooks/mock-payload)
- Send a test event: [`POST /v3/webhooks/send-test-event`](/docs/api/v3/admin/#post-/v3/webhooks/send-test-event)

### Migrated webhooks endpoints

- Return all webhook destinations: `GET /a/<NYLAS_CLIENT_ID>/webhooks` → [`GET /v3/webhooks`](/docs/api/v3/admin/#get-/v3/webhooks)
- Create a webhook destination: `POST /a/<NYLAS_CLIENT_ID>/webhooks` → [`POST /v3/webhooks`](/docs/api/v3/admin/#post-/v3/webhooks)
- Return destinations for specified webhook: `GET /a/<NYLAS_CLIENT_ID>/webhooks/<WEBHOOK_ID>` → [`GET /v3/webhooks/<WEBHOOK_ID>`](/docs/api/v3/admin/#get-/v3/webhooks/-id-)
- Update a webhook destination: `PUT /a/<NYLAS_CLIENT_ID>/webhooks/<WEBHOOK_ID>` → [`PUT /v3/webhooks/<WEBHOOK_ID>`](/docs/api/v3/admin/#put-/v3/webhooks/-id-)
- Delete a webhook destination: `DELETE /a/<NYLAS_CLIENT_ID>/webhooks/<WEBHOOK_ID>` → [`DELETE /v3/webhooks/<WEBHOOK_ID>`](/docs/api/v3/admin/#delete-/v3/webhooks/-id-)

## Changes to webhook triggers in v3

The `.truncated` suffix is new in v3. Watch for it, because it indicates a data payload that exceeds a base limit of 1MB. You will want to re-query for additional data in that case only.

### Unchanged webhook triggers

- `contact.updated`
- `contact.deleted`
- `calendar.created`
- `calendar.updated`
- `calendar.deleted`
- `event.created`
- `event.updated`
- `event.deleted`
- `message.created`
- `message.updated`
- `folder.created`
- `folder.updated`
- `folder.deleted`

### New webhook triggers

- `grant.updated` (Includes re-authentication.)
- `grant.deleted`
- `grant.expired`
- `message.send_success` (Scheduled email messages only.)
- `message.send_failed` (Scheduled email messages only.)
- `message.bounce_detected` (Available for Google, Microsoft Graph, iCloud, and Yahoo.)
- `message.link_clicked`
- `thread.replied`

### Migrated webhook triggers

- `account.connected` → `grant.created`

### Removed webhook triggers

- `account.running`: No longer needed due to architecture changes.
- `account.stopped`: No longer needed due to architecture changes.
- `account.invalid`: Use `grant.deleted` or `grant.expired` instead.
- `account.sync_error`: No longer needed due to architecture changes.
- `contact.created`: Use `contact.updated` instead.
- `job.successful`: No longer needed due to architecture changes.
- `job.failed`: No longer needed due to architecture changes.

## Changes to Calendars and Events in v3

The Calendar and Events endpoints are available for Google, Microsoft Graph, EWS, iCloud, and virtual calendars. Nylas v3 includes the same basic ability to create, read, update, and delete both Events and Calendars (which contain Events). It also includes the following changes:

- You now need a `calendar_id` for almost all calls to Events endpoints. You can specify it in one of the following ways:
  - Using the `primary` parameter to specify the primary calendar for the grant.
  - Look up and use the ID of the calendar that you want to work with.
- You can now specify open hours by adding the `default_open_hours` parameter to the `availability_rules` object.
  - You can override the default settings by specifying a different availability for each participant.
- Round-robin availability now uses the Nylas `key5` metadata to indicate events that Nylas should consider when calculating the next available time amongst a group of participants.
- The format for event start and end times has been simplified.
- The format for recurring events has been simplified.
  - Recurring events no longer accept a recurrence time zone, and instead use the time zone specified in the `when` object to calculate the time for each event instance.
- You can now list all calendars and events for a specific grant.
- Nylas no longer generates an "Emailed Events" calendar for IMAP accounts.
- Added [`POST /v3/grants/<NYLAS_GRANT_ID>/events/<EVENT_ID>/send-rsvp` endpoint](/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/events/-event_id-/send-rsvp).
- Added the `is_owned_by_user` property for all Calendar calls.
- (Gmail and Microsoft Graph only) Added the `hex_color` property for all Calendar calls.
- (Microsoft Graph only) Added access to shared calendars using the [Return Calendars endpoint](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/calendars).
- Added the `order_by` query parameter for all Events `GET` calls.
- Added the `html_link` property for all Events `GET` calls.
- Added the `capacity` property for all Events calls.
- You can no longer use a `free_busy` object to override or add busy data to an Availability request.
- The `time_slots` and `tentative_busy` parameters for Availability requests have been removed.

### Unchanged Calendar endpoints

- Check a calendar for availability: [`POST /calendars/availability`](/docs/api/v3/ecc/#post-/v3/calendars/availability)

### Migrated Calendar endpoints

- Return all calendars: `GET /calendars` → [`GET /v3/grants/<NYLAS_GRANT_ID>/calendars`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/calendars)
- Create a calendar: `POST /calendars` → [`POST /v3/grants/<NYLAS_GRANT_ID>/calendars`](/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/calendars)
- Return a calendar: `GET /calendars/<CALENDAR_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/calendars/<CALENDAR_ID>`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/calendars/-calendar_id-)
- Update a calendar: `PUT /calendars/<CALENDAR_ID>` → [`PUT /v3/grants/<NYLAS_GRANT_ID>/calendars/<CALENDAR_ID>`](/docs/api/v3/ecc/#put-/v3/grants/-grant_id-/calendars/-calendar_id-)
- Delete a calendar: `DELETE /calendars/<CALENDAR_ID>` → [`DELETE /v3/grants/<NYLAS_GRANT_ID>/calendars/<CALENDAR_ID>`](/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/calendars/-calendar_id-)
- Check a calendar for free/busy status: `POST /calendars/free-busy` → [`POST /v3/grants/<NYLAS_GRANT_ID>/calendars/free-busy`](/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/calendars/free-busy)
- Return room resources information: `GET /resources` -> [`GET /v3/grants/<NYLAS_GRANT_ID>/resources`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/resources)

### Deprecated Calendar endpoints

- Get availability for multiple consecutive meetings: `POST /calendars/availability/consecutive`
- Generate ICS file: `POST /events/to-ics`

### Migrated Events endpoints

- Return all events: `GET /events` → [`GET /v3/grants/<NYLAS_GRANT_ID>/events`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/events)
- Create an event: `POST /events` → [`POST /v3/grants/<NYLAS_GRANT_ID>/events`](/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/events)
- Return an event: `GET /events/<EVENT_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/events/<EVENT_ID>`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/events/-event_id-)
- Update an event: `PUT /events/<EVENT_ID>` → [`PUT /v3/grants/<NYLAS_GRANT_ID>/events/<EVENT_ID>`](/docs/api/v3/ecc/#put-/v3/grants/-grant_id-/events/-event_id-)
- Delete an event: `DELETE /events/<EVENT_ID>` → [`DELETE /v3/grants/<NYLAS_GRANT_ID>/events/<EVENT_ID>`](/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/events/-event_id-)
- Send RSVP: `POST /send-rsvp` → [`POST /v3/grants/<NYLAS_GRANT_ID>/events/<EVENT_ID>/send-rsvp`](/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/events/-event_id-/send-rsvp)

### Removed Events parameters

- `event_id` query parameter for `GET` calls.
- `updated_at_before` for `GET` calls.
- `updated_at_before` for `GET` calls.
- `participants` query parameter for `GET` calls.
- `customer_event_id` query parameter and property for all calls.
- `notifications property` for `POST` and `PUT` calls.
- `original_start_time property` for `GET` calls.
- `organizer_email property` for `GET` calls.
- `organizer_name property` for `GET` calls.
- `owner property is` for `GET` calls.
- `message_id` for `GET` calls.
- `event.recurrence.timezone` for `GET` calls.

## Changes to virtual calendars in v3

- Virtual calendars now use the v3 Calendar and Events APIs, and all Calendar-related endpoint changes apply to virtual calendars.
- Each grant can now have up to 10 virtual calendars.
- You must now provide an identifier when you create a grant for a virtual calendar. This can be any arbitrary string.
- Added the option to specify a primary calendar.
  - By default, the first virtual calendar associated with a grant is considered the primary.

## Changes to Email in v3


- All Messages and Drafts endpoints now require a `grant_id`, an email address, or — if you're using access token authentication — the [`/me/` construction](#me-syntax-for-api-calls).
- **Labels and Folders** have been consolidated into **Folders**.
  - `folder` → `folders` for all Messages and Threads calls.
  - `labels` → `folders` for all Messages and Threads calls.
- **Files** are now called **Attachments**.
  - Previously, you used the `files` endpoints to add files to messages. Now, you use the Drafts and Message-Send endpoints to add attachments, and the Attachments APIs to get information about the attachments. For more information, see [Working with email attachments](/docs/v3/email/attachments/).
- You can now send drafts.
- You can schedule a send time for a message, and edit or delete scheduled send times.
- You can now soft-delete messages and threads.
- The new `message.send_success` and `message.send_failed` notifications allow you to track the results of a scheduled send.
- The new `message.bounce_detected` notification is available to check for message bounces from Google, Microsoft Graph, iCloud, and Yahoo.
- The `schedule_id`, `send_at`, and `use_draft` parameters have been added to `POST` calls.
- The `/messages/search` endpoint has been deprecated. Instead, you now include a URL-encoded provider query string in a [`GET /v3/grants/<NYLAS_GRANT_ID>/messages` request](/docs/reference/api/messages/get-messages/).
- The `/threads/search` endpoint has been deprecated. Instead, you now include a URL-encoded provider query string in a [`GET /v3/grants/<NYLAS_GRANT_ID>/threads` request](/docs/reference/api/threads/get-threads/).
- The `not_in` and `filename` query parameters have been deprecated for `GET` calls.
- The `view=count` query parameter has been deprecated for `GET` calls.
- The `events` and `cids` properties have been deprecated for `GET` calls.
- By default, Nylas now stores messages on 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.


### New Email endpoints

- Delete a message: [`DELETE /v3/grants/<NYLAS_GRANT_ID>/messages/<MESSAGE_ID>`](/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/messages/-message_id-)
- Get a scheduled message: [`GET /v3/grants/<NYLAS_GRANT_ID>/messages/schedules/<SCHEDULE_ID>`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/messages/schedules/-scheduleId-)
- Delete a scheduled-send instance: [`DELETE /v3/grants/<NYLAS_GRANT_ID>/messages/schedules/<SCHEDULE_ID>`](/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/messages/schedules/-scheduleId-) (This doesn't delete the message, just the send-schedule.)

### Migrated Email endpoints

- Return all messages: `GET /messages` → [`GET /v3/grants/<NYLAS_GRANT_ID>/messages`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/messages)
- Return a message: `GET /messages/<MESSAGE_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/messages/<MESSAGE_ID>`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/messages/-message_id-)
- Update a message: `PUT /messages/<MESSAGE_ID>` → [`PUT /v3/grants/<NYLAS_GRANT_ID>/messages/<MESSAGE_ID>`](/docs/api/v3/ecc/#put-/v3/grants/-grant_id-/messages/-message_id-)
- Search for a message: `GET /messages/search` → search parameters with [`GET /v3/grants/<NYLAS_GRANT_ID>/messages`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/messages/-message_id-)
- Send a message: `POST /send` → [`POST /v3/grants/<NYLAS_GRANT_ID>/messages/send`](/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/messages/send)
- Return all drafts: `GET /drafts` → [`GET /v3/grants/<NYLAS_GRANT_ID>/drafts`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/drafts)
- Create a draft: `POST /drafts` → [`POST /v3/grants/<NYLAS_GRANT_ID>/drafts`](/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/drafts)
- Return a draft: `GET /drafts/<DRAFT_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/drafts/<DRAFT_ID>`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/drafts/-draft_id-)
- Update a draft: `PUT /drafts/<DRAFT_ID>` → [`PUT /v3/grants/<NYLAS_GRANT_ID>/drafts/<DRAFT_ID>`](/docs/api/v3/ecc/#put-/v3/grants/-grant_id-/drafts/-draft_id-)
- Delete a draft: `DELETE /drafts/<DRAFT_ID>` → [`DELETE /v3/grants/<NYLAS_GRANT_ID>/drafts/<DRAFT_ID>`](/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/drafts/-draft_id-)
- Return all scheduled messages: `GET /outbox` → [`GET /v3/grants/<NYLAS_GRANT_ID>/messages/schedules`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/messages/schedules)

### Removed Email endpoints

- All `/outbox` endpoints (one `GET` can be migrated; see above).
- All `/files` endpoints. Use the Drafts or Messages/Send endpoints instead. [Learn more](/docs/v3/email/attachments/).

### Changes to message tracking in v3

- The `tracking` sub-object has been renamed `tracking_options`.
- The `payload` in the `recent` object is now `label`.
- The `id` in the `recent` object has been changed to `click_id` for link clicked tracking, and `opened_id` for message open tracking.

### Changes to email search in v3

In Nylas v2, you could only search email messages on IMAP providers by subject and body contents. In v3, you can search using [all standard IMAP SEARCH operators](https://datatracker.ietf.org/doc/html/rfc3501#section-6.4.4).

## Changes to Threads in v3

The Threads API has been retooled for Nylas v3.

### New Threads endpoint

- Delete a thread: [`DELETE /v3/grants/<NYLAS_GRANT_ID>/threads/<THREAD_ID>`](/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/threads/-thread_id-)

### Migrated Threads endpoints

- All `/threads` endpoints → `/v3/grants/<NYLAS_GRANT_ID>/threads`

### New Threads response fields

The Threads API now returns the following fields in request responses, in addition to the fields returned in v2.7:

- `latest_draft_or_message`
- `has_drafts`

### Updated Threads response fields

- `first_message_timestamp` → `earliest_message_date`
- `last_message_received_timestamp` → `latest_message_received_date`
- `last_message_sent_timestamp` → `latest_message_sent_date`

### Removed Threads response fields and query params

- `labels` response field: Threads are now organized by `folders` (see [Changes to Folders and Labels](#changes-to-folders-and-labels-in-v3)).
- `last_message_timestamp` response field: Replaced by the `latest_draft_or_message.date` subobject.
- `view=expanded` query param: No longer supported.

## Changes to Folders and Labels in v3

In v3, Labels have been combined with Folders. Folders are a straightforward replacement for v3; Labels are pretty much the same.

### Migrated Folders and Labels endpoints

- Return all labels → Return all folders (`GET /labels` → [`GET /v3/grants/<NYLAS_GRANT_ID>/folders`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/folders))
- Create a label → Create a folder (`POST /labels` → [`POST /v3/grants/<NYLAS_GRANT_ID>/folders`](/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/folders))
- Return a label → Return a folder (`GET /labels/<LABEL_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/folders/<FOLDER_ID>`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/folders/-folder_id-))
- Update a label → Update a folder (`PUT /labels/<LABEL_ID>` → [`PUT /v3/grants/<NYLAS_GRANT_ID>/folders/<FOLDER_ID>`](/docs/api/v3/ecc/#put-/v3/grants/-grant_id-/folders/-folder_id-))
- Delete a label → Delete a folder (`DELETE /labels/<LABEL_ID>` → [`DELETE /v3/grants/<NYLAS_GRANT_ID>/folders/<FOLDER_ID>`](/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/folders/-folder_id-))
- Return all folders: `GET /folders` → [`GET /v3/grants/<NYLAS_GRANT_ID>/folders`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/folders)
- Create a folder: `POST /folders` → [`POST /v3/grants/<NYLAS_GRANT_ID>/folders`](/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/folders)
- Return a folder: `GET /folders/<FOLDER_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/folders/<FOLDER_ID>`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/folders/-folder_id-)
- Update a folder: `PUT /folders/<FOLDER_ID>` → [`PUT /v3/grants/<NYLAS_GRANT_ID>/folders/<FOLDER_ID>`](/docs/api/v3/ecc/#put-/v3/grants/-grant_id-/folders/-folder_id-)
- Delete a folder: `DELETE /folders/<FOLDER_ID>` → [`DELETE /v3/grants/<NYLAS_GRANT_ID>/folders/<FOLDER_ID>`](/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/folders/-folder_id-)

## Changes to Contacts in v3

Contacts are no longer listed in simple comma-separated values, but are now returned as JSON objects.

### Migrated Contacts endpoints

- Return all contacts: `GET /contacts` → [`GET /v3/grants/<NYLAS_GRANT_ID>/contacts`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/contacts)
- Create a contact: `POST /contacts` → [`POST /v3/grants/<NYLAS_GRANT_ID>/contacts`](/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/contacts)
- Return a contact: `GET /contacts/<CONTACT_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/contacts/<CONTACT_ID>`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/contacts/-contact_id-)
- Update a contact: `PUT /contacts/<CONTACT_ID>` → [`PUT /v3/grants/<NYLAS_GRANT_ID>/contacts/<CONTACT_ID>`](/docs/api/v3/ecc/#put-/v3/grants/-grant_id-/contacts/-contact_id-)
- Delete a contact: `DELETE /contacts/<CONTACT_ID>` → [`DELETE /v3/grants/<NYLAS_GRANT_ID>/contacts/<CONTACT_ID>`](/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/contacts/-contact_id-)
- Return all contact groups: `GET /contacts/groups` → [`GET /v3/grants/<NYLAS_GRANT_ID>/contacts/groups`](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/contacts/groups)

### Removed Contacts endpoints

The `GET /contacts/<CONTACT_ID>/picture` endpoint has been deprecated. Instead, you can now include the `?profile_picture=true` query parameter in a [Get Contact request](/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/contacts/-contact_id-) to get the contact's profile picture.