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

# Authentication

> Authenticate with OAuth2 client credentials and scope requests to an organisation

The API uses the OAuth2 **client credentials** flow. You exchange a `client_id` and
`client_secret` for a short-lived access token, then send that token — along with an
organisation context header — on every request.

## Getting Credentials

As part of the beta program you receive a `client_id` and `client_secret`, along with the
IDs (`org_...`) of the organisations you're authorized to access.

## Getting an Access Token

Exchange your credentials for an access token at the token endpoint, using HTTP Basic auth
(`client_id` as username, `client_secret` as password) and the `com.cula.tracking`
audience:

```bash Token request theme={null}
curl -X POST https://auth.demo.cula.earth/oauth2/token \
  -u "$CULA_CLIENT_ID:$CULA_CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "audience=com.cula.tracking"
```

```json Token response theme={null}
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "expires_in": 300,
  "token_type": "bearer"
}
```

Tokens are short-lived and expire after `expires_in` seconds. Request a new token before the current one expires or when a request returns
`401`.

<Note>
  Prefer an OAuth2 client library for your stack that supports the client credentials
  grant and handles token caching and renewal, rather than rolling the token exchange by
  hand.
</Note>

## Making Authenticated Requests

Every request needs the access token as a bearer token. Most endpoints also require a
`Cula-Organisation-Id` header naming the organisation the request operates on:

```http Request headers theme={null}
Authorization: Bearer your_access_token_here
Cula-Organisation-Id: org_01k6cvp6bdeayb0hfrghfwxjzx
```

The organisation must be one your credentials are authorized for, otherwise the request is
rejected.

<Note>
  The `/webhooks` endpoints are account-wide and do **not** take a `Cula-Organisation-Id`
  header. All other endpoints require it.
</Note>
