# Authentication
Source: https://docs.aden.space/docs/developers/api/authentication

Bearer tokens: team API keys or Supabase session tokens.
Every authenticated request carries a bearer token in the `Authorization`
header:

```http
GET /api/v1/tracks HTTP/1.1
Host: www.aden.space
Authorization: Bearer <token>
```

The backend looks at the prefix to decide how to validate:

* Starts with &#x2A;*`aden_`** → treated as a [team API key](#team-api-keys).
* Anything else → treated as a [Supabase JWT](#supabase-session-tokens).

## Team API keys [#team-api-keys]

* Format: `aden_live_<random>`.
* Created from **Team → Settings → API Keys** in the web app.
* Hashed with SHA-256 at rest; the raw key is shown once at creation.
* Scoped to the team they were created in. The server binds requests to
  that team automatically.
* Rate-limited per team based on the team's plan.

```bash
curl https://www.aden.space/api/v1/tracks \
  -H "Authorization: Bearer aden_live_xxxxxxxxxxxxxxxxxxxxxxxx"
```

### Scopes [#scopes]

Each key stores a list of scopes. Read endpoints are always allowed; write
endpoints check against the key's scopes and return `403` if the scope is
missing.

<Callout>
  Revoke compromised keys immediately from the same settings page. The key
  stops working on the next request.
</Callout>

## Supabase session tokens [#supabase-session-tokens]

User-facing apps authenticate with the same Supabase JWT the Aden web app
uses. This keeps Row Level Security policies in force and ties requests to
the real user.

```ts
const {
    data: { session },
} = await supabase.auth.getSession()

const res = await fetch('https://www.aden.space/api/v1/auth/me', {
    headers: { Authorization: `Bearer ${session?.access_token}` },
})
```

* Token expires and refreshes on Supabase's normal schedule. The SDK's
  `getToken` callback is the right integration point.
* Requests run under the user's identity; they can only see and mutate
  teams they're a member of.
* `auth.me`, `user.*`, and team-management routes require a session token
  (not an API key).

## Choosing a mode [#choosing-a-mode]

| You're building…                          | Use              |
| ----------------------------------------- | ---------------- |
| A cron job, CI step, DAW plugin, CLI tool | Team API key     |
| A user-facing web or mobile app           | Supabase session |
| A Raycast/Alfred-style personal tool      | Team API key     |
| A multi-tenant SaaS on top of Aden        | Supabase session |
| A webhook endpoint                        | Team API key     |

## Anonymous access [#anonymous-access]

A small set of endpoints don't need auth:

* `GET /api/v1/health`
* `GET /api/v1/testimonials` (public testimonials used on the landing page)

Everything else returns `401 { "error": "Unauthorized" }` without a valid
bearer token.