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

# Overview

> Learn how to authenticate with client credentials for use with the Corti API.

<Note>
  This guide covers authentication for use with the Corti API. If you are
  looking for authenticating users with Corti Assistant Embedded, then see more
  [here](/assistant/authentication).
</Note>

## Authenticating with Corti Auth

Corti uses OAuth 2.0 client credentials for server-to-server authentication. This flow requires that you fetch a short-lived access token based on a `client_id` and `client_secret` from the Corti Auth Server before calling the API.

```mermaid theme={null}
%%{init: {
  "sequence": {
    "mirrorActors": false,
    "boxTextMargin": 20
  }
}}%%
sequenceDiagram
    participant Service as Your Backend
    participant OAuth as Corti Auth
    participant Corti as Corti API

    Service->>OAuth: POST /token<br/>grant_type=client_credentials<br/>client_id, client_secret
    OAuth-->>Service: 200 OK<br/>access_token (short-lived)

    Service->>Corti: API Request<br/>Authorization: Bearer {{access_token}}<br/>Tenant-Name: base
    Corti-->>Service: API Response
```

Note that both the client secret and the access tokens generated have full access to the API. They should never be shared or exposed to the client. For best practices on keeping your credentials secure, read [our guide](/authentication/security_best_practices).

<Tip>
  Need to open a real-time speech-to-text WebSocket directly from a browser? Request a **limited-scope token** with `scope="openid transcribe"` and/or `scope="openid streams"`. The resulting token can only be used against the corresponding streaming endpoints — see [Limited-scope credentials for streaming APIs](/authentication/security_best_practices#4-if-you-must-use-tokens-in-special-cases-use-limited-scope-credentials).
</Tip>

### Fetching an Access Token with OAuth 2.0 client-credentials

<CodeGroup>
  ```bash title="cURL (base realm)" theme={null}
  # Replace these with your values
  CLIENT_ID="<your-client-id>"
  CLIENT_SECRET="<your-client-secret>"
  ENVIRONMENT="<eu-or-us>"

  curl \
    "https://auth.${ENVIRONMENT}.corti.app/realms/base/protocol/openid-connect/token" \
    -H 'Content-Type: application/x-www-form-urlencoded' \
    -d "client_id=${CLIENT_ID}" -d "client_secret=${CLIENT_SECRET}" \
    -d 'grant_type=client_credentials' -d 'scope=openid'
  ```

  ```bash title="cURL (custom tenant)" theme={null}
  # Replace these with your values
  CLIENT_ID="<your-client-id>"
  CLIENT_SECRET="<your-client-secret>"
  ENVIRONMENT="<eu-or-us>"
  TENANT="<your-tenant-name>"

  curl \
    "https://auth.${ENVIRONMENT}.corti.app/realms/${TENANT}/protocol/openid-connect/token" \
    -H 'Content-Type: application/x-www-form-urlencoded' \
    -d "client_id=${CLIENT_ID}" -d "client_secret=${CLIENT_SECRET}" \
    -d 'grant_type=client_credentials' -d 'scope=openid'
  ```
</CodeGroup>

```json title="Response" theme={null}
{
  "access_token": "eyJhbGciOi...",
  "expires_in": 300,
  "token_type": "Bearer",
  "scope": "profile openid email"
}
```

For more detailed instructions on how to get an access token in various languages, see our guide here: [Authentication Quickstart](/authentication/quickstart)

### Using the access token in API requests

Once you have an access token, include it in the Authorization header. You must also provide the Tenant-Name header to specify which tenant context the request operates in.

```curl title="Example request" theme={null}
curl -X GET "https://api.$environment.corti.app/v2/interactions" \
  -H "Authorization: Bearer {{access_token}}" \
  -H "Tenant-Name: base"
```

<Expandable title="headers">
  <ParamField path="Authorization" type="string" required>
    Must contain the bearer token returned from the OAuth server.
  </ParamField>

  <ParamField path="Tenant-Name" type="string" required>
    The tenant identifier where the request is executed. Default tenants
    typically use `base`, but enterprise setups may use a custom tenant name.
  </ParamField>
</Expandable>

## Why we use client credentials instead of an API key

API keys are simple, but they are static. If one leaks, whoever has it can call your APIs until you rotate it. Client credentials solve this by issuing short-lived tokens that expire automatically, which limits the blast radius of a leak and improves auditability.

Key differences:

* API keys are long-lived, client credentials produce short-lived tokens (5 minutes).
* API keys cannot express scopes or granular permissions, OAuth tokens can.
* OAuth flows integrate with identity providers and tenancy models, which makes them safer and easier to govern in enterprise environments.
