> For the complete documentation index, see [llms.txt](https://docs.january.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.january.ai/docs/authentication.md).

# Authentication

January supports account API keys for trusted backends and short-lived client tokens for applications running on an end user's device.

## Account API keys

Create `sk-…` API keys in the [January Developer Dashboard](https://dashboard.january.ai). Send the key as a bearer credential on every backend request:

```http
Authorization: Bearer sk-your-key
```

An account API key authenticates your organization. Store it in a secret manager or server environment variable; never include it in a browser bundle, mobile application, public repository, log, or screenshot.

## Client tokens

Mobile and browser applications should request a short-lived `ct-…` client token from your authenticated backend. The backend mints that token with the account API key and binds it to the signed-in end user.

The application then sends the client token as its bearer credential. When it expires, request a replacement from your backend and retry once.

The whole flow, with the exact calls:

```mermaid
sequenceDiagram
    autonumber
    participant App as 📱 Your mobile app
    participant Backend as Your backend
    participant January as January API<br/>partners.january.ai

    Note over Backend: Holds your API key (sk-…).<br/>It never leaves your server.

    App->>Backend: POST /your-token-endpoint<br/>with the user's normal app session
    Note over Backend: Verify the session and<br/>look up that user's id
    Backend->>January: POST /v1.2/auth/client-tokens<br/>Authorization: Bearer sk-…<br/>{ end_user_id, scopes, ttl_seconds }
    January-->>Backend: 201 { token: "ct-…", expires_in: 1800, … }
    Backend-->>App: The same JSON, unchanged
    Note over App: Keeps the ct-… token in memory<br/>(the SDK caches and refreshes it)

    loop Until the token expires (30 minutes by default)
        App->>January: GET /v1.2/foods?query=…<br/>Authorization: Bearer ct-…
        January-->>App: Data for that user only
    end

    App->>January: Any call after expiry
    January-->>App: 401 { code: "token_expired" }
    Note over App,Backend: Repeat steps 1 to 4, then retry the call once
```

1. **The app asks your backend for a token.** It calls an endpoint you add to your backend (`POST /your-token-endpoint` above), authenticated like the rest of your API, so only a signed-in user can reach it.
2. **Your backend mints the token.** It verifies the session, derives that user's id, and calls `POST https://partners.january.ai/v1.2/auth/client-tokens` with your `sk-…` key, the `end_user_id`, and the `scopes` the screen needs.
3. **January returns a `ct-…` token** bound to that user, with `expires_in`.
4. **Your backend returns that JSON to the app unchanged.** The SDKs decode it as-is.
5. **The app calls January directly** with `Authorization: Bearer ct-…` until the token expires. On a `401` with code `token_expired`, it repeats steps 1 to 4 and retries once; the SDKs do this for you.

The endpoint in step 1 is the only server code you write. Its contract and security rules are in the backend token endpoint guide for [iOS](/ios-sdk/getting-started/backend-token-endpoint.md), [Android](/android-sdk/getting-started/backend-token-endpoint.md), [React Native](/react-native-sdk/getting-started/backend-token-endpoint.md), and [Web](/web-sdk/getting-started/backend-token-endpoint.md).

See [Authentication and client tokens](/rest-api/authentication.md) for the interactive minting and revocation endpoints.
