Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Nylas IAM principals API
version: v3
summary: The complete Nylas v3 API — Email, Calendar, Contacts, Notetaker, Scheduling, Administration, and Migration.
description: The Nylas API is designed using the REST ideology to provide simple and predictable URIs to access and modify objects. Requests support standard HTTP methods like `GET`, `PUT`, `POST`, and `DELETE`, and standard status codes. Response bodies are always UTF-8 encoded JSON objects, unless explicitly documented otherwise. You can use the Nylas Postman collection to quickly start using the Nylas APIs. For more information, check out the Nylas Postman collection documentation.
contact:
url: https://www.nylas.com/
servers:
- url: https://api.us.nylas.com
description: U.S.
- url: https://api.eu.nylas.com
description: E.U.
security:
- ACCESS_TOKEN: []
- NYLAS_API_KEY: []
tags:
- name: IAM principals
description: 'Manage reusable IAM identities, their resource bindings, roles, and direct permissions. Requests require an organization-bound IAM API key with the corresponding `iam.principals.*` permission. Start with the IAM API guide.
## Principal and credential limits
IAM limits start with a base allowance and increase as you bind principals to resources. **N** is the number of distinct applications, workspaces, and grants directly referenced by at least one non-deleted principal''s resource binding. Resources without a principal binding don''t count. Multiple principals bound to the same resource count that resource once. Organization bindings don''t increase N.
| Object | Limit |
| ----------------------------------- | ---------------------------------------------------- |
| Principals per organization | `100 + 2N` |
| Active credentials per organization | `2 × (100 + 2N)` |
| Credentials per principal | 10 total, including disabled and expired credentials |
Suppose your organization has **1 application, 2 workspaces, and 3 grants**. The limits depend on which resources have principal bindings:
| Principal bindings | N | Principal limit | Active credential limit |
| ------------------------------------------------------------------------- | --- | --------------- | ----------------------- |
| No principals are bound to any of the six resources | 0 | 100 | 200 |
| One principal is bound to one grant | 1 | 102 | 204 |
| Ten principals are all bound to the same grant | 1 | 102 | 204 |
| At least one principal is bound to each application, workspace, and grant | 6 | 112 | 224 |
| Principals are bound only to the organization | 0 | 100 | 200 |
Binding a principal to a grant counts that grant; it doesn''t also count the grant''s parent application or workspace. Those resources count only when they have their own principal bindings. With 10 distinct bound resources, the limits are 120 principals and 240 active credentials. Every principal still has a separate limit of 10 total credentials.
Deleting a credential frees its per-principal slot; disabling it doesn''t. Disabling or deleting a key releases its active organization capacity. Expired keys release organization capacity when background reconciliation processes them. Nylas rejects a binding change that lowers the organization''s principal limit below current usage.
A quota failure returns **400** with `error.code` set to `api.resource_limit_exceeded`, `error.type` set to `api.invalid_request`, and `error.details` containing `resource_type`, `limit`, and `current`. Remove unused objects or disable active keys as appropriate before retrying. Reserve credential capacity for rotation.'
paths:
/v3/iam/principals:
get:
summary: List IAM principals
tags:
- IAM principals
operationId: list-iam-principals
description: 'Requires `iam.principals.read` on an active principal bound to the authenticated organization. Authenticate with an active, unexpired IAM credential of type `api_key`. Application API keys (including legacy API keys) and provider OAuth tokens cannot authorize IAM management endpoints. Use an existing IAM credential with these permissions, or create your first management credential in the Dashboard.
Use next_cursor from the response as page_token on the next request. When next_cursor is absent, there are no more results.'
security:
- IAM_API_KEY: []
x-permissions:
- iam.principals.read
parameters:
- in: query
name: limit
schema:
type: integer
minimum: 1
maximum: 200
default: 50
description: Maximum results per page.
- in: query
name: page_token
schema:
type: string
maxLength: 2048
description: Opaque next_cursor from the previous response.
- in: query
name: resource_binding_type
schema:
type: string
enum:
- organization
- application
- workspace
- grant
description: Filter by binding type. Must be supplied with resource_binding_id.
- in: query
name: resource_binding_id
schema:
type: string
maxLength: 256
description: Filter by binding ID. Must be supplied with resource_binding_type.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
request_id:
type: string
description: Request ID for troubleshooting.
data:
type: array
items:
$ref: '#/components/schemas/Principal'
next_cursor:
type: string
description: Opaque cursor. Absent on the final page. Pass as page_token.
example:
request_id: 5fa64c92-e840-4357-86b9-2aa364d35b88
data:
- id: 9Xf3LmQa2rP7sTuV0wYzB
organization_id: <NYLAS_ORGANIZATION_ID>
name: Support mailbox reader
description: Reads the support mailbox
status: active
roles:
- role_system_messages_reader
direct_permissions: []
resource_binding:
type: grant
id: <NYLAS_GRANT_ID>
created_at: 1791417600
updated_at: 1791417600
'400':
description: Invalid request or object quota exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Invalid, disabled, deleted, or expired authentication credential
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Missing management permission or organization binding
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Principal or credential not found in this organization
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflicting principal or credential state
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Too many requests
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
x-code-samples:
- lang: bash
label: cURL
source: "curl --request GET \\\n --url \"https://api.us.nylas.com/v3/iam/principals\" \\\n --header \"Authorization: Bearer $NYLAS_IAM_ADMIN_KEY\"\n"
post:
summary: Create IAM principal
tags:
- IAM principals
operationId: create-iam-principal
description: 'Requires `iam.principals.create` on an active principal bound to the authenticated organization. Authenticate with an active, unexpired IAM credential of type `api_key`. Application API keys (including legacy API keys) and provider OAuth tokens cannot authorize IAM management endpoints. Use an existing IAM credential with these permissions, or create your first management credential in the Dashboard.
Creates a principal with exactly one resource binding. The organization comes from the caller credential; do not supply organization_id. Unknown fields and null values are rejected.'
security:
- IAM_API_KEY: []
x-permissions:
- iam.principals.create
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PrincipalCreate'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
request_id:
type: string
description: Request ID for troubleshooting.
data:
$ref: '#/components/schemas/Principal'
example:
request_id: 5fa64c92-e840-4357-86b9-2aa364d35b88
data:
id: 9Xf3LmQa2rP7sTuV0wYzB
organization_id: <NYLAS_ORGANIZATION_ID>
name: Support mailbox reader
description: Reads the support mailbox
status: active
roles:
- role_system_messages_reader
direct_permissions: []
resource_binding:
type: grant
id: <NYLAS_GRANT_ID>
created_at: 1791417600
updated_at: 1791417600
'400':
description: Invalid request or object quota exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Invalid, disabled, deleted, or expired authentication credential
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Missing management permission or organization binding
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Principal or credential not found in this organization
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflicting principal or credential state
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Too many requests
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
x-code-samples:
- lang: bash
label: cURL
source: "curl --request POST \\\n --url \"https://api.us.nylas.com/v3/iam/principals\" \\\n --header \"Authorization: Bearer $NYLAS_IAM_ADMIN_KEY\" \\\n --header \"Content-Type: application/json\" \\\n --data '{\"name\": \"Support mailbox reader\", \"roles\": [\"role_system_messages_reader\"], \"resource_binding\": {\"type\": \"grant\", \"id\": \"<NYLAS_GRANT_ID>\"}}'\n"
- lang: javascript
label: Node.js (HTTP)
source: "const requiredEnvironment = (name) => {\n const value = process.env[name]?.trim();\n if (!value) throw new Error(`Set ${name} before running this example`);\n return value;\n};\nconst adminKey = requiredEnvironment(\"NYLAS_IAM_ADMIN_KEY\");\n// Node.js 22+: direct HTTP, without SDK-specific IAM methods.\nconst response = await fetch(\"https://api.us.nylas.com/v3/iam/principals\", {\n method: \"POST\",\n signal: AbortSignal.timeout(30000),\n headers: {\n Authorization: `Bearer ${adminKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n name: \"Support mailbox reader\",\n roles: [\"role_system_messages_reader\"],\n resource_binding: {\n type: \"grant\",\n id: requiredEnvironment(\"NYLAS_GRANT_ID\"),\n },\n }),\n});\nif (!response.ok)\n throw new Error(`Principal creation failed (${response.status})`);\nconst { data: principal } = await response.json();\nconsole.log(principal.id);\n"
- lang: python
label: Python (HTTP)
source: "import json\nimport os\nfrom urllib.request import Request, urlopen\n\nrequest = Request(\n \"https://api.us.nylas.com/v3/iam/principals\",\n method=\"POST\",\n headers={\n \"Authorization\": f\"Bearer {os.environ['NYLAS_IAM_ADMIN_KEY']}\",\n \"Content-Type\": \"application/json\",\n },\n data=json.dumps({\n \"name\": \"Support mailbox reader\",\n \"roles\": [\"role_system_messages_reader\"],\n \"resource_binding\": {\"type\": \"grant\", \"id\": os.environ[\"NYLAS_GRANT_ID\"]},\n }).encode(),\n)\nwith urlopen(request, timeout=30) as response:\n principal = json.load(response)[\"data\"]\nprint(principal[\"id\"])\n"
/v3/iam/principals/{principal_id}:
parameters:
- in: path
name: principal_id
required: true
schema:
type: string
description: ID of the principal in the authenticated organization.
get:
summary: Get IAM principal
tags:
- IAM principals
operationId: get-iam-principal
description: Requires `iam.principals.read` on an active principal bound to the authenticated organization. Authenticate with an active, unexpired IAM credential of type `api_key`. Application API keys (including legacy API keys) and provider OAuth tokens cannot authorize IAM management endpoints. Use an existing IAM credential with these permissions, or create your first management credential in the Dashboard.
security:
- IAM_API_KEY: []
x-permissions:
- iam.principals.read
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
request_id:
type: string
description: Request ID for troubleshooting.
data:
$ref: '#/components/schemas/Principal'
example:
request_id: 5fa64c92-e840-4357-86b9-2aa364d35b88
data:
id: 9Xf3LmQa2rP7sTuV0wYzB
organization_id: <NYLAS_ORGANIZATION_ID>
name: Support mailbox reader
description: Reads the support mailbox
status: active
roles:
- role_system_messages_reader
direct_permissions: []
resource_binding:
type: grant
id: <NYLAS_GRANT_ID>
created_at: 1791417600
updated_at: 1791417600
'400':
description: Invalid request or object quota exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Invalid, disabled, deleted, or expired authentication credential
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Missing management permission or organization binding
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Principal or credential not found in this organization
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflicting principal or credential state
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Too many requests
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
x-code-samples:
- lang: bash
label: cURL
source: "curl --request GET \\\n --url \"https://api.us.nylas.com/v3/iam/principals/${NYLAS_PRINCIPAL_ID}\" \\\n --header \"Authorization: Bearer $NYLAS_IAM_ADMIN_KEY\"\n"
patch:
summary: Update IAM principal
tags:
- IAM principals
operationId: update-iam-principal
description: 'Requires `iam.principals.update` on an active principal bound to the authenticated organization. Authenticate with an active, unexpired IAM credential of type `api_key`. Application API keys (including legacy API keys) and provider OAuth tokens cannot authorize IAM management endpoints. Use an existing IAM credential with these permissions, or create your first management credential in the Dashboard.
Each supplied field replaces its current value. Omitted fields stay unchanged. An empty roles or direct_permissions array clears that assignment set; an empty description clears the description. resource_binding replaces the single binding. Empty bodies, null values, unknown fields, and add/remove payloads are rejected. When active credentials exist, a non-Organization binding must resolve to exactly one application. A change that violates this invariant returns 409. The last active organization-bound IAM Admin cannot be deleted, disabled, or lose that binding or role.'
security:
- IAM_API_KEY: []
x-permissions:
- iam.principals.update
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PrincipalUpdate'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
request_id:
type: string
description: Request ID for troubleshooting.
data:
$ref: '#/components/schemas/Principal'
example:
request_id: 5fa64c92-e840-4357-86b9-2aa364d35b88
data:
id: 9Xf3LmQa2rP7sTuV0wYzB
organization_id: <NYLAS_ORGANIZATION_ID>
name: Support mailbox reader
description: Reads the support mailbox
status: active
roles:
- role_system_messages_reader
direct_permissions: []
resource_binding:
type: grant
id: <NYLAS_GRANT_ID>
created_at: 1791417600
updated_at: 1791417600
'400':
description: Invalid request or object quota exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Invalid, disabled, deleted, or expired authentication credential
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Missing management permission or organization binding
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Principal or credential not found in this organization
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflicting principal or credential state
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Too many requests
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
x-code-samples:
- lang: bash
label: cURL
source: "curl --request PATCH \\\n --url \"https://api.us.nylas.com/v3/iam/principals/${NYLAS_PRINCIPAL_ID}\" \\\n --header \"Authorization: Bearer $NYLAS_IAM_ADMIN_KEY\" \\\n --header \"Content-Type: application/json\" \\\n --data '{\"direct_permissions\": [\"messages.read\"]}'\n"
delete:
summary: Delete IAM principal
tags:
- IAM principals
operationId: delete-iam-principal
description: 'Requires `iam.principals.delete` on an active principal bound to the authenticated organization. Authenticate with an active, unexpired IAM credential of type `api_key`. Application API keys (including legacy API keys) and provider OAuth tokens cannot authorize IAM management endpoints. Use an existing IAM credential with these permissions, or create your first management credential in the Dashboard.
Permanently deletes the principal and its credentials. The last active organization-bound IAM Admin cannot be deleted. A successful response contains request_id and no data.'
security:
- IAM_API_KEY: []
x-permissions:
- iam.principals.delete
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
request_id:
type: string
description: Request ID for troubleshooting.
example:
request_id: 5fa64c92-e840-4357-86b9-2aa364d35b88
'400':
description: Invalid request or object quota exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Invalid, disabled, deleted, or expired authentication credential
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Missing management permission or organization binding
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Principal or credential not found in this organization
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflicting principal or credential state
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Too many requests
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
x-code-samples:
- lang: bash
label: cURL
source: "curl --request DELETE \\\n --url \"https://api.us.nylas.com/v3/iam/principals/${NYLAS_PRINCIPAL_ID}\" \\\n --header \"Authorization: Bearer $NYLAS_IAM_ADMIN_KEY\"\n"
components:
schemas:
PrincipalCreate:
type: object
additionalProperties: false
required:
- name
- resource_binding
properties:
name:
type: string
description: Descriptive workload name. Surrounding whitespace is removed.
minLength: 1
maxLength: 128
example: Support mailbox reader
description:
type: string
description: Optional workload description.
maxLength: 1024
default: ''
status:
type: string
description: Whether the principal or credential can authenticate.
enum:
- active
- disabled
default: active
roles:
type: array
description: System or custom role IDs. Duplicate IDs are removed. Use the Dashboard to manage custom roles. Accepts up to 100 distinct IDs. Accepts up to 100 distinct IDs.
items:
type: string
example:
- role_system_messages_reader
direct_permissions:
type: array
description: Canonical permission IDs assigned directly to the principal. Duplicate IDs are removed. Accepts up to 100 distinct IDs. Accepts up to 100 distinct IDs.
items:
type: string
example:
- messages.read
resource_binding:
$ref: '#/components/schemas/ResourceBinding'
Principal:
type: object
required:
- id
- organization_id
- name
- description
- status
- roles
- direct_permissions
- resource_binding
- created_at
- updated_at
properties:
id:
type: string
description: Opaque principal ID.
organization_id:
type: string
description: Organization inferred from the authenticating IAM API key.
name:
type: string
description: Descriptive workload name. Surrounding whitespace is removed.
minLength: 1
maxLength: 128
example: Support mailbox reader
description:
type: string
description: Optional workload description.
maxLength: 1024
default: ''
status:
type: string
description: Whether the principal or credential can authenticate.
enum:
- active
- disabled
default: active
roles:
type: array
description: System or custom role IDs. Duplicate IDs are removed. Use the Dashboard to manage custom roles. Accepts up to 100 distinct IDs. Accepts up to 100 distinct IDs.
items:
type: string
example:
- role_system_messages_reader
direct_permissions:
type: array
description: Canonical permission IDs assigned directly to the principal. Duplicate IDs are removed. Accepts up to 100 distinct IDs. Accepts up to 100 distinct IDs.
items:
type: string
example:
- messages.read
resource_binding:
anyOf:
- $ref: '#/components/schemas/ResourceBinding'
- type: 'null'
description: The single binding. May be null if its resource was removed and reconciliation cleared the binding.
created_at:
type: integer
format: int64
description: Unix timestamp in seconds.
updated_at:
type: integer
format: int64
description: Unix timestamp in seconds.
example:
id: 9Xf3LmQa2rP7sTuV0wYzB
organization_id: <NYLAS_ORGANIZATION_ID>
name: Support mailbox reader
description: Reads the support mailbox
status: active
roles:
- role_system_messages_reader
direct_permissions: []
resource_binding:
type: grant
id: <NYLAS_GRANT_ID>
created_at: 1791417600
updated_at: 1791417600
ResourceBinding:
type: object
additionalProperties: false
required:
- type
- id
properties:
type:
type: string
description: Resource boundary for this principal.
enum:
- organization
- application
- workspace
- grant
id:
type: string
description: ID of a resource in the authenticated organization.
minLength: 1
maxLength: 256
example:
type: grant
id: <NYLAS_GRANT_ID>
Error:
type: object
properties:
request_id:
type: string
description: Request ID for troubleshooting.
error:
type: object
required:
- type
- message
properties:
code:
type: string
description: Error code.
type:
type: string
description: Error category.
message:
type: string
description: Description of the failure.
details:
type: object
description: Additional error context. Quota errors include resource_type, limit, and current.
properties:
resource_type:
type: string
limit:
type: integer
current:
type: integer
PrincipalUpdate:
type: object
additionalProperties: false
minProperties: 1
properties:
name:
type: string
description: Descriptive workload name. Surrounding whitespace is removed.
minLength: 1
maxLength: 128
example: Support mailbox reader
description:
type: string
description: Optional workload description.
maxLength: 1024
status:
type: string
description: Whether the principal or credential can authenticate.
enum:
- active
- disabled
roles:
type: array
description: System or custom role IDs. Duplicate IDs are removed. Use the Dashboard to manage custom roles. Accepts up to 100 distinct IDs.
items:
type: string
example:
- role_system_messages_reader
direct_permissions:
type: array
description: Canonical permission IDs assigned directly to the principal. Duplicate IDs are removed. Accepts up to 100 distinct IDs.
items:
type: string
example:
- messages.read
resource_binding:
$ref: '#/components/schemas/ResourceBinding'
securitySchemes:
IAM_API_KEY:
type: http
scheme: bearer
bearerFormat: IAM API key
description: An active, unexpired IAM credential of type `api_key` whose principal is active, has an Organization resource binding, and has the required IAM management permission. Use an existing IAM credential with these permissions, or [create your first management credential in the Dashboard](/docs/v3/auth/nylas-iam/manage-principals-with-api/#create-a-management-credential-in-the-dashboard). Application API keys (including legacy API keys) and provider OAuth tokens cannot authorize IAM management endpoints.
ACCESS_TOKEN:
scheme: bearer
type: http
bearerFormat: NYLAS_ACCESS_TOKEN
description: 'The Nylas **access token** for a specific grant. Issued as part of OAuth 2.1 flow token
exchange.'
NYLAS_API_KEY:
scheme: bearer
type: http
bearerFormat: NYLAS_API_KEY
description: 'The Nylas **API key** provides application-level access to APIs and all grants. You can
generate these from the Dashboard. Learn more about [authorizing requests](/docs/v3/auth/).'
SCHEDULER_SESSION_TOKEN:
scheme: bearer
type: http
bearerFormat: Session ID
description: The Nylas Scheduler **session ID** that Scheduler UI Components use to authorize API requests.
x-provenance:
method: harvested
publisher: Nylas
source: https://developer.nylas.com/openapi.json
note: split by refine-openapis from the provider's own published document, verified by fetch (openapi/_original/*.fetch.json);
stamped by stamp-openapi-provenance.py (roadmap#793)