# Bring Your Own Authentication

> **POST** `https://api.us.nylas.com/v3/connect/custom`

Source: https://developer.nylas.com/docs/reference/api/manage-grants/byo_auth/

Manually creates a grant using the Bring Your Own (BYO) Authentication flow. If you're handling the
OAuth flow in your own project or you want to migrate existing users, BYO Auth lets you provide
the user's `refresh_token` to create a grant.

If a user previously authenticated with your Nylas application using the same email address, Nylas
detects this and re-authenticates their existing grant instead of creating a new one. The API
response contains the user's existing `grant_id`.

### Supported providers

Pick the request body variant that matches your provider:

- **Refresh token** — OAuth providers (`google`, `microsoft`, `yahoo`, `zoom`) using a standard refresh token.
- **Credential override** — OAuth providers, but using a stored [credential record](/docs/reference/api/connector-credentials/) to swap in different client credentials.
- **Microsoft bulk auth** — Microsoft App Permissions. Requires a [connector credential](/docs/reference/api/connector-credentials/create_credential/) and the [admin consent flow](/docs/v3/auth/bulk-auth-grants/#make-a-microsoft-admin-consent-flow-request-using-nylas-apis).
- **Google bulk auth** — Google Service Accounts. Requires a [connector credential](/docs/reference/api/connector-credentials/create_credential/) and the [Service Account flow](/docs/v3/auth/bulk-auth-grants/#google-app-permission-via-nylas).
- **IMAP** — direct IMAP/SMTP credentials for any IMAP provider.
- **iCloud** — an iCloud email address plus an [Apple app password](https://support.apple.com/en-us/HT204397).
- **EWS** — on-premises Microsoft Exchange; hosted Exchange should use Microsoft Graph instead.
- **Virtual calendar** — a [Virtual Calendar](/docs/v3/calendar/virtual-calendars/) grant for scheduling without a third-party provider.
- **Zoom Meetings** — Zoom OAuth. Your OAuth app must include the [granular scopes](https://developers.zoom.us/docs/integrations/oauth-scopes-granular/) `meeting:write:meeting`, `meeting:update:meeting`, and `meeting:delete:meeting`.
- **Nylas (Agent Account)** — a fully Nylas-hosted [Agent Account](/docs/v3/agent-accounts/) email and calendar mailbox on a domain you've registered with Nylas.

**Authentication:** NYLAS_API_KEY

## Request body

Content-Type: application/json

- **Refresh token**
  - `provider` (string) **(required)** - The user's OAuth provider.
  - `settings` (object) **(required)** - A list of settings required by the provider, including the `refresh_token`.
    - `refresh_token` (string) - The refresh token associated with the email account.
- **Credential override**
  - `provider` (string) **(required)** - The user's OAuth provider.
  - `settings` (object) **(required)** - A list of settings required by the provider, including the `refresh_token`.

If you add the `credential_id` field with the UUID of an existing
[credential record](/docs/reference/api/connector-credentials/), Nylas uses the
provider's `client_id` and `client_secret` from the credential record.
    - `refresh_token` (string) - The refresh token associated with the email account.
    - `credential_id` (string) - The UUID of an existing
[credential record](/docs/reference/api/connector-credentials/) that Nylas
can use to override the default connector settings.
- **Microsoft bulk auth**
  - `provider` (string) **(required)** - The user's OAuth provider.
  - `settings` (object) **(required)** - A list of settings required by Microsoft. This sets the user's email address and
the Nylas `credential_id`.

If a grant already exists for the provided email address, Nylas automatically starts
the re-authentication process.
    - `email_address` (string) - The user's email address.
    - `credential_id` (string) - The ID of an existing `adminconsent` credential that Nylas can use to
authenticate Microsoft App Permission grants.
- **Google bulk auth**
  - `provider` (string) **(required)** - The user's OAuth provider.
  - `settings` (object) **(required)** - A list of settings required by Google. This sets the user's email address and the
Nylas `credential_id`.

If a grant already exists for the provided email address, Nylas automatically starts
the re-authentication process.
    - `email_address` (string) - The user's email address.
    - `credential_id` (string) - The ID of an existing `serviceaccount` credential that Nylas can use to
authenticate Google Service Account grants.
    - `scopes` (array) - A list of scopes for the grant.
- **IMAP**
  - `provider` (string) **(required)** - The user's provider.
  - `settings` (object) **(required)** - A list of settings needed for Nylas to connect to the provider's IMAP server. If
the provider uses a different address or credentials for SMTP (to send email),
include that information separately in the SMTP fields.
    - `imap_username` (string) - The user's username or email address.
    - `imap_password` (string) - The user's email account password or app password.
    - `imap_host` (string) - The IMAP host. If you don't define the host in the request payload, Nylas tries
to auto-detect the hostname using the provided `imap_username`. If you're using
a self-hosted IMAP server, you _must_ provide the hostname.
    - `imap_port` (integer) - The IMAP port number. If you don't define the port in the request payload, Nylas
tries to auto-detect it using the provided `imap_username`. If you're using a
self-hosted IMAP server, you _must_ provide the port number.
    - `smtp_host` (string) - The SMTP host. If you don't define the host in the request payload, Nylas tries
to auto-detect it using the provided `imap_username`. If you're using a self-
hosted SMTP server, you _must_ provide the hostname.
    - `smtp_port` (integer) - The SMTP port number. If you don't define the port in the request payload, Nylas
tries to auto-detect it using the provided `imap_username`. If you're using a
self-hosted SMTP server, you _must_ provide the port number.
    - `smtp_username` (string) - The user's SMTP username, if their SMTP credentials are different from their
IMAP credentials.
    - `smtp_password` (string) - The user's SMTP password, if their SMTP credentials are different from their
IMAP credentials.
- **iCloud**
  - `provider` (string) **(required)** - The user's provider.
  - `settings` (object) **(required)** - A list of settings required by iCloud.
    - `username` (string) - The user's iCloud email address.
    - `password` (string) - The user's app password.
- **EWS**
  - `provider` (string) **(required)** - The user's provider.
  - `settings` (object) **(required)** - A list of settings required by EWS.
    - `email` (string) - The user's email address.
    - `ews_username` (string) - The user's Exchange username, formatted as an email address.
    - `ews_password` (string) - The user's Microsoft Exchange password.
    - `ews_host` (string) - The EWS host. If you don't define the host in the request payload, Nylas tries
to auto-detect it using the provided `ews_username`. If you're using a self-
hosted EWS server, you _must_ provide the hostname.
    - `ews_port` (integer) - The EWS port number.
  - `scope` (array) - A list of scopes for the grant.
- **Virtual calendar**
  - `provider` (string) **(required)** - The account's provider.
  - `settings` (object) **(required)** - A list of settings required by Nylas.
    - `email` (string) - The virtual account identifier. This can be any arbitrary string — it doesn't
have to be in email address format.
  - `state` (string) - An optional state value that Nylas returns to your project when the authentication
flow completes. If you include the `state`, Nylas returns the unmodified value to
your project. You can use this for verification, or to track information about the
account.

For more information about the `state` parameter, see the
[OAuth 2.0 specification](https://datatracker.ietf.org/doc/html/rfc6749) or the
[official OAuth 2.0 documentation](https://www.oauth.com/oauth2-servers/authorization/the-authorization-request/).
- **Zoom Meetings**
  - `provider` (string) **(required)** - The user's OAuth provider (in this case, `zoom`).
  - `settings` (object) **(required)** - A list of settings required by Zoom.
    - `refresh_token` (string) - The `refresh_token` from the Zoom `code` exchange flow.
- **Nylas (Agent Account)**
  - `provider` (string) **(required)** - The account's provider. Use `nylas` to create an Agent Account.
  - `name` (string) - The Agent Account's display name. Nylas stores this as the grant's `name` and uses it
as the default `From` display name when the account sends email, so a recipient sees
`Sales Agent <sales-agent@agents.yourcompany.com>` instead of the bare address. Omit it
and the account sends with no display name. You can override the name on an individual
message with the `from` field on [send](/docs/reference/api/messages/send-message/).
  - `workspace_id` (string) - The ID of the [workspace](/docs/reference/api/workspaces/) to place the Agent Account in.
The workspace's `policy_id` and `rule_ids` govern the account's limits, spam detection,
and mail rules. If omitted, Nylas auto-groups the account into a workspace whose `domain`
matches the email address (when `auto_group` is enabled), or places it in the
application's default workspace.
  - `settings` (object) **(required)** - The settings required for a Nylas Agent Account.
    - `email` (string) **(required)** - The Agent Account's email address. The email's domain must match a domain you've already
[registered with Nylas](/docs/reference/api/manage-domains/).
    - `app_password` (string) - Optional password that unlocks IMAP and SMTP-submission access to the Agent Account.
Omit it and protocol-level access stays disabled. Must be 18–40 printable ASCII
characters (codes 33–126) and contain at least one uppercase letter, one lowercase
letter, and one digit. Stored as a bcrypt hash — it can't be retrieved later, only
reset by updating the grant. See [Connect mail clients to an Agent Account](/docs/v3/agent-accounts/mail-clients/).

## Responses

### 201 - Grant Created

- `request_id` (string) - The request ID.
- `data` (object)
  - `account_id` (string) - The v2 Nylas account ID. This field appears only if the grant was created by migrating a v2
connected account.
  - `blocked` (boolean) - When `true`, indicates that the grant is blocked from accessing the Nylas APIs.
  - `created_at` (integer) **(required)** - When the grant was created, in seconds using the Unix timestamp format.
  - `email` (string) - The email address associated with the grant. If the provider supports `id_token` and exposes the
user's email address, Nylas automatically extracts this value.
  - `grant_status` (string) - Specifies whether the grant is valid or the user needs to re-authenticate.
  - `id` (string) **(required)** - A unique identifier for the grant.
  - `ip` (string) - The user's client IP address. Mostly useful for
[Hosted OAuth](/docs/v3/auth/hosted-oauth-apikey/).
  - `name` (string) - The user's display name.
  - `provider` (string) **(required)** - The provider that the user authenticated with.
  - `provider_user_id` (string) - The user's provider ID. This field might be changed at any time by the provider.
  - `scope` (array) **(required)** - An array of [granular scopes](/docs/dev-guide/scopes/) associated with the grant. If none are
specified, Nylas uses the default scopes from the
[connector](/docs/reference/api/connectors-integrations/).
  - `settings` (object) - A list of settings associated with the grant. The contents of this object might differ between
grants or depending on the provider.
  - `email_aliases` (array) - An array of found email aliases for this grant. Only returned if special query parameter `expose_aliases` for 
[Get Grant](/docs/reference/api/manage-grants/get_grant_by_id/) is used and set to `true`.
Applicable only for Google and Microsoft grants.
  - `state` (string) - The initial state that was set as part of the authentication process. Nylas passes this value
back to your project without modifying it. You can use this field for verification, or to track
information about the user.
  - `updated_at` (integer) - When the user last authenticated their grant, in seconds using the Unix timestamp format.
Initially, this value is the same as `created_at`.
  - `user_agent` (string) - The user's [client or browser information](https://www.useragents.me/). Mostly useful for
[Hosted OAuth](/docs/v3/auth/hosted-oauth-apikey/).
  - `workspace_id` (string) - The ID of the Workspace the grant belongs to, if any. For grants from providers other than
Agent Accounts, Nylas may omit this field when the grant is in the application's default
workspace.
  - `credential_id` (string) - The ID of the Credential the grant is associated with. Grant will use this Credential for provider communication.

### 400 - Bad Request

- `request_id` (string) **(required)** - ID of the request
- `error` (object) **(required)** - Error object
  - `type` (string) - Type of error
  - `message` (string) - Informative error message
  - `provider_error` (object) - (OPTIONAL) informative error message from provider's side

### 401 - Not Authenticated

- `request_id` (string) **(required)** - ID of the request
- `error` (object) **(required)** - Error object
  - `type` (string) - Type of error
  - `message` (string) - Informative error message
  - `provider_error` (object) - (OPTIONAL) informative error message from provider's side

## Code samples

### cURL (Microsoft)

```bash
curl --request POST \
  --url "https://api.us.nylas.com/v3/connect/custom" \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "provider": "microsoft",
    "settings": {
      "refresh_token": "<REFRESH_TOKEN>"
    }
  }'

```

### cURL (Google)

```bash
curl --request POST \
  --url "https://api.us.nylas.com/v3/connect/custom" \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "provider": "google",
    "settings": {
      "refresh_token": "<GOOGLE_REFRESH_TOKEN>"
    }
  }'

```

### cURL (IMAP)

```bash
curl --request POST \
  --url "https://api.us.nylas.com/v3/connect/custom" \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "provider": "imap",
    "settings": {
      "imap_username": "user@example.com",
      "imap_password": "<IMAP_PASSWORD>",
      "imap_host": "imap.example.com",
      "imap_port": 993,
      "smtp_host": "smtp.example.com",
      "smtp_port": 587,
      "smtp_username": "user@example.com",
      "smtp_password": "<SMTP_PASSWORD>"
    }
  }'

```

### cURL (iCloud)

```bash
curl --request POST \
  --url "https://api.us.nylas.com/v3/connect/custom" \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "provider": "icloud",
    "settings": {
      "username": "user@icloud.com",
      "password": "<ICLOUD_APP_PASSWORD>"
    }
  }'

```

### cURL (Virtual Calendar)

```bash
curl --request POST \
  --url "https://api.us.nylas.com/v3/connect/custom" \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "provider": "virtual-calendar",
    "settings": {
      "email": "conference-room-3a@example.com"
    }
  }'

```

### cURL (Nylas Agent Account)

```bash
curl --location 'https://api.us.nylas.com/v3/connect/custom' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "provider": "nylas",
    "name": "Sales Agent",
    "workspace_id": "<WORKSPACE_ID>",
    "settings": {
        "email": "user@yourdomain.com"
    }
}'

```

### Node.js SDK

```javascript
import Nylas from "nylas";

const nylas = new Nylas({
  apiKey: "<NYLAS_API_KEY>",
  apiUri: "<NYLAS_API_URI>",
});

// Microsoft (refresh-token) Bring-Your-Own-Auth grant.
async function authenticateMicrosoft() {
  const grant = await nylas.auth.customAuthentication({
    requestBody: {
      provider: "microsoft",
      settings: {
        refreshToken: "<MICROSOFT_REFRESH_TOKEN>",
      },
      scope: ["Mail.Read", "Mail.Send"],
    },
  });

  return grant;
}

// Nylas Agent Account grant — provisions a Nylas-hosted mailbox on a domain
// you've registered with Nylas. No OAuth refresh token required.
async function authenticateAgentAccount() {
  const grant = await nylas.auth.customAuthentication({
    requestBody: {
      provider: "nylas",
      name: "Sales Agent",
      settings: {
        email: "agent@yourdomain.com",
        policyId: "<POLICY_ID>",
      },
    },
  });

  return grant;
}

authenticateMicrosoft()
  .then((grant) => console.log("Microsoft grant:", grant))
  .catch((error) => console.error("Microsoft auth error:", error));

authenticateAgentAccount()
  .then((grant) => console.log("Agent Account grant:", grant))
  .catch((error) => console.error("Agent Account auth error:", error));

```

### Ruby SDK

```ruby
require 'nylas'

nylas = Nylas::Client.new(
  api_key: "<NYLAS_API_KEY>",
)

request_body = {
  provider: '<PROVIDER>',
  settings: {'username': '<USERNAME>', 'password': '<PASSWORD>'},
  scope: 'email.read_only,calendar.read_only,contacts.read_only',
  state: '<STATE>'
}

auth = nylas.auth.custom_authentication(request_body)
puts auth

```

### Python SDK

```python
from nylas import Client

nylas = Client(
    "<NYLAS_API_KEY>",
    "<NYLAS_API_URI>",
)

request_body = {
    "provider": "icloud",
    "settings": {
        "username": "<USERNAME>",
        "password": "<PASSWORD>",
    },
    "scope": ["email.read_only", "calendar.read_only", "contacts.read_only"],
    "state": "<STATE>",
}

grant = nylas.auth.custom_authentication(request_body)
print(grant)

```

### Java SDK

```java
import com.nylas.NylasClient;
import com.nylas.models.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Main {
    public static void main(String[] args) throws
            NylasSdkTimeoutError, NylasApiError {
        NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();

        AuthProvider provider = AuthProvider.ICLOUD;

        Map<String, Object> settings = new HashMap<>();
        settings.put("username", "<USERNAME>");
        settings.put("password", "<PASSWORD>");

        List<String> scopes = List.of(
            "email.read_only", "calendar.read_only", "contacts.read_only");

        CreateGrantRequest requestBody = new CreateGrantRequest.Builder(provider, settings)
            .state("<STATE>")
            .scopes(scopes)
            .build();

        Response<Grant> grant = nylas.auth().customAuthentication(requestBody);
        System.out.println(grant);
    }
}

```

### Kotlin SDK

```kotlin
import com.nylas.NylasClient
import com.nylas.models.*

fun main() {
    val nylas: NylasClient = NylasClient(
        apiKey = "<NYLAS_API_KEY>"
    )

    val provider = AuthProvider.ICLOUD
    val settings = mapOf("username" to "<USERNAME>", "password" to "<PASSWORD>")
    val scopes = listOf("email.read_only", "calendar.read_only", "contacts.read_only")

    val requestBody = CreateGrantRequest(provider, settings, "<STATE>", scopes)
    val grant = nylas.auth().customAuthentication(requestBody)

    println(grant)
}

```
