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

# Authentication

> Bearer credentials, issued per workspace and revocable per request.

Every request carries a bearer token:

```http theme={null}
Authorization: Bearer mdsk_api_xxxxxxxxxxxxxxxxxxxxxxxx
```

Credentials are issued per workspace in the dashboard under **Settings → API**.
Only the workspace owner can create one.

## Two kinds of credential

They are not interchangeable. The prefix tells you which is which.

| Prefix      | Surface                  | Where to issue it  |
| ----------- | ------------------------ | ------------------ |
| `mdsk_api_` | The REST API at `/v1`    | **Settings → API** |
| `mdsk_mcp_` | The MCP server at `/mcp` | **Settings → MCP** |

An API token sent to the MCP server is rejected, and the reverse is also true.
One credential type per surface means pulling your AI agent's access does not
also break your billing integration.

## Shown once

We keep a hash of the token, not the token. When you create one, it appears on
screen and never again. Lose it, and the path is to revoke it and issue another.

The dashboard lists each credential by its label and the first few characters.
That is enough to tell them apart when you are deciding whether a revoke is
safe. Give them labels that say where they run.

## Revocation is immediate

`revoked_at` is checked on every request, not cached. A revoked token stops
working on its very next call. No propagation delay to wait out during an
incident.

## Scope

A credential belongs to one workspace, and no parameter changes that. It
cannot be pointed at another workspace, which is what makes it safe to hand to
an AI agent that may be reading untrusted text.

An integration acts with the permissions of a **member**, not an owner. It
can read and work tickets. Billing, invitations, and workspace settings are
off limits.

## Failures

<ResponseField name="401 invalid_credential" type="error">
  Missing, malformed, expired, or revoked. Check that the header is
  `Authorization: Bearer <token>` and that the token matches the surface you
  are calling.
</ResponseField>

<ResponseField name="404 not_found" type="error">
  You asked for a resource in another workspace. This is on purpose, not a
  403: a 403 would confirm the resource exists, which is the leak itself.
</ResponseField>

## Keep it server side

The token can read every conversation in the workspace and reply to any of
them. It belongs on a server. Never ship one in a browser bundle or a mobile
app.

If you want conversations to start from a web page, you want
[the chat widget](/channels/chat-widget). It uses a public key that is safe to
expose and is checked against the domain it loads on.

## Request ids

Every response carries an `X-Request-Id` header. Log it. Quoting it in a
support request is the difference between us finding your call and guessing.
