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

# Base URLs, tokens, and concepts

> The key concepts you need before integrating: domain split, identity model, token types, and scopes.

## Hosts and purposes

<Warning>
  Ave separates user-facing pages, API calls, and organization administration. Mixing the sign-in host and API host is the #1 integration mistake.
</Warning>

| Host                 | Used for                                                                            |
| -------------------- | ----------------------------------------------------------------------------------- |
| `aveid.net`          | User-facing pages (sign-in, Connector consent), OIDC discovery, JWKS                |
| `api.aveid.net`      | API calls (token exchange, userinfo, signing)                                       |
| `business.aveid.net` | Business organization membership, wrapped org keys, verified domains, and SSO setup |

```
✅ POST https://api.aveid.net/api/oauth/token
✅ GET  https://aveid.net/.well-known/openid-configuration
❌ POST https://aveid.net/api/oauth/token   ← token API is on api.aveid.net
```

## Identity model

When a user signs in with Ave, they sign in as a specific **identity** — not just a user account. The same person can have multiple identities.

| Concept      | Description                                                              |
| ------------ | ------------------------------------------------------------------------ |
| `identityId` | Stable UUID for an identity. Use this as your primary key for user data. |
| `handle`     | The identity's username (e.g. `alice`). Can be changed by the user.      |

<Warning>
  Don't store data keyed by `handle` — it can change. Always use `identityId` (the `sub` claim in JWTs) as your stable identifier.
</Warning>

## Token types

A successful token exchange returns up to four tokens, each with a different purpose:

<AccordionGroup>
  <Accordion title="access_token — opaque bearer token">
    An opaque string accepted by Ave's own API endpoints (mainly `/api/oauth/userinfo`). Not a JWT — you cannot decode it. It expires after 1 hour.

    ```
    access_token: "ave_at_..."
    ```
  </Accordion>

  <Accordion title="access_token_jwt — signed JWT for Ave APIs">
    A signed JWT with `aud: https://aveid.net`. Use this when calling Ave API endpoints that accept JWTs, or as the subject token for Connector token exchange. Do not use it as the login token for your app API; use `id_token` or your own app session for that.

    ```
    access_token_jwt: "eyJ..."
    ```

    Verify using the `jwks_uri` from your issuer's OIDC discovery document (`{issuer}/.well-known/openid-configuration`). For Ave, this is `https://aveid.net/.well-known/jwks.json`.
  </Accordion>

  <Accordion title="id_token — OIDC identity token">
    A signed JWT with `aud` set to **your `clientId`**. Use this to establish a user session in your app, or with OIDC-aware services like Convex. Only returned when `openid` scope is granted.

    ```
    id_token: "eyJ..."
    ```
  </Accordion>

  <Accordion title="refresh_token — long-lived session token">
    An opaque token you can exchange for a fresh set of access/ID tokens without re-authenticating the user. Only returned when `offline_access` scope is granted. Rotated on every use — store the new one immediately.

    ```
    refresh_token: "rt_..."
    ```
  </Accordion>
</AccordionGroup>

<Note>
  `id_token` and `access_token_jwt` are both JWTs but have **different audiences**. The `id_token` audience is your `clientId`. The `access_token_jwt` audience is `https://aveid.net`. This matters for any library that validates JWT audience.
</Note>

## Scopes

Scopes are space-separated strings requested during authorization. They control what claims appear in tokens and what resources can be accessed.

| Scope            | What it unlocks                                            |
| ---------------- | ---------------------------------------------------------- |
| `openid`         | Returns `id_token`. Required for OIDC flows.               |
| `profile`        | Adds `name`, `preferred_username`, `picture` to userinfo   |
| `email`          | Adds `email` to userinfo                                   |
| `offline_access` | Returns `refresh_token` for long-lived sessions            |
| `user_id`        | Returns raw `userId` when requested in the authorize scope |

<Note>
  Scopes are allowlisted per app. Requesting a scope your app hasn't been granted will return an `invalid_scope` error.
</Note>

## Token endpoint field casing

The Ave token endpoint (`POST /api/oauth/token`) accepts both OAuth-standard `snake_case` body fields and legacy `camelCase` variants.

```ts theme={null}
{
  "grant_type": "authorization_code",
  "client_id": "YOUR_CLIENT_ID",
  "redirect_uri": "...",
  "code_verifier": "..."
}
```

Prefer the standard `snake_case` names in new integrations. Legacy `grantType`, `clientId`, `redirectUri`, and `codeVerifier` still work for backward compatibility.
