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

# Authentication

> Authenticate with a bearer token and select your tenant on every request.

Splendor uses two pieces of identity on every request:

1. A **bearer token** in the `Authorization` header that identifies you.
2. A **tenant header**, `X-Splendor-Tenant-Id`, that selects which workspace you are acting in.

```bash theme={null}
curl https://api.withsplendor.com/v1/datasets \
  -H "Authorization: Bearer $SPLENDOR_TOKEN" \
  -H "X-Splendor-Tenant-Id: $SPLENDOR_TENANT_ID"
```

You get both values from the [console](https://app.withsplendor.com). Treat the token as a secret: never embed it in client-side code or commit it to version control.

## Two kinds of API key

Most of the time a token acts within **one** tenant — that's a **tenant key** (`spltk.v1.…`), which you mint from the console's **API Keys** panel (or `POST /v1/admin/api-keys`). It's all you need for everything in these guides.

If you're building a product *on* Splendor and need to create and operate many tenants — say one per end-customer — you use a **platform key** (`splpk.v1.…`) instead. A single platform key provisions tenants and acts inside any of them by naming the tenant in the header. See [Build a platform](/guides/platform-patterns).

| Key              | Prefix      | Reaches                    | Mint it                                                    |
| ---------------- | ----------- | -------------------------- | ---------------------------------------------------------- |
| **Tenant key**   | `spltk.v1.` | one tenant                 | Console → API Keys, or `POST /v1/admin/api-keys`           |
| **Platform key** | `splpk.v1.` | every tenant you provision | Console → Platform Keys, or `POST /v1/admin/platform-keys` |

Both are shown once, and minting either is the **one action that requires a human**. It's not about the request method — you can `POST` it — it's about *which credential* is allowed: key creation rejects API keys (both tenant and platform keys get a `403`) and accepts only a signed-in admin's console session. So your first key always comes from a person in the browser. Everything *after* that authenticates with the key, so a script — or a coding agent — can do the rest.

## The tenant header

A token can grant access to more than one tenant. The `X-Splendor-Tenant-Id` header tells Splendor which one this request applies to, and the API enforces that the token actually has access to it.

The header is required on every endpoint except two:

* `GET /v1/me` — returns your identity and the tenants you can access, so it runs before you have chosen one.
* The platform endpoints (`/v1/platform/*`) — these manage your *fleet* of tenants rather than acting within a single one (see [Build a platform](/guides/platform-patterns)).

<Info>
  Requests that omit the tenant header where it is required return `400`. Requests that name a tenant your token cannot access return `403`.
</Info>

## Discover your tenants

Call `/v1/me` to see who you are and which tenants you can select. Use the `tenant_id` values it returns as your `X-Splendor-Tenant-Id`.

<CodeGroup>
  ```bash curl theme={null}
  curl https://api.withsplendor.com/v1/me \
    -H "Authorization: Bearer $SPLENDOR_TOKEN"
  ```

  ```python Python theme={null}
  me = client.get("/v1/me").json()
  for tenant in me["tenants"]:
      print(tenant["tenant_id"], tenant["role"], tenant["is_admin"])
  ```
</CodeGroup>

```json Response theme={null}
{
  "user_id": "user_01H...",
  "email": "you@example.com",
  "is_staff": false,
  "tenants": [
    { "tenant_id": "acme", "name": "Acme", "role": "Admin", "is_admin": true }
  ]
}
```

## Roles

Within a tenant, read and query endpoints are available to any member. Operations that create, change, or delete data — managing sources and connectors, editing detections, deleting datasets, triggering reindexes — require an admin role. (Splendor staff have their own internal operations endpoints, separate from everything documented here.)

See [Roles & permissions](/roles/permissions) for the full breakdown of which operations require which role, and [Plans & RBAC](/roles/plans) for how role enforcement is enabled.

## Responses to expect

| Status | Meaning                                                                                             |
| ------ | --------------------------------------------------------------------------------------------------- |
| `401`  | The token is missing, malformed, or expired.                                                        |
| `403`  | The token is valid but lacks access to the selected tenant, or the role required for the operation. |
| `400`  | The tenant header is required for this endpoint and was not supplied.                               |

For the full error model and codes, see [Errors](/reference/errors).
