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

# Authentication

> How to authenticate requests to the Vyla API.

## Overview

The Vyla API supports two authentication methods depending on your use case.

| Method        | Header                         | Use case                                       |
| ------------- | ------------------------------ | ---------------------------------------------- |
| Session token | `X-Session-Token`              | Browser players and client-side apps           |
| API key       | `Authorization` or `X-API-Key` | Server-side integrations and direct API access |

***

## Session Tokens (Browser / Player)

If you are building a browser-based player or client-side application, use session tokens. Your API key never leaves the browser — your server calls `POST /api/auth` with a valid API key to receive a short-lived token, then sends that token down to the client for use on subsequent requests.

### Step 1 — Get a token (server-side)

```javascript theme={null}
const { token } = await fetch('https://1c34-y.hf.space/api/auth', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}).then(r => r.json());
```

`POST /api/auth` requires a valid API key. The token inherits the tier of the key used to obtain it — a `public` key issues a `public`-tier token, a `standard` key issues a `standard`-tier token, and so on.

### Step 2 — Send the token (client-side)

```javascript theme={null}
const res = await fetch('https://1c34-y.hf.space/movie?id=550', {
  headers: { 'X-Session-Token': token }
});
```

Tokens are HMAC-signed and verified server-side without shared in-memory state, so they work correctly across all server workers. Tokens expire after 30 minutes — re-fetch from `/api/auth` and retry when expired.

### Token errors

| Error                              | Cause                                                                                             |
| ---------------------------------- | ------------------------------------------------------------------------------------------------- |
| `Missing API key`                  | `POST /api/auth` was called without a valid API key.                                              |
| `Invalid or expired session token` | Token is malformed, tampered with, or older than 30 minutes. Re-fetch from `/api/auth` and retry. |
| `Access denied`                    | Token was issued from a `public`-tier key and was used to access a proxied stream.                |

***

## API Keys (Server-Side / Direct Access)

API keys are for server-side integrations and direct API access where the key is never exposed to end users.

Rate limits are enforced per API key — not per IP address or per user. Each request made with the same key counts toward that key's limit regardless of where it originates.

| Tier       | Rate Limit     | Streaming access |
| ---------- | -------------- | ---------------- |
| `public`   | 10 req / 60s   | No               |
| `standard` | 100 req / 60s  | Yes              |
| `partner`  | 1000 req / 60s | Yes              |

A public key is available for testing non-streaming endpoints:

```
public_api_key
```

<Warning>
  The `public` tier cannot access the stream proxy (`/api?url=...`) or stream any video data. This restriction applies whether authenticating with a `public` API key directly **or** with a session token obtained from a `public` key. Streaming requires a `standard` or `partner` key, or a session token obtained from one.
</Warning>

Standard and partner keys are no longer issued publicly. [Submit a request](https://forms.gle/zB57GNQngFtahsZz6) to get one.

### Sending your key

<CodeGroup>
  ```bash Authorization Header theme={null}
  curl "https://1c34-y.hf.space/api/health" \
    -H "Authorization: Bearer public_api_key"
  ```

  ```bash X-API-Key Header theme={null}
  curl "https://1c34-y.hf.space/api/health" \
    -H "X-API-Key: public_api_key"
  ```
</CodeGroup>

### API key errors

| Error                 | Cause                                                                      |
| --------------------- | -------------------------------------------------------------------------- |
| `Missing API key`     | No `Authorization`, `X-API-Key`, or `X-Session-Token` header sent.         |
| `Invalid API key`     | Key doesn't match any known key.                                           |
| `Rate limit exceeded` | The key's request limit has been hit for the current 60-second window.     |
| `Access denied`       | A `public`-tier key or token was used to access a proxied stream endpoint. |

***

## Rate Limiting

Rate limits are tracked per API key. Session token requests (authenticated via `X-Session-Token`) are not subject to rate limiting — only direct API key usage is counted.

When a limit is exceeded the API returns `429` with a JSON body:

```json theme={null}
{
  "error": "Rate limit exceeded",
  "resetAt": 1718000000000,
  "limit": 100,
  "window": 60000
}
```

`resetAt` is a Unix timestamp in milliseconds indicating when the window resets.

***

## Which method should I use?

Use **session tokens** if your code runs in a browser. Putting an API key in client-side JavaScript exposes it in network requests — session tokens exist to prevent that. Your server fetches the token using its API key and passes it to the client.

Use **API keys** if your code runs on a server where the key is never sent to the browser.

***

## Public vs. Protected Routes

| Route                  | Auth required | `public` key/token allowed |
| ---------------------- | ------------- | -------------------------- |
| `GET /`                | No            | Yes                        |
| `POST /api/auth`       | Yes (API key) | Yes                        |
| `GET /api/health`      | Yes           | Yes                        |
| `GET /api/subtitles/*` | Yes           | Yes                        |
| `GET /api/downloads/*` | Yes           | Yes                        |
| `GET /movie`           | Yes           | No                         |
| `GET /tv`              | Yes           | No                         |
| `GET /api/test/:id`    | Yes           | Yes                        |
| `GET /api/debug/:id`   | Yes           | Yes                        |
| `GET /api?url=`        | Yes           | No                         |
