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

# Authentication

> Authenticate with ONVY bearer tokens and choose the right OAuth flow for your integration.

Bearer authentication is the standard way to call `health-api`. You obtain an access token for one ONVY project, then send it on protected API requests.

## What you need from ONVY

* A `project_id`
* The API base URL: `https://api.onvy.health`
* Either:
  * a confidential OAuth client with `client_id` and `client_secret` for server-to-server traffic
  * or a public client plus a supported upstream identity token for user authentication flows

## Choose the right flow

| Use case                         | Endpoint                                     | Notes                                                                                |
| -------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------ |
| Backend or BFF integration       | `POST /v1/projects/{project_id}/auth/server` | Uses HTTP Basic auth with a confidential client and returns an access token.         |
| Mobile or web app token exchange | `POST /v1/projects/{project_id}/auth/sdk`    | Exchanges an upstream OIDC token or ONVY refresh token for a user-scoped ONVY token. |
| Raw OAuth integration            | `POST /oauth/token`                          | Canonical OAuth token authority. Form-encoded rather than JSON.                      |

## Server-to-server authentication

Use this flow when your backend calls ONVY directly.

```bash theme={null}
curl -sS -X POST "$BASE_URL/v1/projects/$PROJECT_ID/auth/server" \
  -u "$CLIENT_ID:$CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"scope":"users:read daily_records:read ai_summaries:read"}'
```

Response:

```json theme={null}
{
  "access_token": "eyJ...",
  "token_type": "Bearer",
  "expires_in": 900
}
```

Use the returned access token on protected routes:

```bash theme={null}
curl -sS "$BASE_URL/users?limit=10" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

## User authentication for mobile or web apps

Use this flow when your app already authenticates the user with your own identity provider.

Exchange an upstream identity token:

```bash theme={null}
curl -sS -X POST "$BASE_URL/v1/projects/$PROJECT_ID/auth/sdk" \
  -H "Content-Type: application/json" \
  -d '{
    "grant": "exchange",
    "token": "'"$ID_TOKEN"'",
    "client_id": "sdk"
  }'
```

Refresh an ONVY refresh token:

```bash theme={null}
curl -sS -X POST "$BASE_URL/v1/projects/$PROJECT_ID/auth/sdk" \
  -H "Content-Type: application/json" \
  -d '{
    "grant": "refresh",
    "token": "'"$REFRESH_TOKEN"'",
    "client_id": "sdk"
  }'
```

This endpoint maps the request to the appropriate OAuth grant for the target project and returns the same token envelope as the canonical token endpoint.

## Canonical OAuth endpoint

Use `POST /oauth/token` when you want direct control over the OAuth grant parameters.

Example server flow:

```bash theme={null}
curl -sS -X POST "$BASE_URL/oauth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Authorization: Basic $(printf '%s:%s' "$CLIENT_ID" "$CLIENT_SECRET" | base64)" \
  --data-urlencode "grant_type=client_credentials" \
  --data-urlencode "resource=urn:onvy:project:$PROJECT_ID"
```

## Token claims

ONVY access tokens include these core claims:

* `iss`
* `aud`
* `exp`
* `iat`
* `nbf`
* `jti`
* `project_id`
* `sub`
* `principal_type`
* `scope`

If `principal_type=user`, the token must also include `user_id`.

## Scope format

Scopes follow this pattern:

```text theme={null}
<resource>[:namespace]:<action>
```

Examples:

* `users:read`
* `daily_records:create`
* `chat_completions:create`
* `admin.oauth_clients:revoke`

## How the project auth endpoints map to OAuth

* `/v1/projects/{project_id}/auth/server` maps to the `client_credentials` grant for `urn:onvy:project:{project_id}`
* `/v1/projects/{project_id}/auth/sdk` maps to token exchange or refresh, depending on the `grant` value in the JSON body
* `/oauth/token` is the canonical OAuth endpoint when you want to send grant parameters directly
