> ## Documentation Index
> Fetch the complete documentation index at: https://api-doc.fidly.be/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> OAuth2 client credentials, access token lifetime, refresh rotation and permissions.

The API uses the OAuth2 **client credentials** flow. Each integration owns a
`client_id` / `client_secret` pair, issued and managed in the Fidly interface.

## Retrieving the keys

`POST /auth/token` accepts a JSON body and two grant types:

<CodeGroup>
  ```bash Client credentials theme={null}
  curl -X POST https://api.fidly.be/auth/token \
    -H "Content-Type: application/json" \
    -d '{
      "grant_type": "client_credentials",
      "client_id": "YOUR_CLIENT_ID",
      "client_secret": "YOUR_CLIENT_SECRET"
    }'
  ```

  ```bash Refresh token theme={null}
  curl -X POST https://api.fidly.be/auth/token \
    -H "Content-Type: application/json" \
    -d '{
      "grant_type": "refresh_token",
      "refresh_token": "YOUR_REFRESH_TOKEN"
    }'
  ```
</CodeGroup>

Both return the same shape:

```json theme={null}
{
  "access_token": "eyJhbGciOi...",
  "token_type": "bearer",
  "expires_in": 3600,
  "refresh_token": "b3f1..."
}
```

## Access token

The `access_token` is a JWT valid for **1 hour** (`expires_in: 3600`), sent on
every request in the `Authorization: Bearer <access_token>` header.

The client's permissions are embedded in it at issuance: a permission granted or
revoked in the interface takes effect on the **next** `access_token`, not on those
already issued.

## Refresh token

The `refresh_token` lets you get a new pair of keys without re-sending the
`client_secret`. Its validity is **unlimited as long as it is not consumed**. It is
**single-use**: consuming it invalidates the one you sent and returns a new
`access_token` + `refresh_token` pair — the `refresh_token` you receive is brand
new, its validity starts over.

Each `client_id` is only allowed one active `refresh_token` at a time. If several
processes share one `client_id`, have them share the keys — each fetching its own
would log the others out. Cache the `access_token` and reuse it for its full hour
of validity, rather than requesting a new one on every call.

## Permissions

Your client's permissions are set with a **per-action, per-resource** granularity:
for each resource (`document`, `relation`, `bank_account`, `journal`, `branding`),
each action — create, read, update, delete — can be allowed or not from the Fidly
interface. All four actions can always be configured; an action with no matching
route today simply has no effect.

The reference lists (`/units-of-measure`, `/currencies`, `/countries`) require a
valid `access_token` but no resource permission.

| Situation                                            | Response                       |
| ---------------------------------------------------- | ------------------------------ |
| Missing or invalid `access_token`                    | `401 invalid_token`            |
| Valid `access_token` without the required permission | `403 insufficient_permissions` |

## Security

A few choices in how the keys are handled, worth knowing to integrate confidently:

**Temporary lockout on failures.** Repeated failed authentications on the same
`client_id` trigger a temporary `429 too_many_requests`, to slow down brute force.
Back off and retry later; a successful authentication resets the counter.

**One active pair per client.** Re-creating a pair via the client credentials
overwrites the previous `refresh_token`: any earlier refresh session is
invalidated. An already-issued `access_token` however stays valid until it expires
— revoking a permission therefore takes effect at most one hour later.

**Rotation reveals theft.** A `refresh_token` that was already used fails with
`401 invalid_grant`. If that happens with no explanation on your side, treat the
pair as compromised and start over from your client credentials.

**Nothing sensitive in the clear.** On Fidly's side, the `client_secret` and the
`refresh_token` are stored hashed: a leak would yield no reusable key.

<Warning>
  We recommend keeping your keys around to reuse them for their validity period — in
  memory or in a database, whichever fits your architecture — and never logging a
  full token or the `client_secret`.
</Warning>
