# Authentication

The LVNG API supports two authentication methods: **JWT tokens** (via Supabase) for user sessions, and **API keys** for programmatic access. Both methods resolve to a tenant-scoped request context that isolates all data operations.

## Overview

| Method | Header | Best For |
|--------|--------|----------|
| JWT Token | `Authorization: Bearer <jwt>` | Browser apps, user sessions |
| API Key | `Authorization: Bearer YOUR_API_KEY` | Backend services, scripts, CI/CD |

## JWT Tokens

LVNG uses **Supabase-issued JWTs** as the primary authentication method for user sessions. Tokens are validated server-side using the `jsonwebtoken` library against the `JWT_SECRET` environment variable.

### Token Claims

The JWT payload contains the following claims:

```json
{
  "userId": "uuid-of-the-user",
  "email": "user@example.com",
  "role": "admin",
  "organizationId": "org-uuid",
  "iat": 1710864000,
  "exp": 1710867600
}
```

### Token Lifetime

| Token Type | TTL |
|------------|-----|
| Access token | 1 hour |
| Refresh token | 7 days |
| Redis session cache | 3600 seconds |

### Request Example

```bash
curl -X GET https://api.lvng.ai/api/v2/channels \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json"
```

### How It Works

1. The user signs in via Supabase Auth (email/password, OAuth, or magic link).
2. Supabase returns an access token (JWT) and a refresh token.
3. Your frontend sends the access token in the `Authorization` header with every request.
4. The LVNG middleware validates the JWT signature, extracts the user's identity, and stores the session in Redis with a 3600-second TTL.
5. All subsequent database queries are scoped to the user's `customer_id`.

> **Tip:** Access tokens expire after 1 hour. Use the Supabase client's built-in token refresh to keep sessions alive without prompting the user to sign in again.

## API Keys

API keys are designed for server-to-server communication where there is no browser session. They are long-lived credentials tied to a specific customer account and stored as bcrypt hashes in the `api_keys` database table with a 30-second in-memory cache for performance.

### Key Format

LVNG API keys follow a fixed format that encodes the customer scope. The token portion is 32-64 random characters.

```bash
vtron_cust_{customerId}_{token}

# Example:
vtron_cust_abc123_sk_live_9f8e7d6c5b4a3210fedcba98
```

### Sending the Key

The API accepts your key via three methods. All are equivalent.

| Name | Type | Description |
|------|------|-------------|
| `Authorization` | header | Pass the key as a Bearer token: "Bearer lvng_sk_live_...". Recommended for all API calls. |
| `x-api-key` | header | Pass the full API key as the header value. Supported as an alternative to the Authorization header. |
| `api_key` | query param | Pass the key as a query parameter: ?api_key=vtron_cust_.... Use only when headers are not available. |

### curl Example (Authorization: Bearer)

```bash
curl -X POST https://api.lvng.ai/api/v2/chat \
  -H "Authorization: Bearer vtron_cust_abc123_sk_live_9f8e7d6c5b4a3210fedcba98" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Summarize yesterday'\''s standup notes.",
    "platform": "api"
  }'
```

### Plan-Based Rate Limits

API keys are associated with a plan tier that determines rate limits.

| Plan | Per Minute | Per Hour | Per Day |
|------|-----------|----------|---------|
| Free | 5 | 20 | 100 |
| Pro | 100 | 500 | 10,000 |
| Enterprise | Unlimited | Unlimited | Unlimited |

## Request Context

After successful authentication, the middleware populates `req.user` with the following fields. All downstream handlers use this context for tenant-scoped operations.

```json
{
  "id": "user-uuid",
  "customer_id": "customer-uuid",
  "email": "user@example.com",
  "role": "admin",
  "auth_method": "jwt",
  "organization_id": "org-uuid",
  "org_role": "owner"
}
```

## Public Endpoints

The following endpoints do not require authentication. They are rate-limited by IP address (60 req/min).

| Path | Description |
|------|-------------|
| `/health` | Server health check |
| `/capabilities` | Platform capability discovery |
| `/v2/discover` | API discovery endpoint |
| `/v2/ingest` | Data ingestion webhook |
| `/v2/artifacts/meta` | Artifact metadata (public) |
| `/analytics/events` | Analytics event ingestion |

## Tenant Isolation

LVNG is a multi-tenant platform. Every authentication method resolves to a `customer_id`. All database queries, agent executions, and workflow runs are automatically scoped to that tenant.

- A JWT encodes the `customer_id` in its claims. The middleware extracts it on every request.
- An API key embeds the `customer_id` directly in the key prefix (`vtron_cust_{customerId}_...`). The middleware parses it and enforces scope.
- There is no way to query data belonging to another tenant, even with a valid token.

## Security Notes

1. **Never expose API keys in client-side code.** API keys are for server environments only. Use JWT tokens for browser-based applications.
2. **service_role keys are blocked on public endpoints.** The middleware rejects Supabase service_role keys on user-facing routes to prevent privilege escalation.
3. **API key versioning.** The server tracks key versions via the `X-API-Key-Version` response header. Use this to verify your key is current after rotation.
4. **Rotate keys periodically.** Generate new keys and revoke old ones from Settings > API Keys in the dashboard.
5. **Use environment variables.** Never hard-code keys in source files. Add `.env` to your `.gitignore`.

## Environment Variables

Store your credentials in environment variables.

```bash
# .env -- add this file to .gitignore
LVNG_API_KEY=vtron_cust_abc123_sk_live_9f8e7d6c5b4a3210fedcba98

# Optional: override the base URL for self-hosted deployments
LVNG_API_URL=https://api.lvng.ai/api
```

## Next Steps

- [Rate Limits](/docs/getting-started/rate-limits) -- Per-endpoint and per-plan rate limits, headers, and retry strategies.
- [Error Codes](/docs/errors) -- HTTP and Socket.io error codes, response formats, and troubleshooting.
