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

# Authentication

> How to authenticate API requests across all SNH AI services

All SNH AI services use JWT (JSON Web Tokens) for authentication. The flow is the same regardless of which service you are using.

## Authentication Flow

1. **Obtain your API key** during [Account Setup](/account-setup)
2. **Exchange your API key for a JWT token** using the `/auth/token` endpoint
3. **Include the token** in the `Authorization` header on every API request

## Get a JWT Token

Exchange your API key for a short-lived JWT token.

**Endpoint:** `POST /auth/token`

Pass your API key in the `X-API-Key` header:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://cra.pr.snh-ai.com/auth/token \
    -H "X-API-Key: $PR_API_KEY" \
    -H "Content-Type: application/json"
  ```

  ```python Python theme={null}
  import requests, os

  base = os.environ["PR_API_BASE"]
  api_key = os.environ["PR_API_KEY"]

  resp = requests.post(
      f"{base}/auth/token",
      headers={"X-API-Key": api_key}
  )
  token = resp.json()["access_token"]
  ```

  ```javascript JavaScript theme={null}
  const base = process.env.PR_API_BASE;
  const apiKey = process.env.PR_API_KEY;

  const resp = await fetch(`${base}/auth/token`, {
    method: "POST",
    headers: { "X-API-Key": apiKey }
  });
  const { access_token } = await resp.json();
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "expires_in": 7200
}
```

* Token expires in **2 hours** (7200 seconds)
* Tokens cannot be refreshed or extended — request a new one before expiry

See the [Auth Token endpoint reference](/api-reference/endpoints/auth-token) for full request/response details.

## Use the Token

Include the token in the `Authorization` header for all protected endpoints:

```
Authorization: Bearer YOUR_TOKEN_HERE
```

## Error Responses

| Status | Response                                           | Cause                                     |
| ------ | -------------------------------------------------- | ----------------------------------------- |
| 401    | `"Authentication required. Provide Bearer token."` | Missing `Authorization` header            |
| 401    | `"Token validation failed: Token has expired"`     | Expired JWT token                         |
| 401    | `"Invalid API key."`                               | Wrong or revoked API key on `/auth/token` |

## Best Practices

1. **Token Management:**
   * Cache tokens and refresh before expiration
   * Handle 401 errors by requesting a new token
   * Never hardcode tokens

2. **Security:**
   * Never expose API keys in client-side code
   * Use environment variables for API keys
   * Rotate API keys periodically

3. **Error Handling:**
   * Always check response status codes
   * Implement retry logic for 401 errors — see [Retry Logic](/retry-logic)
   * Log authentication errors for debugging
