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

# Authentication

> Create an API key and send it as a Bearer token

The public API authenticates with **API keys only**. There is no OAuth flow, no username and
password, and no session — a key is all a request needs.

## Create a key

<Steps>
  <Step title="Open Settings → API Keys">
    In the dashboard, go to **Settings** and open the **API Keys** tab. You need the
    *API keys* permission; account owners have it by default.
  </Step>

  <Step title="Create a key with a name">
    Click **Create API Key** and give it a name that says what it is for
    (`crm-sync`, `website-form`). Names must be unique within the account.
  </Step>

  <Step title="Copy it now">
    The full key — `pk_` followed by 43 characters — is shown **once**. Copy it into your
    secret store. Afterwards the dashboard only shows a preview (`pk_abcd...`).
  </Step>
</Steps>

## Send it with every request

Put the key in the `Authorization` header as a Bearer token:

```bash theme={null}
curl https://api.dialtu.com/api/v2/public/salesflow/pipelines/12/stages \
  -H "Authorization: Bearer pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```

In the **Try it** panel of any endpoint page, paste the key into the **Authorization** field;
the request is sent through the documentation site's proxy, so it works from the browser.

## When authentication fails

Authentication is checked before anything else, so these responses have a plain `{"detail"}`
body rather than the `error_code` envelope described in [Errors](/en/api-reference/errors):

| Situation                                   | Response                                                                          |
| ------------------------------------------- | --------------------------------------------------------------------------------- |
| Missing or malformed `Authorization` header | `401` `{"detail": "Unauthorized"}`                                                |
| Unknown or deleted key                      | `401` `{"detail": "Invalid or expired API key. Please check your credentials."}`  |
| Key created before per-sub-account scoping  | `401` `{"detail": "This API key is not scoped to a workspace. Contact support."}` |

## Scope: what a key can reach

A key belongs to the account it was created in and can only read and write that account's
data. If your account is a partner account with several sub-accounts beneath it, **a key
covers exactly one sub-account** — the one you were in when you created it:

* List endpoints return only that sub-account's records, including their `count`.
* An ID that belongs to a sibling sub-account does not exist as far as your key is concerned:
  you get a `404` or a `UNKNOWN_*` refusal, never data from the wrong calendar or pipeline.

To integrate several sub-accounts, create one key inside each and send each sub-account's
requests with its own key.

## Keep keys safe

<Warning>
  A key grants the same access as a user of the account. Treat it like a password.
</Warning>

* Use keys **server-side only**. Never embed one in a mobile app, a browser bundle or a public
  repository.
* Create **one key per integration**, named after it, so revoking one does not break another.
* **Revoke** a key by deleting it in **Settings → API Keys**; requests with it fail immediately
  with `401`.
* To **rotate**, create the new key, switch your integration over, then delete the old one.
  There is no expiry — a key stays valid until you delete it.
