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

# Authentication

> Authenticate with JWT Bearer tokens, verify tenant claims, and troubleshoot common failures.

# Authentication

<p>
  <a href="/assets/downloads/guides/authentication.pdf" download="authentication.pdf">Download this guide</a>
</p>

The SNH AI Background Check API uses **JWT Bearer tokens**. Send a valid JWT on **protected** routes. **`GET /health`** is public in standard deployments ([Health check](/api-reference/endpoints/health)).

## Getting sandbox access

**Contact SNH AI** ([support@snh-ai.com](mailto:support@snh-ai.com)) to request sandbox access. You receive a **Bearer JWT** scoped to your account. The token payload must include the **`tenant`** claim SNH AI configures for your environment. Without `tenant`, protected routes reject the request even when the JWT is otherwise valid. Auth0 machine-to-machine tokens sometimes omit `tenant` unless your identity provider adds it — ask SNH AI to include that claim.

Do **not** commit client IDs, secrets, or sample JWTs into your codebase or docs.

### Using the API reference

1. Open any page under **API Reference** (for example [Create order](/api-reference/endpoints/create-order)).
2. Click **Authorize** (Bearer lock).
3. Paste your JWT. You may include the literal `Bearer ` prefix or omit it; use what your tooling expects consistently.
4. Use the JSON examples as request bodies. Default host is **sandbox** (`https://sandbox.theary.ai`) unless you select another server.

## Authentication method

* **Type**: Bearer JWT
* **Header**: `Authorization: Bearer <jwt_token>`

Access is organization-scoped: any valid JWT with your `tenant` claim can call the documented consumer endpoints for that organization. Role-based permission tiers (for example read-only vs. admin) are not exposed on this API surface.

## Making authenticated requests

Include your JWT on protected endpoints (example: [List orders](/api-reference/endpoints/list-orders)).

<CodeGroup>
  ```bash cURL theme={null}
  curl -sS -X GET "https://sandbox.theary.ai/background-check/v1/orders?page=1&limit=10" \
    -H "Authorization: Bearer YOUR_JWT_TOKEN" \
    -H "Accept: application/json"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://sandbox.theary.ai/background-check/v1/orders?page=1&limit=10', {
    headers: {
      Authorization: 'Bearer YOUR_JWT_TOKEN',
      Accept: 'application/json',
    },
  })
  ```

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

  headers = {
      'Authorization': 'Bearer YOUR_JWT_TOKEN',
      'Accept': 'application/json',
  }
  response = requests.get(
      'https://sandbox.theary.ai/background-check/v1/orders',
      params={'page': 1, 'limit': 10},
      headers=headers,
  )
  ```
</CodeGroup>

**Production**: same paths under `https://api.theary.ai` with production-issued credentials.

## Verify your token (tenant claim)

This decodes the JWT payload **without cryptographic verification** (useful locally; rely on SNH AI issuance for correctness):

```javascript theme={null}
function decodeJwtPayload(jwt) {
  try {
    const payloadPart = jwt.split('.')[1]
    const normalized = payloadPart.replace(/-/g, '+').replace(/_/g, '/')
    const json = Buffer.from(normalized, 'base64').toString('utf8')
    return JSON.parse(json)
  } catch {
    return null
  }
}

const token = process.env.AUTH_TOKEN // or paste a string in REPL
const payload = decodeJwtPayload(token)
if (!payload?.tenant) {
  console.warn('Missing tenant claim — API calls may fail. Ask SNH AI for a token that includes tenant.')
} else {
  console.log(`tenant=${payload.tenant}`)
}
```

## Optional: machine-to-machine (client credentials)

If SNH AI provisions an OAuth client for your integration, you can request tokens from your identity provider with client credentials. Prefer a token that already includes the **`tenant`** claim when you test. Never publish secrets.

## Security

* **Organization isolation** requires the **`tenant`** claim aligned to your SNH AI organization.
* **Protected routes**: all documented integration endpoints except `/health` require the Bearer JWT.

## Troubleshooting

| Symptom                                                             | What to try                                                                                                                                                                   |
| ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `401 Unauthorized`, empty or generic body                           | Missing or malformed `Authorization` header; ensure `Bearer <jwt>`.                                                                                                           |
| `401` generic `"Unauthorized"` message                              | Refresh the JWT or request a new sandbox token from your account manager.                                                                                                     |
| Requests fail after token “works” on `/health`                      | Decode the JWT and confirm **`tenant`** is present.                                                                                                                           |
| `401` tenant-related failure (missing, unknown, or inactive tenant) | Message is `"Tenant information not found in token"` or `"Tenant validation failed: ..."`; confirm your JWT's **`tenant`** claim is present and correct, then contact SNH AI. |
| Auth0 M2M token without `tenant`                                    | Ask SNH AI to add a **`tenant`** claim via your IdP Action or use a manually issued JWT.                                                                                      |

## Testing connectivity then auth

`GET /health` does **not** require auth:

<CodeGroup>
  ```bash cURL theme={null}
  curl -sS -i "https://sandbox.theary.ai/health"
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch('https://sandbox.theary.ai/health')
  const body = await res.json()
  ```

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

  r = requests.get('https://sandbox.theary.ai/health')
  body = r.json()
  ```
</CodeGroup>

Then call an authenticated endpoint (for example **List orders** above) with your Bearer token.

**Expected healthy response:**

```json theme={null}
{
  "success": true,
  "image": "api:stable"
}
```

Sandbox-specific limits are summarized in **[Environments](/getting-started/environments)**.

## Error responses

### Authentication errors (401)

All token-validation failures (expired, malformed, missing signature, and similar) return the same generic response:

```json theme={null}
{
  "statusCode": 401,
  "message": "Unauthorized"
}
```

### Tenant resolution errors (401)

Missing, unknown, or inactive tenant information also returns `401`, with a more specific message:

```json theme={null}
{
  "statusCode": 401,
  "message": "Tenant information not found in token"
}
```

## Next steps

1. [Quickstart](/quickstart)
2. [Environments](/getting-started/environments)
3. [Create order](/api-reference/endpoints/create-order)
4. [API overview](/api-reference/background-check/overview)
