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

# Authentication

> Obtain and use an OAuth 2.0 access token for the chmod API.

The chmod API uses the OAuth 2.0 **client credentials** grant. Your backend exchanges a
client id and secret for a short-lived bearer token, then sends that token on every call.

<Warning>
  These credentials belong on your server only. Never ship them in a mobile app, a
  browser bundle or a public repository. Your app receives an `sdk_token` scoped to a
  single transaction instead — that is the whole point of the split.
</Warning>

## Request a token

<CodeGroup>
  ```bash cURL lines theme={null}
  curl -X POST https://{your-account}.auth.us-east-1.amazoncognito.com/oauth2/token \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "grant_type=client_credentials" \
    -d "client_id=$CHMOD_CLIENT_ID" \
    -d "client_secret=$CHMOD_CLIENT_SECRET" \
    -d "scope=account-integration-api/account-api-access"
  ```

  ```typescript Node.js lines theme={null}
  const body = new URLSearchParams({
    grant_type:    "client_credentials",
    client_id:     process.env.CHMOD_CLIENT_ID!,
    client_secret: process.env.CHMOD_CLIENT_SECRET!,
    scope:         "account-integration-api/account-api-access",
  });

  const res = await fetch(`${COGNITO_URL}/oauth2/token`, {
    method:  "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body,
  });

  const { access_token, expires_in } = await res.json();
  ```

  ```python Python lines theme={null}
  import os, requests

  res = requests.post(
      f"{COGNITO_URL}/oauth2/token",
      data={
          "grant_type":    "client_credentials",
          "client_id":     os.environ["CHMOD_CLIENT_ID"],
          "client_secret": os.environ["CHMOD_CLIENT_SECRET"],
          "scope":         "account-integration-api/account-api-access",
      },
  )
  access_token = res.json()["access_token"]
  ```
</CodeGroup>

### Parameters

<ParamField body="grant_type" type="string" required>
  Always `client_credentials`.
</ParamField>

<ParamField body="client_id" type="string" required>
  Your account's OAuth client id.
</ParamField>

<ParamField body="client_secret" type="string" required>
  Your account's OAuth client secret.
</ParamField>

<ParamField body="scope" type="string" required>
  Always `account-integration-api/account-api-access`.
</ParamField>

### Response

```json lines theme={null}
{
  "access_token": "eyJraWQiOiJ...",
  "expires_in": 3600,
  "token_type": "Bearer"
}
```

<ResponseField name="access_token" type="string">
  The bearer token to send on API calls.
</ResponseField>

<ResponseField name="expires_in" type="integer">
  Lifetime in seconds.
</ResponseField>

<ResponseField name="token_type" type="string">
  Always `Bearer`.
</ResponseField>

## Use the token

Every request to the chmod API carries the token in the `Authorization` header, with the `Bearer` scheme:

```bash lines theme={null}
curl https://{your-api-host}/api/account/integration/kyc/transaction \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

The same header goes on every endpoint — creating customers, creating transactions and reading results. There is nothing else to sign and no per-request nonce.

A token is valid for one hour. Reuse it across requests until it expires; when the API answers `401`, request a new one and retry. Tokens are not single-use, and requesting a new one does not invalidate the previous one.

<Info>
  The token identifies your account, not a user. Requests made with it act on your account's customers and transactions, so keep it on the server and never forward it to a device.
</Info>


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