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

# Authentication

> How to sign up, mint API keys, and authenticate every request.

The Overten API uses two different authentication schemes, and it's
important to know which one each endpoint expects:

| Scheme                    | Used by                                 | Header                                                                |
| ------------------------- | --------------------------------------- | --------------------------------------------------------------------- |
| **API key** (`sk_live_*`) | All generation, run, and file endpoints | `X-API-Key: sk_live_...`   *(or `Authorization: Bearer sk_live_...`)* |
| **Firebase ID token**     | `/signup` and key-management endpoints  | `Authorization: Bearer <firebase_token>`                              |

The separation mirrors a typical dev experience: you sign in as a human
(Firebase), mint a machine credential (API key), then your production code
only ever sees the machine credential.

## Key format

API keys have the format `sk_live_<28 alphanumeric chars>` and bill against
your org.

We only ever store `sha256(key)`. The raw secret is returned **once** at
creation time and cannot be retrieved later. If you lose a key, revoke it
and mint a new one.

## Signing up

A docs-only developer can go from zero to a usable API key with one POST.

<Steps>
  <Step title="Get a Firebase ID token">
    Sign in via the Overten dashboard or with Firebase's web SDK. See
    the [Quickstart](/quickstart#1-get-a-firebase-id-token) for both flows.
  </Step>

  <Step title="Call POST /signup">
    ```bash theme={null}
    curl -X POST "https://backend.overtenai.com/api/v1/signup" \
      -H "Authorization: Bearer $FIREBASE_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "org_name": "Acme Docs",
        "tier": "free",
        "key_name": "primary"
      }'
    ```

    The response contains `org_id`, `secret` (the `sk_live_*` key), and
    `webhook_secret`. **Store the secret somewhere safe — it is shown once.**
  </Step>

  <Step title="Use the key">
    Send `X-API-Key: sk_live_...` on every other endpoint (or, for
    existing Bearer-based integrations, `Authorization: Bearer sk_live_...`
    — both are accepted). See the rest of this page for key rotation and
    revocation.
  </Step>
</Steps>

If you already belong to a workspace in the Overten web app, pass its
`existing_org_id` instead of `org_name` and the signup will light up API
access on that org instead of creating a second one.

## Creating additional keys

You probably want separate keys per service or deployment environment:

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST "https://backend.overtenai.com/api/v1/organizations/$ORG_ID/api-keys" \
    -H "Authorization: Bearer $FIREBASE_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{ "name": "ci-tests" }'
  ```

  ```python Python theme={null}
  resp = requests.post(
      f"{API}/organizations/{org_id}/api-keys",
      headers={"Authorization": f"Bearer {firebase_token}"},
      json={"name": "ci-tests"},
  )
  print(resp.json()["secret"])  # shown once
  ```
</CodeGroup>

Response mirrors `/signup` — the `secret` field is present exactly once.

## Listing keys

```bash theme={null}
GET /api/v1/organizations/{org_id}/api-keys
Authorization: Bearer <firebase_token>
```

Returns an array of key records. Only `prefix` is shown; the raw secret
is never re-exposed, even to the key's creator.

```json theme={null}
{
  "items": [
    {
      "key_id": "key_abc123",
      "name": "primary",
      "prefix": "sk_live_4aT7",
      "created_at": "2026-04-17T11:20:00Z",
      "last_used_at": "2026-04-17T12:30:00Z",
      "revoked_at": null
    }
  ]
}
```

## Revoking keys

Revocation takes effect immediately; subsequent requests with that key
return `401 invalid_api_key`.

```bash theme={null}
DELETE /api/v1/organizations/{org_id}/api-keys/{key_id}
Authorization: Bearer <firebase_token>
```

Returns `204 No Content`.

## Rotating keys

1. Mint a new key via `POST /.../api-keys`.
2. Deploy the new key to your services.
3. Once all traffic uses the new key, revoke the old one.

Keys have no expiry — they stay valid until revoked.

## Security hygiene

<AccordionGroup>
  <Accordion title="Never commit live keys to source control" icon="triangle-exclamation">
    Treat `sk_live_*` like a database password. Use a secret manager (AWS
    Secrets Manager, Doppler, 1Password, Vault, etc.) in production.
  </Accordion>

  <Accordion title="Report leaks immediately" icon="shield">
    If you think a key has leaked, revoke it via the dashboard or DELETE
    endpoint, and then email [support@overten.ai](mailto:support@overten.ai) — we can audit the
    affected key's usage for anomalies.
  </Accordion>

  <Accordion title="Use separate keys per environment" icon="layer-group">
    One key per environment (prod / staging / CI) limits the blast radius
    of a leak. Rotate independently.
  </Accordion>

  <Accordion title="Scope is per-org, not per-key" icon="users">
    Any key belonging to an org has the same permissions on that org. We
    don't (yet) support scoped keys that only touch specific formats. If
    you need that, email us and tell us the use case.
  </Accordion>
</AccordionGroup>

## Verifying a key works

Before shipping, confirm end-to-end with:

```bash theme={null}
curl "https://backend.overtenai.com/api/v1/verify" \
  -H "X-API-Key: $OVERTEN_API_KEY"
```

Response:

```json theme={null}
{
  "org_id": "org_xyz",
  "org_name": "Acme Docs",
  "tier": "free",
  "webhook_secret": "whsec_...",
  "key_prefix": "sk_live_4aT7"
}
```

`/verify` is the cheapest call in the API — use it in health checks.

***

Continue to [Runs and tasks](/concepts/runs-and-tasks) for how we model
work, or jump straight to [Format guides](/guides/excel) for end-to-end
examples.
