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

# Authentication

> Get authenticated and start testing our API

Authenticate securely to the Profile API using **Access Tokens**. We support two modern strategies:

* **Machine-to-Machine (M2M)** for your own backend services
* **OAuth 2.1** for any integration that acts on behalf of a user: third-party apps, AI agents, dashboards

## Machine-to-Machine (M2M) Authentication

M2M authentication is designed for **backend services, internal automations, and server-to-server integrations**.
It uses **access tokens** that are scoped to your organization and expire automatically.

### How It Works

1. **Request an Access Token**

   Exchange your `client_id` and `client_secret` for an access token. Credentials can be supplied either in the request body or as HTTP Basic Auth:

   ```http theme={"system"}
   POST https://vanguard.profilebehavior.com/api/v4/auth
   Content-Type: application/json

   {
     "grant_type": "client_credentials",
     "client_id": "your_client_id",
     "client_secret": "your_client_secret"
   }
   ```

   Or, equivalently, with Basic Auth:

   ```http theme={"system"}
   POST https://vanguard.profilebehavior.com/api/v4/auth
   Authorization: Basic base64(client_id:client_secret)
   ```

   Response:

   ```json theme={"system"}
   {
     "access_token": "eyJhbGciOi...",
     "token_type": "Bearer",
     "expires_in": 3600
   }
   ```

2. **Include the Token in API Requests**

   Add the access token to the `Authorization` header:

   ```http theme={"system"}
   Authorization: Bearer YOUR_ACCESS_TOKEN
   ```

3. **Tokens Expire**

   Access tokens are short-lived and expire after **approximately 1 hour**.
   Request a new one when the previous token is near expiry.

### Example (cURL)

```bash theme={"system"}
curl --request POST \
  --url https://vanguard.profilebehavior.com/api/v4/test \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{"ping": "pong"}'
```

## OAuth 2.1 Authentication

OAuth 2.1 is for integrations that **act on behalf of a specific Profile user**. That covers third-party apps, AI agents and MCP servers, CLI tools, and any browser-based dashboard where a user signs in.

Tokens issued under OAuth are scoped to one Profile account (the one the user consented from) and carry OAuth **scopes** that narrow what the integration can do. The same bearer token works against the REST API (`/api/v4/*`) and the MCP endpoint (`/mcp`).

### Discovery

Fetch the OAuth protected-resource metadata to learn where the authorization server lives and what scopes exist:

```http theme={"system"}
GET /.well-known/oauth-protected-resource HTTP/1.1
Host: vanguard.profilebehavior.com
```

```json theme={"system"}
{
  "resource": "https://vanguard.profilebehavior.com",
  "authorization_servers": ["https://login.profilebehavior.com"],
  "scopes_supported": [
    "profiles:read",
    "profiles:write",
    "tags:manage",
    "account:read",
    "account:write"
  ],
  "bearer_methods_supported": ["header"]
}
```

On any 401 from a protected endpoint, the response includes a `WWW-Authenticate: Bearer resource_metadata="..."` header pointing at this document, so clients can discover it automatically.

### Client Registration

You have two ways to register an OAuth client:

* **Pre-registered integrations.** For a production integration you build or operate (your own dashboard, an internal tool, a specific third-party connector), contact support to register a client and receive a `client_id` (and `client_secret` for confidential clients).
* **Dynamic Client Registration (DCR).** MCP agents and other on-the-fly clients can register themselves at the authorization server's DCR endpoint. See the authorization server's discovery document at `https://login.profilebehavior.com/.well-known/oauth-authorization-server` for the registration URL. No pre-provisioning required.

### How It Works

1. **Redirect to authorize**

   Send the user's browser to the authorization endpoint with the standard OAuth 2.1 query params (`client_id`, `redirect_uri`, `response_type=code`, `scope`, `state`, `code_challenge`, `code_challenge_method=S256`):

   ```
   https://login.profilebehavior.com/oauth/authorize?client_id=...&redirect_uri=...&response_type=code&scope=profiles:read+tags:manage&state=...&code_challenge=...&code_challenge_method=S256
   ```

