# Authentication

> OAuth 2.1 client-credentials, action scopes, and least-privilege service accounts.

Aerandil authenticates with **OAuth 2.1 `client_credentials`**. A service account exchanges its `client_id` / `client_secret` for a short-lived bearer token, then sends that token on every request.

## Get a token

```bash
curl -X POST https://api.aerandil.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d grant_type=client_credentials \
  -d client_id="$AERANDIL_CLIENT_ID" \
  -d client_secret="$AERANDIL_CLIENT_SECRET" \
  -d scope="objects:read actions:hospitality.action.apply_payment:apply"
```

The response carries an `access_token`. Send it as a bearer token:

```bash
curl https://api.aerandil.com/v1/object-types/hospitality.folio/objects/$ID \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

## Scopes

Aerandil grants are fine-grained. There are two families.

### Resource scopes

Coarse capabilities over reads and platform surfaces:

| Scope                              | Grants                                                     |
| ---------------------------------- | ---------------------------------------------------------- |
| `objects:read`                     | Read objects, links, types, and events.                    |
| `events:read`                      | Read the event log and subscribe to the live event stream. |
| `analytics:read`                   | Read conformed metrics over their maintained rollups.      |
| `functions:invoke`                 | Invoke registered functions (or use a per-function scope). |
| `webhooks:read` / `webhooks:write` | Read or manage webhook subscriptions.                      |
| `erasure:write`                    | Force a GDPR Article 17 hard-delete of a record.           |
| `tenant_admin:write`               | Operator-privileged, whole-tenant lifecycle.               |

### Action scopes

**Writes are [actions](/guides/ontology-model/#actions), and each action is separately authorized.** Two forms:

- `actions:apply` — a catch-all that authorizes _every_ registered action.
- `actions:{api_name}:apply` — authorizes one action, e.g. `actions:hospitality.action.apply_payment:apply`.

Neither subsumes the other: a token presenting a per-action scope can apply that action; a token presenting `actions:apply` can apply any. Prefer **per-action scopes** for service accounts and reserve the catch-all for trusted first-party callers — issue the narrowest grant that does the job.

## Verifying webhook deliveries

If your service _receives_ webhooks from Aerandil rather than calling the API, it verifies the `aerandil_webhook_signature` on each delivery instead of presenting a bearer token. That signature scheme is documented with the webhook payloads in the [API reference](/api/).

## Next

- [Quickstart](/guides/quickstart/) — token → apply an action → read the result.
- [The ontology model](/guides/ontology-model/) — why writes are actions.

---

Source: https://developers.aerandil.com/guides/authentication/
