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

# Auth & Keys

> Create, scope, rotate, and revoke developer API keys.

## Overview

All Developer API requests authenticate with `X-API-Key`. This page covers every endpoint for managing the keys themselves.

**Base URL:** `https://api.indigenius.ai/v1`

**Required scope for key management:** `keys:read` (read), `keys:write` (create/update/rotate/revoke)

***

## `POST /v1/auth/keys`

Creates a new API key with specific scopes and optional rate limits.

| Field                | Type          | Required | Description                                             |
| -------------------- | ------------- | -------- | ------------------------------------------------------- |
| `name`               | string        | No       | Human-readable label for the key                        |
| `scopes`             | string\[]     | No       | Permission scopes granted to the key                    |
| `expiresAt`          | ISO 8601 date | No       | Expiry date/time for the key                            |
| `rateLimitPerMinute` | integer       | No       | Max requests per minute (1–1000)                        |
| `rateLimitPerHour`   | integer       | No       | Max requests per hour (1–10000)                         |
| `allowedIps`         | string\[]     | No       | IP allowlist; omit to allow all                         |
| `callbackUrl`        | https URL     | No       | Webhook URL to receive event notifications for this key |

<CodeGroup>
  ```bash Bash theme={null}
  curl -X POST https://api.indigenius.ai/v1/auth/keys \
    -H "X-API-Key: $INDIGENIUS_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Production key",
      "scopes": ["calls:read", "calls:write", "agents:read", "agents:write"],
      "expiresAt": "2027-01-01T00:00:00.000Z",
      "rateLimitPerMinute": 120,
      "rateLimitPerHour": 2000,
      "allowedIps": ["102.88.10.5"],
      "callbackUrl": "https://client.example.com/hooks/indigenius"
    }'
  ```

  ```javascript Node theme={null}
  const response = await fetch('https://api.indigenius.ai/v1/auth/keys', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': process.env.INDIGENIUS_API_KEY,
    },
    body: JSON.stringify({
      name: 'Production key',
      scopes: ['calls:read', 'calls:write', 'agents:read', 'agents:write'],
      expiresAt: '2027-01-01T00:00:00.000Z',
      rateLimitPerMinute: 120,
      rateLimitPerHour: 2000,
      allowedIps: ['102.88.10.5'],
      callbackUrl: 'https://client.example.com/hooks/indigenius', // optional
    }),
  });
  console.log(await response.json());
  ```

  ```python Python theme={null}
  import requests, os

  response = requests.post(
      "https://api.indigenius.ai/v1/auth/keys",
      headers={
          "X-API-Key": os.environ["INDIGENIUS_API_KEY"],
          "Content-Type": "application/json",
      },
      json={
          "name": "Production key",
          "scopes": ["calls:read", "calls:write", "agents:read", "agents:write"],
          "expiresAt": "2027-01-01T00:00:00.000Z",
          "rateLimitPerMinute": 120,
          "rateLimitPerHour": 2000,
          "allowedIps": ["102.88.10.5"],
          # optional — provide a webhook URL to receive event notifications for this key
          "callbackUrl": "https://client.example.com/hooks/indigenius",
      },
      timeout=30,
  )
  print(response.json())
  ```
</CodeGroup>

<Warning>
  The full API key secret is returned **only in this response**. Store it
  immediately in a secret manager. If it is lost, rotate the key — it cannot be
  retrieved again.
</Warning>

**`201 Created`**

```json theme={null}
{
  "status": true,
  "message": "API key created",
  "data": {
    "id": "665e4a34c65bb95f2f2d72e1",
    "name": "Production key",
    "key": "sk_live_xxxxxxxxxxxxxxxxxxxxxxxx",
    "publicKey": "pk_live_7ecf0af44e8f4e48",
    "scopes": ["calls:read", "calls:write", "agents:read", "agents:write"],
    "status": "active"
  }
}
```

***

## `GET /v1/auth/keys`

Lists all API keys for your organization.

<CodeGroup>
  ```bash Bash theme={null}
  curl https://api.indigenius.ai/v1/auth/keys \
    -H "X-API-Key: $INDIGENIUS_API_KEY"
  ```

  ```javascript Node theme={null}
  const response = await fetch('https://api.indigenius.ai/v1/auth/keys', {
    headers: { 'X-API-Key': process.env.INDIGENIUS_API_KEY },
  });
  console.log(await response.json());
  ```

  ```python Python theme={null}
  import requests, os

  response = requests.get(
      "https://api.indigenius.ai/v1/auth/keys",
      headers={"X-API-Key": os.environ["INDIGENIUS_API_KEY"]},
      timeout=30,
  )
  print(response.json())
  ```
</CodeGroup>

**`200 OK`**

```json theme={null}
{
  "status": true,
  "message": "API keys fetched",
  "data": [
    {
      "id": "665e4a34c65bb95f2f2d72e1",
      "name": "Production key",
      "publicKey": "pk_live_7ecf0af44e8f4e48",
      "scopes": ["calls:read", "calls:write"],
      "status": "active",
      "expiresAt": "2027-01-01T00:00:00.000Z"
    }
  ]
}
```

***

## `GET /v1/auth/scopes`

Returns all supported permission scopes.

<CodeGroup>
  ```bash Bash theme={null}
  curl https://api.indigenius.ai/v1/auth/scopes \
    -H "X-API-Key: $INDIGENIUS_API_KEY"
  ```

  ```javascript Node theme={null}
  const response = await fetch('https://api.indigenius.ai/v1/auth/scopes', {
    headers: { 'X-API-Key': process.env.INDIGENIUS_API_KEY },
  });
  console.log(await response.json());
  ```

  ```python Python theme={null}
  import requests, os

  response = requests.get(
      "https://api.indigenius.ai/v1/auth/scopes",
      headers={"X-API-Key": os.environ["INDIGENIUS_API_KEY"]},
      timeout=30,
  )
  print(response.json())
  ```
