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

# Authentication

> Authenticate with the HelpGenie API using API keys or session tokens

All API requests require authentication. The recommended method for external integrations is an **API key**.

## Method 1: API Key (recommended)

Create an API key in [Help Genie](https://helpgenie.ai) → **Settings** → **API Keys** → **Create Key**.

The full key is shown **once** — copy it immediately and store it securely. Keys use the `hg_live_` prefix.

Pass your key using either method:

<CodeGroup>
  ```bash Authorization header theme={null}
  curl https://api.helpgenie.ai/v1/genies \
    -H "Authorization: Bearer hg_live_YOUR_KEY"
  ```

  ```bash X-API-Key header theme={null}
  curl https://api.helpgenie.ai/v1/genies \
    -H "X-API-Key: hg_live_YOUR_KEY"
  ```

  ```typescript fetch theme={null}
  const response = await fetch("https://api.helpgenie.ai/v1/genies", {
    headers: {
      Authorization: "Bearer hg_live_YOUR_KEY",
    },
  });

  const result = await response.json();
  ```
</CodeGroup>

**Key details:**

* Don't expire — work until revoked
* Rate limited: **60 requests/minute** per key
* Max **5 active keys** per user
* Keys carry the same permissions as the user who created them

## Method 2: Session Token (for browser/app contexts)

For browser-based applications, authenticate with Supabase Auth:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { createClient } from "@supabase/supabase-js";

  const supabase = createClient(
    "https://<project-ref>.supabase.co",
    "<anon-key>"
  );

  const { data, error } = await supabase.auth.signInWithPassword({
    email: "user@example.com",
    password: "your-password",
  });

  const accessToken = data.session?.access_token;
  ```

  ```bash cURL theme={null}
  curl -X POST "https://<project-ref>.supabase.co/auth/v1/token?grant_type=password" \
    -H "apikey: <anon-key>" \
    -H "Content-Type: application/json" \
    -d '{
      "email": "user@example.com",
      "password": "your-password"
    }'
  ```
</CodeGroup>

Then include the token in the `Authorization` header:

```
Authorization: Bearer <session_access_token>
```

Session tokens expire after \~1 hour. The Supabase client handles refresh automatically.

## Making authenticated requests

<CodeGroup>
  ```bash cURL (API key) theme={null}
  curl https://api.helpgenie.ai/v1/genies \
    -H "Authorization: Bearer hg_live_YOUR_KEY"
  ```

  ```typescript TypeScript (ApiService) theme={null}
  import { ApiService } from "@/services/api/ApiService";

  // ApiService handles token retrieval automatically
  const genies = await ApiService.invoke({
    resource: "genies",
    action: "all",
  });
  ```

  ```typescript fetch (session token) theme={null}
  const response = await fetch("https://api.helpgenie.ai/v1/genies", {
    headers: {
      Authorization: `Bearer ${accessToken}`,
    },
  });

  const result = await response.json();
  ```
</CodeGroup>

## Authentication errors

| Error code           | HTTP status | Description                                           |
| -------------------- | ----------- | ----------------------------------------------------- |
| `UNAUTHORIZED`       | 401         | No authentication header provided.                    |
| `INVALID_KEY_PREFIX` | 401         | API key doesn't start with `hg_live_` or `hg_admin_`. |
| `KEY_NOT_FOUND`      | 401         | API key not found or has been revoked.                |
| `INVALID_TOKEN`      | 401         | Session token is malformed, expired, or revoked.      |

Example error response:

```json theme={null}
{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "No authentication provided. Include an Authorization header with 'Bearer hg_live_YOUR_KEY' or set the X-API-Key header.",
    "status": 401
  }
}
```

See [Error handling](/getting-started/errors) for the complete error reference.
