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

# Authentication

> Choose the correct key model, scope boundaries, and tenant semantics for secure Callaro integrations.

# Pick auth by trust boundary, not convenience.

Callaro supports JWT, tenant API keys, partner API keys, and runtime server keys. The right choice depends on whether the caller acts for one tenant, many tenants, or internal runtime services.

<CardGroup cols={3}>
  <Card title="JWT" icon="user-round">Best for user-interactive operations in the Callaro app. Subject to app role and JWT-only controller guards.</Card>
  <Card title="Tenant API key" icon="key-round">Best for server integrations that operate inside a single tenant and need explicit scope control.</Card>
  <Card title="Partner API key" icon="building-2">Best for platform partners managing tenant provisioning and delegated operations across tenants.</Card>
</CardGroup>

## Header patterns

<Tabs>
  <Tab title="JWT">
    <CodeGroup>
      ```bash cURL theme={null}
      curl "https://api.callaro.ai/api/v1/agents" \
        -H "Authorization: Bearer $CALLARO_JWT"
      ```

      ```javascript Node.js theme={null}
      const jwtResponse = await fetch('https://api.callaro.ai/api/v1/agents', {
        headers: { Authorization: `Bearer ${process.env.CALLARO_JWT}` }
      });
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Tenant API key">
    <CodeGroup>
      ```bash cURL theme={null}
      curl "https://api.callaro.ai/api/v1/voice_sessions?page_size=25" \
        -H "X-Api-Key: $CALLARO_TENANT_API_KEY"
      ```

      ```javascript Node.js theme={null}
      const tenantResponse = await fetch('https://api.callaro.ai/api/v1/voice_sessions?page_size=25', {
        headers: { 'X-Api-Key': process.env.CALLARO_TENANT_API_KEY }
      });
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Partner API key">
    <CodeGroup>
      ```bash cURL theme={null}
      curl "https://api.callaro.ai/api/v1/partner/tenants" \
        -H "X-Partner-Api-Key: $CALLARO_PARTNER_API_KEY"
      ```

      ```javascript Node.js theme={null}
      const partnerResponse = await fetch('https://api.callaro.ai/api/v1/partner/tenants', {
        headers: { 'X-Partner-Api-Key': process.env.CALLARO_PARTNER_API_KEY }
      });
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Decision table

| Integration scenario                       | Recommended auth   | Why                                                      |
| ------------------------------------------ | ------------------ | -------------------------------------------------------- |
| Internal operator using Callaro UI         | JWT                | Uses app session/role model and JWT-only guards.         |
| Tenant backend sync job (CRM, BI, exports) | Tenant API key     | Tenant-scoped, explicit least-privilege scopes.          |
| Multi-tenant partner provisioning flow     | Partner API key    | Supports partner namespace and delegated tenant actions. |
| Runtime service-to-service internal call   | Runtime server key | Server-only routes, not customer-issued API keys.        |

## Scope model (source: API key permission matrix)

Scopes are granted per key and mapped to route families. Examples:

* `bulk_call_campaigns:read` and `bulk_call_campaigns:write`
* `contacts:read` and `contacts:write`
* `phone_numbers:read` and `phone_numbers:write`
* `voice_sessions:read`
* `billing:tenant:read` and `billing:partner:read`

<Note>
  Some scopes are opt-in and intentionally excluded from defaults, including `billing:partner:allocate` and `call_traces:admin_read`.
</Note>

## `X-Tenant-Id` semantics

When using partner APIs that operate on behalf of a downstream tenant, include `X-Tenant-Id` when required by that route family to select the effective tenant context.

<Warning>
  Do not use `X-Tenant-Id` to bypass scope restrictions. The effective action is still gated by partner key permissions and route-level authorization.
</Warning>

## Least-privilege rollout pattern

<Steps>
  <Step title="Start with read-only scopes">
    Create a dedicated key for observability and dry-run operations first.
  </Step>

  <Step title="Add write scopes only for required route families">
    Split campaign write operations from billing or contact-compliance scopes to reduce blast radius.
  </Step>

  <Step title="Use separate keys per environment and workload">
    Keep sandbox and production keys isolated, and rotate keys tied to specific services.
  </Step>

  <Step title="Review keys quarterly">
    Remove stale scopes, revoke unused keys, and validate service ownership.
  </Step>
</Steps>

<Note>
  Empty or omitted scopes should not be treated as "allow all." Use explicit scopes and audit them against the permissions matrix before go-live.
</Note>
