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

# Authentication

> How to authenticate with the KeyStone OS API using M2M tokens and user tokens.

KeyStone OS uses Auth0 for authentication. There are two authentication methods depending on your use case.

## M2M tokens (platform integration)

M2M (Machine-to-Machine) tokens are for server-to-server communication where no human user is involved. Your backend exchanges its `client_id` and `client_secret` for a short-lived access token via the Auth0 Client Credentials flow. This is the primary authentication method for platforms calling the KeyStone API.

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://auth.keystoneos.xyz/oauth/token \
    --header 'content-type: application/json' \
    --data '{
      "client_id": "YOUR_CLIENT_ID",
      "client_secret": "YOUR_CLIENT_SECRET",
      "audience": "https://api.keystoneos.xyz",
      "grant_type": "client_credentials"
    }'
  ```

  ```typescript TypeScript SDK theme={null}
  import { KeystoneClient } from "@keystoneos/sdk";

  // The SDK handles token acquisition and refresh automatically
  const client = new KeystoneClient({
    clientId: "YOUR_CLIENT_ID",
    clientSecret: "YOUR_CLIENT_SECRET",
  });

  // Tokens are fetched on first request and cached until expiry
  const settlements = await client.settlements.list();
  ```

  ```python Python SDK theme={null}
  from keystoneos import KeystoneClient

  # The SDK handles token acquisition and refresh automatically
  async with KeystoneClient(
      client_id="YOUR_CLIENT_ID",
      client_secret="YOUR_CLIENT_SECRET",
  ) as client:
      # Tokens are fetched on first request and cached until expiry
      settlements = await client.settlements.list()
  ```
</CodeGroup>

**Environment resolution:** Your M2M client ID is linked to a specific platform environment. The API automatically resolves which environment you are operating in based on your credentials.

**Scopes:** M2M tokens carry scopes that define what operations are permitted:

| Scope                      | Description                                     |
| -------------------------- | ----------------------------------------------- |
| `settlements:read`         | View settlements and events                     |
| `settlements:write`        | Create settlements, submit compliance decisions |
| `templates:read`           | View settlement templates                       |
| `platform:read`            | View platform details                           |
| `platform:webhooks:manage` | Manage webhook endpoints                        |

## User tokens (dashboard access)

For interactive [KeyStone Dashboard](https://app.keystoneos.xyz) access, users authenticate via Auth0 Organizations using PKCE flow. User tokens carry `permissions` instead of `scope`.

Team members can be invited and managed in the dashboard under **Members**. Each member is assigned a role that controls which dashboard features they can access.

**Environment header:** User tokens must include the `X-Keystone-Environment` header to specify which environment to operate in:

```
X-Keystone-Environment: production
```

This is required because a user may have access to multiple environments (e.g. sandbox, production).

## IP allowlisting

Environments can optionally restrict API access to specific IP addresses. When configured, only requests from allowlisted IPs are accepted for M2M tokens in that environment.

Configure IP allowlists in the [KeyStone Dashboard](https://app.keystoneos.xyz) under **Settings > Security**. You can add individual IPs or CIDR ranges, each with an optional description.

<Note>
  When no IPs are configured, all addresses are permitted. Adding the first IP immediately restricts access to only allowlisted addresses.
</Note>

## Token lifecycle

| Property    | Value                              |
| ----------- | ---------------------------------- |
| Token type  | JWT (RS256)                        |
| Expiry      | 24 hours                           |
| Refresh     | Request a new token before expiry  |
| Rate limits | Contact support for current limits |

## Example: authenticated request

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.keystoneos.xyz/v1/settlements \
    -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
    -H "Content-Type: application/json"
  ```

  ```typescript TypeScript SDK theme={null}
  // Auth is handled automatically by the client
  const { items } = await client.settlements.list();
  ```

  ```python Python SDK theme={null}
  # Auth is handled automatically by the client
  result = await client.settlements.list()
  ```
</CodeGroup>

<Card title="Next: Your first settlement" icon="arrow-right" href="/getting-started/first-settlement">
  Walk through a complete settlement end-to-end.
</Card>
