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

# Authenticate Requests to the Fayne Academy REST API

> Learn how to authenticate API requests using Bearer tokens, generate API keys from your dashboard, and handle authentication errors.

All requests to the Fayne Academy REST API must include an API key. The API uses Bearer token authentication: you pass your key in the `Authorization` header on every request. Each key is scoped to a single academy, so the API infers your academy from the key you provide. You never pass an academy identifier separately, and the host you call does not matter because the academy comes from the key.

<Note>
  The REST API is available on Fayne's paid plans. On a free or trial plan, API requests are rejected with a `402` (`trial_api_unavailable`). Upgrade to enable API access.
</Note>

## Generating an API key

Open your academy owner dashboard and navigate to **Settings > API Keys**. Click **Create API key**, give it a name, and copy the full key immediately. It is shown only once.

<Warning>
  Store your API key in an environment variable or secrets manager. Never commit it to source control or expose it in client-side code.
</Warning>

## Key format

Every API key begins with the prefix `fa_live_` followed by 32 lowercase hexadecimal characters, making the full key 40 characters long.

```text theme={null}
fa_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
         └─────────── 32 hex chars ─────────┘
```

## Sending the Authorization header

Include your key as a Bearer token in the `Authorization` header of every request.

```text theme={null}
Authorization: Bearer fa_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

### Example request

```bash theme={null}
curl https://yourname.fayneos.com/api/v1/courses \
  -H "Authorization: Bearer fa_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```

## Rate limiting

Requests are rate-limited per API key. When you exceed the limit, the API returns a `429` response with a `Retry-After` header indicating how many seconds to wait before retrying.

## Error codes

The table below covers authentication and common resource errors you may encounter across all endpoints.

| HTTP status | Code                    | When it occurs                                                           |
| ----------- | ----------------------- | ------------------------------------------------------------------------ |
| `401`       | `unauthorized`          | Missing or invalid `Authorization` header                                |
| `401`       | `unauthorized`          | API key does not start with `fa_live_`                                   |
| `401`       | `unauthorized`          | API key is revoked or does not exist                                     |
| `402`       | `trial_api_unavailable` | API access requires a paid plan                                          |
| `402`       | `academy_locked`        | The academy is locked (for example, billing inactive)                    |
| `402`       | `limit_exceeded`        | A plan limit was reached                                                 |
| `400`       | `validation_error`      | A path or body value failed validation (for example, a malformed UUID)   |
| `400`       | `invalid_course`        | Only published courses can be assigned                                   |
| `400`       | `invalid_courses`       | Some course IDs are invalid or unpublished                               |
| `400`       | `invalid_lists`         | Some list IDs are invalid or not in this academy                         |
| `403`       | `forbidden`             | The key is not permitted to perform this action                          |
| `404`       | `not_found`             | Student, course, or list not found in this academy                       |
| `409`       | `already_exists`        | The student is already a member, or a list with that name already exists |
| `429`       | `rate_limit_exceeded`   | Too many requests; check the `Retry-After` header                        |
| `500`       | `internal_error`        | An unexpected server error occurred                                      |

### Error response shape

When a request fails, the API returns a JSON body with an `error` object containing a `code` and a human-readable `message`.

```json theme={null}
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid API key"
  }
}
```

## Common questions

<AccordionGroup>
  <Accordion title="Can I connect my CRM or other tools?">
    Yes. Use this REST API to sync people from your CRM or funnel: call [POST /api/v1/students](/api-reference/students) to add a student and enroll them in courses in one request, or manage [lists](/api-reference/lists) so course access follows list membership (add someone in your tool and they get access; remove them and it is revoked). To let an AI assistant like Claude or Cursor read and edit your course content directly, see [Connect AI Tools](/content/connect-ai-tools).
  </Accordion>
</AccordionGroup>