2. **Consent**

   Profile shows the user a branded consent screen listing your app, the account they're connecting, and the scopes requested. On approval, Profile redirects the browser back to your `redirect_uri` with an authorization code.

3. **Token exchange**

   Exchange the code for an access token at the token endpoint:

   ```http theme={"system"}
   POST https://login.profilebehavior.com/oauth/token
   Content-Type: application/x-www-form-urlencoded

   grant_type=authorization_code&code=...&redirect_uri=...&client_id=...&code_verifier=...
   ```

4. **Make API requests**

   Include the token as a bearer in the `Authorization` header:

   ```http theme={"system"}
   Authorization: Bearer USER_ACCESS_TOKEN
   ```

### Scopes

Scopes are the unit of authorization for OAuth tokens. A token can only perform operations covered by the scopes the user granted. Users see and can deny each scope on the consent screen, and can revoke an entire connection at any time from the **Connected apps** section of their user profile.

Request only the scopes your integration actually needs. Over-asking on the consent screen is the single most common reason users deny a connection.

#### `profiles:read`

Read access to profiles and their behavioral data.

**Allows:**

* Listing profiles on the connected account
* Reading a profile's name, email, and phone
* Reading DISC, Focus, and Core assessment scores
* Reading AI-generated behavioral debriefs (and triggering generation of a debrief if one doesn't exist yet)

**Does not allow:** creating, modifying, or deleting profiles; accessing profiles on accounts the user isn't signed in to.

**Typical use:** any integration that summarizes or analyzes behavioral data, including AI assistants answering questions about people on the team.

#### `profiles:write`

Full profile lifecycle. Includes creating profiles via assessment invite.

**Allows:**

* Creating new profiles (sends a real assessment invite email or SMS)
* Updating profile metadata
* Deleting profiles
* Resending invite links

**Does not allow:** reading behavioral scores (request `profiles:read` alongside if you need both).

**Typical use:** HR tools, onboarding automations, roster-management integrations.

#### `tags:manage`

Full CRUD on tags and tag membership.

**Allows:**

* Listing, creating, renaming, recoloring, and deleting tags
* Replacing the set of profiles attached to a tag

**Does not allow:** creating or modifying profiles. The profiles a tag references must already exist on the account.

**Typical use:** cohort-management, group-assignment, and filtering workflows.

#### `account:read`

Read access to account-level metadata.

**Allows:**

* Reading account name, logo, and preferences
* Reading the assessment catalog
* Reading resource aliases (external ID mappings)

**Does not allow:** reading profiles or behavioral data (that's `profiles:read`).

**Typical use:** diagnostic and reporting tools that need context about the account they're connected to.

#### `account:write`

Modify account-level settings.

**Allows:**

* Updating account logo and preferences
* Creating, updating, and deleting resource aliases

**Does not allow:** deleting the account, changing billing, or modifying users.

**Typical use:** integrations that need to keep resource-alias mappings in sync with an external system.

### Scope enforcement

Every API request is validated against the token's granted scopes before the handler runs. An OAuth client calling an endpoint without the corresponding scope receives a 403 with a descriptive error message. There is no silent degradation or partial success.

### Example OAuth Request

```http theme={"system"}
GET /api/v4/account HTTP/1.1
Host: vanguard.profilebehavior.com
Authorization: Bearer eyJhbGciOi... (access token)
```

## Which Authentication Method Should I Use?

| Use Case                                     | Auth Type |
| -------------------------------------------- | --------- |
| Your own backend services talking to our API | ✅ M2M     |
| Cron jobs & internal automation              | ✅ M2M     |
| Third-party apps acting on a user's behalf   | ✅ OAuth   |
| AI agents and MCP servers (ChatGPT, Claude)  | ✅ OAuth   |
| User-facing apps where a person signs in     | ✅ OAuth   |

## Security Notes

* **Never expose client secrets** in frontend apps or browser-based code. Public clients (browser, mobile, CLI) must use PKCE instead.
* **Access tokens are short-lived** (\~1 hour). Use refresh tokens to obtain new access tokens without re-prompting the user.
* OAuth users authenticate through Profile's secure login. **Passwords are never shared** with external tools.
* Users can view and revoke any connected app from the **Connected apps** section of their user profile at any time.
