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

# Authentication

> Secure your API requests with organization-scoped API keys

# Authentication

Every programmatic call uses an **organization API key**. Sign up at [kallglot.com](https://www.kallglot.com/users/sign_up), open the Developer Portal, and create keys per environment (`sk_live_*` vs `sk_test_*`).

## API Keys

Every API key belongs to a single organization.

### Key Types

| Type | Prefix     | Usage                   |
| ---- | ---------- | ----------------------- |
| Live | `sk_live_` | Production traffic      |
| Test | `sk_test_` | Test or sandbox traffic |

### Why calls fail (`401`, `402`, `403`)

Typical gate checks: unknown or revoked keys, wrong live/test environment, inactive subscription, or exhausted API credits. See [Errors](/errors) when wiring retries.

<Warning>
  **Never expose your API keys in client-side code.** Use API keys only in trusted server-side environments. Browser and mobile clients should connect with short-lived session stream tokens created by your backend.
</Warning>

## Making Authenticated Requests

Use the `Authorization` header with a Bearer token:

```bash theme={null}
curl https://api.kallglot.com/v1/sessions \
  -H "Authorization: Bearer sk_live_your_api_key"
```

### Request Headers

| Header            | Required            | Description                              |
| ----------------- | ------------------- | ---------------------------------------- |
| `Authorization`   | Yes                 | Preferred format: `Bearer <api_key>`     |
| `X-API-Key`       | No                  | Alternative to `Authorization`           |
| `Content-Type`    | Yes for JSON bodies | Use `application/json` for POST requests |
| `Idempotency-Key` | Recommended on POST | Prevents duplicate writes on retry       |

## WebSocket Authentication

WebSocket connections use the session stream token returned by `POST /v1/sessions`, not your API key.

```javascript theme={null}
const session = await fetch('https://api.kallglot.com/v1/sessions', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.KALLGLOT_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    mode: 'bidirectional_translation',
    source_language: 'de',
    target_language: 'en'
  })
}).then((response) => response.json());

const ws = new WebSocket(
  `${session.stream.url}?token=${session.stream.token}`
);
```

<Note>
  That JSON body is **WebSocket-only** (no PSTN leg). For Twilio, Telnyx, or SIP, add **`routing`** on `POST /v1/sessions` as documented in [Create Session](/api-reference/sessions/create)—do not use a nested **`provider`** object.
</Note>

### Token Expiration

Stream tokens expire after 5 minutes. The `stream.expires_at` field tells you exactly when the token expires. Token expiry is checked only when the WebSocket connects, so an already-connected stream stays active after that point.

## API Key Permissions

API keys can be scoped to the smallest permission set your application needs:

| Permission        | Description               |
| ----------------- | ------------------------- |
| `sessions:read`   | Retrieve session details  |
| `sessions:write`  | Create and end sessions   |
| `recordings:read` | Access recordings         |
| `analysis:read`   | Retrieve analysis results |
| `analysis:write`  | Request session analysis  |
| `webhooks:manage` | Manage webhook endpoints  |

New keys are created with the full standard scope set listed above so integrations work out of the box; prefer the smallest viable set whenever you can customize scopes.

## Response Headers

Authenticated HTTP responses may include these headers:

| Header                    | Description                                               |
| ------------------------- | --------------------------------------------------------- |
| `X-Request-ID`            | Stable request identifier for support and debugging       |
| `X-RateLimit-Limit`       | Maximum requests allowed in the current rate-limit window |
| `X-RateLimit-Remaining`   | Requests remaining in the current rate-limit window       |
| `X-RateLimit-Reset`       | Unix timestamp when the current rate-limit window resets  |
| `X-API-Credits-Remaining` | Remaining API credits for the organization                |
| `X-API-Credits-Used`      | API credits used in the current billing period            |

For billable write requests, the credit headers reflect the post-request balance when the request succeeds.

## Authentication And Billing Errors

```json theme={null}
{
  "error": {
    "type": "permission_error",
    "code": "insufficient_api_credits",
    "message": "API credits exhausted. Purchase more credits to continue.",
    "request_id": "req_123"
  }
}
```

| Status | Code                        | Meaning                                                                                                                             |
| ------ | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `401`  | `api_key_invalid`           | The API key is missing, malformed, or unknown                                                                                       |
| `401`  | `api_key_expired`           | The API key has expired                                                                                                             |
| `401`  | `api_key_revoked`           | The API key has been revoked                                                                                                        |
| `401`  | `api_key_wrong_environment` | A test key was used against live, or vice versa                                                                                     |
| `403`  | `organization_inactive`     | The organization subscription is inactive                                                                                           |
| `402`  | `insufficient_api_credits`  | The organization has no API credits remaining                                                                                       |
| `403`  | `insufficient_permissions`  | The key lacks a required permission ([scopes](#api-key-permissions)); this is unrelated to **`402`** (billing / credits exhaustion) |

<Warning>
  Examples: **`POST /v1/sessions`** needs **`sessions:write`**. A key missing that scope receives **`403`** even when credits are available (`402`).
</Warning>

## Security Best Practices

<AccordionGroup>
  <Accordion title="Rotate keys regularly">
    Create new API keys periodically and revoke old ones to reduce exposure if a key is leaked.
  </Accordion>

  <Accordion title="Use environment variables">
    Store API keys in environment variables or a secret manager, never in source control.

    ```bash theme={null}
    export KALLGLOT_API_KEY=sk_live_your_api_key
    ```
  </Accordion>

  <Accordion title="Separate test and live keys">
    Live keys should only be used against the live API environment. Test keys should only be used in test or sandbox environments.
  </Accordion>

  <Accordion title="Monitor usage and credits">
    Watch the Developer Portal for unusual API activity, rate-limit pressure, and low API-credit balances.
  </Accordion>

  <Accordion title="Revoke compromised keys immediately">
    If a key may have been exposed, revoke it immediately and replace it with a new scoped key.
  </Accordion>
</AccordionGroup>

<Note>
  See [Error Codes](/errors) for the full error catalog and [Rate Limits](/rate-limits) for throughput limits and retry guidance.
</Note>
