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

# Authentication

> API key for server-to-server access, OAuth 2.0 + PKCE for user-scoped access.

The SDK supports two authentication modes. Pick the one that matches your use case:

| Mode                 | Header                          | Use when                                                                                         |
| -------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------ |
| **API Key**          | `x-api-key: ang_live_...`       | Server-to-server. Catalog browsing, no user context.                                             |
| **OAuth 2.0 + PKCE** | `Authorization: Bearer <token>` | Client apps acting on behalf of a user. Required for library, playlists, and stream acquisition. |

Both modes hit the same endpoints — the API decides what's accessible based on which credential you present.

## API key

API keys are managed via the [Developer Portal](/developer-portal) and the underlying `DeveloperService`. Keys carry a visible prefix (`ang_live_...` for production, `ang_test_...` for test) plus an opaque secret tail. Pass the full key in the `x-api-key` header:

```bash theme={null}
curl -sS "https://sdk.anghami.com/v1/music/songs/123456" \
  -H "x-api-key: $ANGHAMI_API_KEY"
```

API keys can browse the public catalog (songs, albums, artists, search, charts) but **cannot** acquire streams or read user libraries. For that, use OAuth.

Billing is tracked per key. Rotate keys with `RotateApiKey` (the old key keeps working for a server-defined grace period to allow migration). Revoke immediately with `RevokeApiKey` — there is no recovery.

## OAuth 2.0 + PKCE

User-scoped access uses the standard [Authorization Code + PKCE](https://datatracker.ietf.org/doc/html/rfc7636) flow. PKCE is **required** for both confidential and public clients.

### 1. Build the authorization URL

```
GET https://sdk.anghami.com/v1/auth/authorize
  ?client_id={CLIENT_ID}
  &redirect_uri={REDIRECT_URI}
  &response_type=code
  &scope=read+stream
  &code_challenge={CODE_CHALLENGE}
  &code_challenge_method=S256
  &state={CSRF_TOKEN}
```

Generate `code_verifier` (43–128 chars, URL-safe) and derive `code_challenge = BASE64URL(SHA256(code_verifier))`.

### 2. Exchange the code for tokens

After consent, the user is redirected back to your `redirect_uri` with `?code=...&state=...`. Exchange via `AuthService.ExchangeToken`:

```bash theme={null}
curl -sS https://sdk.anghami.com/v1/auth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type":"authorization_code",
    "code":"<code from redirect>",
    "redirect_uri":"<same as authorize>",
    "client_id":"<your client id>",
    "code_verifier":"<the original verifier>"
  }'
```

Response carries `access_token`, `refresh_token`, `expires_in`, and granted `scope`.

### 3. Use the access token

```bash theme={null}
curl -sS "https://sdk.anghami.com/v1/library/likes" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

### 4. Refresh

When `expires_in` runs out, call `RefreshToken`. Refresh tokens **may rotate** — always persist the latest one.

```bash theme={null}
curl -sS https://sdk.anghami.com/v1/auth/token/refresh \
  -H "Content-Type: application/json" \
  -d '{"refresh_token":"<old refresh>","client_id":"<id>"}'
```

### Revoking

`AuthService.RevokeToken` invalidates an access or refresh token immediately. Use this on user logout.

```bash theme={null}
curl -sS https://sdk.anghami.com/v1/auth/token/revoke \
  -H "Content-Type: application/json" \
  -d '{"token":"<access or refresh token>","token_type_hint":"access_token"}'
```

## Scopes

See [OAuth Scopes](/oauth-scopes) for the full list. The current scopes are intentionally broad:

* `read` — catalog, search, browse, library, playlists, profile.
* `stream` — billable. Required for `AcquireMusicStream` and `AcquireVideoStream`.

A future `write` scope is reserved for library and playlist mutations; today the catalog write surface is limited to API key management via `DeveloperService`.

## Errors

Auth failures return [`Error`](/usage-errors) with `code = ERROR_CODE_UNAUTHENTICATED` (missing/invalid credential) or `ERROR_CODE_PERMISSION_DENIED` (valid credential, missing scope). Inspect the `message` for context.
