# Sign-in and API keys · DameDoklad docs

> How the public API and MCP authenticate, how to create an API key and what its scopes allow.

Source: https://damedoklad.cz/en/docs/authentication/

# Sign-in and API keys

How the public API and MCP authenticate, how to create an API key and what its scopes allow.

The public API at `https://api.damedoklad.cz/v1` authenticates with an **API key** or an **OAuth access token**. The MCP server at `https://api.damedoklad.cz/mcp` takes both; see [MCP server](/en/docs/mcp/) for OAuth.

## API key

Send the key in the `Authorization` header:

```bash
curl https://api.damedoklad.cz/v1/series \
  -H "Authorization: Bearer secret_…"
```

-   A key starts with `secret_` and belongs to **one company**. You do not send an `X-Tenant` header to `/v1`: the company comes from the key.
-   You see the full key only once, when you create it. We store only its SHA-256 hash, so it cannot be shown again.
-   Treat it like a password: keep it out of browser code and out of your repository.

## Scopes

A key has one of two scopes, and on top of that may have a separate permission to send:

| Scope | What it allows |
| --- | --- |
| `read` | Only `GET` requests. Anything else gets a `403` with the code `insufficient_scope`. The exception is the exchange at `POST /v1/pohoda/xml`, where a list is asked for by POST: reading passes and each write is refused. |
| `full` | Reading and writing, with the rights of a company owner within `/v1`. |
| `send` | On top of `full`: confirm sending a payment order to a bank and a filing to an authority. **Full access does not include it.** See below. |

Give each integration the narrowest scope it can work with. An OAuth connection has the same scopes, chosen when you approve it; writing is then also limited by your own role in the company. A key or connection of someone with a [custom role](/en/docs/guides/team/) can do only what that role can, a `read` key included.

## Sending through the API and MCP

A key with full access can prepare a payment order or a filing, but not send it. It gets a `403` with the code `send_scope_required`. It may send only when all of this holds:

-   The owner of the company turned it on under **Settings > More > API and MCP** and set limits. It is off by default.
-   The key or connection has the permission to send. Only an owner, in the app, can create a key with it. An OAuth connection has to ask for `send` itself, and you see that on the consent page.
-   The person the key belongs to is an owner of the company today.
-   The amount fits the limit per order and the daily limit, and a filing fits the daily number.

The request must state the digest of the exact data that preparing answered. The operator must have allowed sending, as for the app, and the bank still wants its own signature. Every send goes into the audit log with the name of the key, and the owner gets a notice and an e-mail.

The limits are in crowns, so an order in another currency does not go out through the API. A key can only turn sending off or lower a limit; turning it on and raising a limit happen only in the app.

## Creating a key

You create a key in the app, in **Settings > API and MCP**, or through the API. An owner or accountant can create one, and the company’s plan must include the API; otherwise you get a `402` with the code `plan_limit`.

```bash
curl https://api.damedoklad.cz/v1/api-keys \
  -H "Authorization: Bearer $DAMEDOKLAD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Online shop connection", "scope": "read" }'
```

```json
{
  "object": "api_key",
  "id": "key_…",
  "name": "Online shop connection",
  "scope": "read",
  "hint": "secret_abcdefg…",
  "secret": "secret_abcdefg…the full key"
}
```

Revoke a key in the same place, or with `DELETE /v1/api-keys/{id}`. Anything using it stops working immediately.

## Dashboard API

The app itself uses `/app/v1` with a short-lived access token (15 minutes), a refresh token in a cookie and an `X-Tenant` header with the company ID. It offers the same operations as `/v1`, with permissions by the signed-in user’s role, plus a few for the app only. Use `/v1` and an API key for integrations.

## Sign-in errors

| Status | Meaning |
| --- | --- |
| `401` | The key is missing or invalid. The message is `API key required` or `Invalid API key`. |
| `403` | The key or connection is read-only, code `insufficient_scope`. |

Other errors are on the [Errors and limits](/en/docs/errors-and-limits/) page.
