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

# Client Credentials Flow

> Machine-to-machine OAuth2 for personal-token clients. Exchange a client_id and client_secret for a short-lived access token with no interactive login.

This is the simplest way to call the Aries API when your app only ever acts as one user. If you are building an integration that signs in on behalf of many different users — a **partner/business** integration — use the [Authorization Code flow](/api-reference/oauth2/auth-code-flow) instead.

<Warning>
  **Only user-scoped (personal-token) clients may use this grant.**

  * **Allowed:** personal-token clients — client IDs like `ARI-PERSONAL-TK.<entropy>`, which are bound to a single user. The issued token acts as that user.
  * **Not allowed:** business/partner clients — client IDs like `ARI-PARTNER.*`. These receive an `unauthorized_client` error and must use the interactive [Authorization Code flow](/api-reference/oauth2/auth-code-flow) instead.
</Warning>

***

## Prerequisites

Before you implement this flow, ensure you have:

* **A personal-token client** — Register a personal-token client in Client Center / Manage Account to get a `client_id` (e.g. `ARI-PERSONAL-TK.xxxxx`) and `client_secret`.
* **Secure storage** — Somewhere safe to keep the `client_secret`, such as environment variables or a secrets manager.

<Warning>
  The `client_secret` is shown **only once** when you create the client. Copy it immediately and store it securely. If lost, regenerate it in Client Center / Manage Account.
</Warning>

***

## Step 1: Request an access token

Send your credentials to the token endpoint. The endpoint accepts the request body as either `application/x-www-form-urlencoded` (the OAuth2 standard) or `application/json`.

**Endpoint:** `POST https://api.aries.com/v1/oauth2/token`

**Request body:**

| Field           | Required | Description                                           |
| --------------- | -------- | ----------------------------------------------------- |
| `grant_type`    | Yes      | Must be `client_credentials`                          |
| `client_id`     | Yes      | Your client identifier (e.g. `ARI-PERSONAL-TK.xxxxx`) |
| `client_secret` | Yes      | Your client secret                                    |

<Note>
  Client authentication is done with these body parameters. HTTP Basic authentication is **not** supported for this endpoint.
</Note>

<CodeGroup>
  ```bash cURL (form-encoded) theme={null}
  curl -X POST 'https://api.aries.com/v1/oauth2/token' \
    -H 'Content-Type: application/x-www-form-urlencoded' \
    -d 'grant_type=client_credentials' \
    -d 'client_id=ARI-PERSONAL-TK.xxxxx' \
    -d 'client_secret=YOUR_CLIENT_SECRET'
  ```

  ```bash cURL (JSON) theme={null}
  curl -X POST 'https://api.aries.com/v1/oauth2/token' \
    -H 'Content-Type: application/json' \
    -d '{
      "grant_type": "client_credentials",
      "client_id": "ARI-PERSONAL-TK.xxxxx",
      "client_secret": "YOUR_CLIENT_SECRET"
    }'
  ```

  ```javascript Node.js theme={null}
  async function getAccessToken() {
    const response = await fetch('https://api.aries.com/v1/oauth2/token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: new URLSearchParams({
        grant_type: 'client_credentials',
        client_id: process.env.ARIES_CLIENT_ID,
        client_secret: process.env.ARIES_CLIENT_SECRET,
      }),
    });

    if (!response.ok) {
      const err = await response.json();
      throw new Error(err.error_description || `Token request failed: ${response.status}`);
    }

    return await response.json();
  }
  ```

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

  def get_access_token():
      response = requests.post(
          'https://api.aries.com/v1/oauth2/token',
          data={
              'grant_type': 'client_credentials',
              'client_id': os.environ['ARIES_CLIENT_ID'],
              'client_secret': os.environ['ARIES_CLIENT_SECRET'],
          },
      )
      response.raise_for_status()
      return response.json()
  ```
</CodeGroup>

***

***

## Response

A successful request returns `200 OK` with the token in JSON:

```json theme={null}
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_token": "",
  "refresh_token_expires_in": 0,
  "scope": "user:information account:information"
}
```

| Field                      | Description                                                      |
| -------------------------- | ---------------------------------------------------------------- |
| `access_token`             | A signed JWT (RS256). Send it as a bearer token on API requests. |
| `token_type`               | Always `Bearer`.                                                 |
| `expires_in`               | Token lifetime in seconds. Always `900` (15 minutes).            |
| `scope`                    | Space-delimited list of the client's granted scopes.             |
| `refresh_token`            | **Not issued** for this grant (empty string).                    |
| `refresh_token_expires_in` | **Not issued** for this grant (`0`).                             |

<Note>
  This grant does not issue refresh tokens. When the access token expires, simply request a new one from the same endpoint.
</Note>

***

## Step 2: Make authenticated API requests

Include the access token in the `Authorization` header for every API request.

```
Authorization: Bearer YOUR_ACCESS_TOKEN
```

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET 'https://api.aries.com/v1/users/me/accounts' \
    -H 'Authorization: Bearer YOUR_ACCESS_TOKEN'
  ```

  ```javascript Node.js theme={null}
  const { access_token } = await getAccessToken();

  const accounts = await fetch('https://api.aries.com/v1/users/me/accounts', {
    headers: { 'Authorization': `Bearer ${access_token}` },
  }).then(r => r.json());
  ```

  ```python Python theme={null}
  token = get_access_token()['access_token']

  accounts = requests.get(
      'https://api.aries.com/v1/users/me/accounts',
      headers={'Authorization': f'Bearer {token}'},
  ).json()
  ```
</CodeGroup>

Tokens expire after 15 minutes. When you get a `401`, request a new token from the token endpoint and retry.

***

## Errors

Errors follow the standard OAuth2 error response format:

```json theme={null}
{
  "error": "invalid_client",
  "error_description": "Client authentication failed"
}
```

| Error                 | HTTP status | Cause                                                                                                                                                                                 |
| --------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `invalid_request`     | `400`       | Missing or invalid `grant_type`, `client_id`, or `client_secret`.                                                                                                                     |
| `invalid_client`      | `401`       | Unknown `client_id`, wrong `client_secret`, or an inactive client.                                                                                                                    |
| `unauthorized_client` | `403`       | The client is a business/partner client (`ARI-PARTNER.*`) not permitted to use `client_credentials`. Use the [Authorization Code flow](/api-reference/oauth2/auth-code-flow) instead. |

***

## Next steps

<CardGroup cols={2}>
  <Card title="OAuth2 Overview" icon="shield-halved" href="/api-reference/oauth2/guide">
    Scopes, security, rate limits, and troubleshooting.
  </Card>

  <Card title="Authorization Code Flow" icon="server" href="/api-reference/oauth2/auth-code-flow">
    Interactive redirect flow for partner/business integrations.
  </Card>

  <Card title="Token API Reference" icon="key" href="/api-reference/oauth2/token">
    Interactive token endpoint reference.
  </Card>

  <Card title="Quick Start" icon="bolt" href="/api-reference/quickstart">
    Get started in minutes.
  </Card>
</CardGroup>