</CodeGroup>

***

## `PATCH /v1/auth/keys/{id}/scopes`

Replaces the scopes on a key. This is a full replacement — include all scopes you want the key to have, not just new ones.

<CodeGroup>
  ```bash Bash theme={null}
  curl -X PATCH https://api.indigenius.ai/v1/auth/keys/665e4a34c65bb95f2f2d72e1/scopes \
    -H "X-API-Key: $INDIGENIUS_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"scopes": ["calls:read", "calls:write", "workflows:read", "workflows:write"]}'
  ```

  ```javascript Node theme={null}
  const keyId = '665e4a34c65bb95f2f2d72e1';
  const response = await fetch(
    `https://api.indigenius.ai/v1/auth/keys/${keyId}/scopes`,
    {
      method: 'PATCH',
      headers: {
        'Content-Type': 'application/json',
        'X-API-Key': process.env.INDIGENIUS_API_KEY,
      },
      body: JSON.stringify({
        scopes: [
          'calls:read',
          'calls:write',
          'workflows:read',
          'workflows:write',
        ],
      }),
    },
  );
  console.log(await response.json());
  ```

  ```python Python theme={null}
  import requests, os

  key_id = "665e4a34c65bb95f2f2d72e1"
  response = requests.patch(
      f"https://api.indigenius.ai/v1/auth/keys/{key_id}/scopes",
      headers={
          "X-API-Key": os.environ["INDIGENIUS_API_KEY"],
          "Content-Type": "application/json",
      },
      json={"scopes": ["calls:read", "calls:write", "workflows:read", "workflows:write"]},
      timeout=30,
  )
  print(response.json())
  ```
</CodeGroup>

***

## `POST /v1/auth/keys/{id}/rotate`

Issues a new secret for the key while keeping the same `id`, name, and scopes. The old secret is immediately invalidated.

<CodeGroup>
  ```bash Bash theme={null}
  curl -X POST https://api.indigenius.ai/v1/auth/keys/665e4a34c65bb95f2f2d72e1/rotate \
    -H "X-API-Key: $INDIGENIUS_API_KEY"
  ```

  ```javascript Node theme={null}
  const response = await fetch(
    'https://api.indigenius.ai/v1/auth/keys/665e4a34c65bb95f2f2d72e1/rotate',
    {
      method: 'POST',
      headers: { 'X-API-Key': process.env.INDIGENIUS_API_KEY },
    },
  );
  console.log(await response.json());
  ```

  ```python Python theme={null}
  import requests, os

  response = requests.post(
      "https://api.indigenius.ai/v1/auth/keys/665e4a34c65bb95f2f2d72e1/rotate",
      headers={"X-API-Key": os.environ["INDIGENIUS_API_KEY"]},
      timeout=30,
  )
  print(response.json())
  ```
</CodeGroup>

<Warning>
  Update `INDIGENIUS_API_KEY` in all environments that use this key before
  rotating. The old secret stops working immediately.
</Warning>

***

## `POST /v1/auth/keys/{id}/revoke`

Permanently disables a key. All requests using it will return `401` immediately. This action cannot be undone.

<CodeGroup>
  ```bash Bash theme={null}
  curl -X POST https://api.indigenius.ai/v1/auth/keys/665e4a34c65bb95f2f2d72e1/revoke \
    -H "X-API-Key: $INDIGENIUS_API_KEY"
  ```

  ```javascript Node theme={null}
  const response = await fetch(
    'https://api.indigenius.ai/v1/auth/keys/665e4a34c65bb95f2f2d72e1/revoke',
    {
      method: 'POST',
      headers: { 'X-API-Key': process.env.INDIGENIUS_API_KEY },
    },
  );
  console.log(await response.json());
  ```

  ```python Python theme={null}
  import requests, os

  response = requests.post(
      "https://api.indigenius.ai/v1/auth/keys/665e4a34c65bb95f2f2d72e1/revoke",
      headers={"X-API-Key": os.environ["INDIGENIUS_API_KEY"]},
      timeout=30,
  )
  print(response.json())
  ```
</CodeGroup>

***

## Scope reference

| Scope                 | What it grants                                         |
| --------------------- | ------------------------------------------------------ |
| `keys:read`           | List keys and scopes                                   |
| `keys:write`          | Create, rotate, update scopes, revoke keys             |
| `calls:read`          | List calls, get transcripts and analysis               |
| `calls:write`         | Initiate web and phone calls                           |
| `agents:read`         | List and fetch agents                                  |
| `agents:write`        | Create and update agents                               |
| `widgets:read`        | List and fetch widgets                                 |
| `widgets:write`       | Create, update, delete widgets and create widget calls |
| `workflows:read`      | List workflows, fetch jobs and summaries               |
| `workflows:write`     | Create, run, schedule, cancel, delete workflows        |
| `phone:read`          | List numbers, purchases, contacts                      |
| `phone:write`         | Allocate agents, schedule calls                        |
| `create_studio:read`  | List TTS, STT, dubbing jobs and voices                 |
| `create_studio:write` | Create TTS, STT, dubbing jobs                          |
| `analytics:read`      | Read dashboard and call analytics                      |
| `billing:read`        | Read billing history, transactions, plan               |
| `webhooks:read`       | Read webhook delivery history                          |

***

## Key lifecycle best practices

1. Create separate keys for `dev`, `staging`, and `prod`.
2. Grant only the scopes each key needs — never use an all-scope key in production.
3. Set `expiresAt` on production keys and rotate before expiry.
4. Revoke unused keys promptly — an idle key is an unnecessary attack surface.
5. Rotate immediately after any suspected exposure.
