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

# Request an Access Token

> Sign an ES256 client assertion and exchange it for a short-lived bearer access token using the OAuth 2.0 JWT bearer client assertion flow.

Authentication uses the OAuth 2.0 **JWT bearer client assertion** flow ([RFC 7523](https://datatracker.ietf.org/doc/html/rfc7523)) with a `client_credentials` grant. No client secret is ever transmitted.

You need:

* Your **`OAuthClientId`** and **`KID`** from your onboarding pack.
* The **private key** (`es256-private.pem`) matching the public key you registered. See [Key pair setup](/api-reference/authentication/key-pair-setup).

## Step 1: Build the client assertion

Build a JWT and sign it with your **private** ES256 key.

**Header**

```json theme={null}
{ "alg": "ES256", "typ": "JWT", "kid": "<KID>" }
```

**Payload**

```json theme={null}
{
  "iss": "<OAuthClientId>",
  "sub": "<OAuthClientId>",
  "aud": "cb-gateway-m2m-blue",
  "jti": "<random UUID>",
  "iat": 1790812800,
  "exp": 1790812920
}
```

| Claim | Value |
| - | - |
| `iss`, `sub` | Both **must** equal your `OAuthClientId`. |
| `aud` | **Must** be exactly `cb-gateway-m2m-blue`. It is not the gateway URL. |
| `jti` | A new random UUID for every assertion. Assertions are single-use. |
| `iat` | The current time, in Unix seconds. |
| `exp` | `iat` plus 120 seconds. Assertions are short-lived by design. |

## Step 2: Exchange it for an access token

`POST` the assertion to the token endpoint as `application/x-www-form-urlencoded`. See the [endpoint reference](/api-reference/create-jwt-token) for the full schema.

```http theme={null}
POST /api/security/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=<signed JWT>
&OAuthClientId=<OAuthClientId>
```

The response is JSON containing an `accessToken` field, valid for 30 minutes (`expiresIn: 1800`). No refresh token is issued to M2M clients, so `refreshToken` is always `null`.

## Step 3: Call the API

Send the token as a bearer token on every request:

| Header | Value |
| - | - |
| `Authorization` | `Bearer <accessToken>` |
| `Content-Type` | `application/json` |
| `Accept` | `application/json` |

Request a fresh token when it expires rather than caching it long-term.

## Full example

See [Sample scripts](/api-reference/authentication/sample-scripts) for runnable TypeScript and Python versions of the full flow. Your onboarding pack includes the same scripts with your details filled in.

## Troubleshooting

### 401 from the token endpoint

The token endpoint returns the same empty `401` for every rejected assertion. Check each of these:

* The header `alg` is `ES256` and `kid` is the `KID` of a key that is registered and not revoked.
* `iss` is exactly your `OAuthClientId`. We look up your public key by `iss` and `kid`.
* `aud` is exactly `cb-gateway-m2m-blue`.
* `exp` is present and in the future. We allow 30 seconds of clock skew, so check the machine clock if failures persist.
* `jti` is present and new. A `jti` cannot be reused within 10 minutes.
* The assertion is signed with the private key that matches the public key you registered.

### 401 "Unauthorized to access." from API routes

The access token has expired (tokens last 30 minutes), or the route is not covered by your entitlements. Request a new token, and contact your Credit Benchmark administrator if the error continues.

### A key is missing, revoked or rotated

Contact your Credit Benchmark administrator.

## Security notes

* **Never** share your private key with anyone, including Credit Benchmark. Only the public key should leave your systems.
* Generate a new client assertion for every token request.
* If a private key is ever compromised, ask us to revoke the key immediately and follow [key rotation](/api-reference/authentication/key-pair-setup#key-rotation).


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