> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nextlevelmca.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Security

> How assistant connections are protected: a one-time sign-in code, one person and one workspace per connection, approve exactly what an assistant may do, revoke any time.

An AI assistant connected to NextLevel MCA is a team member's access, delegated. This page is what keeps that safe, whether the assistant is Claude, ChatGPT or something your own developers build.

## What a broker needs to know

* **Sign-in is a one-time code to your work email.** No password is ever shared with the assistant. The code is six digits, works once, expires in ten minutes, and only three can be sent to an address every fifteen minutes. The page asks for a code whether or not the address is known, so it cannot be used to work out who is a user.
* **Each connection is one person in one workspace.** The assistant acts as the person who signed in, with that person's role and their view of the pipeline, in the workspace they picked. A record in another workspace does not exist as far as the connection is concerned.
* **You approve exactly what the assistant may do.** The consent screen lists every permission in plain words, ticked by default; untick anything the connection should not do. A permission can never grant more than the person's own role allows, and an assistant that later asks for more sees the consent screen again.
* **Revoke any time.** **Settings → Developers → Connected apps** shows every connection in the workspace with who made it, which assistant, what it may do and when it was last used, and ends any of them with one click. Deactivating a user ends all of theirs.
* **Access expires and rotates on its own.** The assistant's access is short-lived and renewed quietly in the background; a renewal that is used twice, the sign of a stolen token, shuts the whole connection down. A connection unused for a month, or older than ninety days, has to sign in again.
* **Nothing sensitive is stored in the clear.** Sign-in codes and tokens are stored only as hashes. Social security numbers never leave the platform: not through the API, not to an assistant, not in notifications.
* **The assistant can only do what the app can do.** Every tool runs the same code as the app and the API, with the same permission checks and the same pipeline rules.

## For developers

NextLevel MCA runs its own OAuth 2.1 authorization server at `https://api.nextlevelmca.com`. Claude and ChatGPT need no configuration; the details below are for building your own client.

### Discovery

| Document | URL |
| - | - |
| Protected resource metadata | `https://mcp.nextlevelmca.com/.well-known/oauth-protected-resource` (its `resource` is exactly `https://mcp.nextlevelmca.com`; clients that connect to `…/mcp` get the path-aware document at `/.well-known/oauth-protected-resource/mcp`) |
| Authorization server metadata | `https://api.nextlevelmca.com/.well-known/oauth-authorization-server` |
| JWKS | `https://api.nextlevelmca.com/oauth/jwks` |

* An unauthenticated request to the MCP server returns `401` with `WWW-Authenticate: Bearer resource_metadata="https://mcp.nextlevelmca.com/.well-known/oauth-protected-resource"`, which is how clients find the authorization server without configuration.
* Endpoints: `/oauth/authorize`, `/oauth/token`, `/oauth/register`, `/oauth/revoke`. Supported: `response_type=code`, grants `authorization_code` and `refresh_token`, PKCE `S256` only, public clients (`token_endpoint_auth_method: "none"`). `scopes_supported` lists every scope on the [Access and permissions](/developers/authentication) page.

### Registering a client

* `POST /oauth/register` is open, as MCP expects. Send `client_name` and `redirect_uris`, optionally `logo_uri`, `client_uri`, `grant_types` and `token_endpoint_auth_method`.
* Redirect URIs must be absolute `https` URLs (`http://localhost` and `http://127.0.0.1` on any port are allowed for local clients), with no wildcards or fragments.
* The response is `201` with a `client_id`; there is no client secret. Limited to 10 registrations per hour per IP address; clients unused for 90 days are removed.

### Authorization flow

1. `GET /oauth/authorize` with `response_type=code`, `client_id`, `redirect_uri`, `scope`, `state`, `code_challenge`, `code_challenge_method=S256` and optionally `resource`. `client_id` and `redirect_uri` are validated first; on failure an error page is rendered and nothing is redirected to an unvalidated URI. Parameters are held server-side under an opaque id for 30 minutes.
2. The user enters their email and the 6-digit code (single use, 10 minutes, 3 per email per 15 minutes). The session cookie is signed, `HttpOnly`, `Secure`, `SameSite=Lax` and lives 30 minutes.
3. Users in several workspaces pick one; the grant is pinned to it.
4. Consent lists the client, the workspace and each scope. An empty `scope` means every scope, trimmed by the checkboxes (Claude and ChatGPT send none). An existing, unrevoked consent that covers the scopes skips this step when the client names the scopes it wants. When it names none, the consent screen appears again, ticked as approved last time, so reconnecting is how you narrow what an app may do. Approving replaces the stored scopes.
5. The authorization code is bound to the client, redirect URI, scopes, workspace and PKCE challenge, expires after **60 seconds** and is single use; presenting a consumed code revokes everything issued from it.
6. `POST /oauth/token` (JSON or form-encoded) with `grant_type=authorization_code`, `code`, `redirect_uri`, `client_id` and `code_verifier` returns an access token, a refresh token, `expires_in: 3600` and the granted `scope`. Limited to 60 requests per minute per IP address.

### Tokens

* **Access tokens** are RS256-signed JWTs valid for **1 hour**, verified against the JWKS by `kid`. Claims: `iss` (`https://api.nextlevelmca.com`), `sub` (the user id), `aud` (the `resource` requested, by default `https://mcp.nextlevelmca.com`), `location_id`, `scope`, `client_id`, `iat`, `exp`, `jti`. The MCP server accepts only tokens whose `aud` is its own URL, so a token cannot be replayed against another service; `/v1` accepts tokens minted for either.
* **Refresh tokens** are opaque, stored hashed, and rotate on every use within a family; presenting an already-rotated token revokes the whole family. The one exception is a client refreshing twice at once: a token presented again within 30 seconds of its rotation, while its family is still live, gets a fresh pair in the same family. Lifetime is **30 days, sliding** on each rotation, capped at **90 days** from the first grant.
* Every token, code and sign-in code is stored as a SHA-256 hash. On every request the server also checks that the user is still active in the workspace and that the connection has not been revoked (cached for up to a minute).

### Revocation

* Revoking in **Settings → Developers → Connected apps** deletes the consent and every refresh-token family for that user, client and workspace; outstanding access tokens stop working at their next use, within a minute.
* Clients can `POST /oauth/revoke` with a refresh token to revoke its family, which also stops the family's access tokens.
* Agency connections are listed under **Super Admin → Sign-in → AI connections**, where **Disconnect** ends one right away.
* Removing the connector inside Claude or ChatGPT discards the client's tokens but leaves the consent in place, so revoke in the app as well when offboarding.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.