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

# Request an access token

OAuth 2.0 client credentials grant. The request is form encoded. The token lasts one hour.

<RequestExample>
  ```bash Form credentials theme={null}
  curl --request POST https://api.acealliance.capital/oauth/v1/token \
    --header "Content-Type: application/x-www-form-urlencoded" \
    --data "grant_type=client_credentials" \
    --data "client_id=CLIENT_ID" \
    --data "client_secret=CLIENT_SECRET"
  ```

  ```bash HTTP Basic theme={null}
  curl --request POST https://api.acealliance.capital/oauth/v1/token \
    --user "CLIENT_ID:CLIENT_SECRET" \
    --header "Content-Type: application/x-www-form-urlencoded" \
    --data "grant_type=client_credentials"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "access_token": "ACCESS_TOKEN",
    "token_type": "Bearer",
    "expires_in": 3600
  }
  ```

  ```json 401 Unauthorized theme={null}
  {
    "error": "invalid_client",
    "error_description": "Client authentication failed."
  }
  ```
</ResponseExample>

Send the credentials in the form body or with HTTP Basic authentication, not both.

## Headers

<ParamField header="Content-Type" type="string" required>
  `application/x-www-form-urlencoded`
</ParamField>

<ParamField header="Authorization" type="string">
  `Basic` followed by the base64 of `CLIENT_ID:CLIENT_SECRET`. Replaces `client_id` and `client_secret` in the body.
</ParamField>

## Request body

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

<ParamField body="client_id" type="string">
  Required without HTTP Basic authentication.
</ParamField>

<ParamField body="client_secret" type="string">
  Required without HTTP Basic authentication.
</ParamField>

## Response

<ResponseField name="access_token" type="string" required>
  Send as `Authorization: Bearer ACCESS_TOKEN` on the other endpoints.
</ResponseField>

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

<ResponseField name="expires_in" type="integer" required>
  `3600`
</ResponseField>

The response carries `Cache-Control: no-store`.

## Errors

| Status | `error`                  | Meaning                                                                            |
| ------ | ------------------------ | ---------------------------------------------------------------------------------- |
| `400`  | `unsupported_grant_type` | `grant_type` is not `client_credentials`.                                          |
| `400`  | `invalid_request`        | Both HTTP Basic and form credentials were sent.                                    |
| `401`  | `invalid_client`         | The client ID or secret is not accepted. Same answer for every credential problem. |
| `413`  |                          | Body larger than 4096 bytes. No body.                                              |
| `429`  |                          | More than 30 requests in 60 seconds for this client ID. No body.                   |

## Tokens

* No refresh token. Request a new token before the current one expires.
* Reuse one token for all calls during its hour.
* A revoked secret stops new tokens. Issued tokens run to expiry.
