# Getting a dots API key

A dots "API key" is an **OAuth client id** (`client_id`). The SDK takes it as `apiKey`.

## 1. Sign in to the dev portal

Go to your dots issuer's dev portal: `https://<issuer>/dev/clients` (dev: `https://dots.localhost/dev/clients`). Sign in with your dots account.

## 2. Create a client → **New client**

You'll set:

| Field | What to put |
|---|---|
| **Name** | your app's display name (shown on the consent screen) |
| **Client type** | **Public** for browser/SPA/mobile (PKCE, no secret). **Confidential** for server apps (issues a secret). |
| **Redirect URIs** | every callback URL, exact match — e.g. `http://localhost:3000/dots/callback`, `https://yourapp.com/dots/callback` |
| **Scopes** | `openid profile email wallet` to start; add `pute:read pute:spend` for credits, `data:read data:write` for storage |

On create you get:
- **`client_id`** → this is your `apiKey`.
- **`client_secret`** → shown **once**, only for confidential clients. Store it server-side (never ship it to the browser). Rotate via `/api/dashboard/clients/[id]/regenerate-secret`.

## 3. Use it

```ts
const dots = createDots({ apiKey: "client_xxx", issuer: "https://dots.localhost" });
```

Public client → the SDK runs PKCE in the browser; no secret needed.
Confidential client → keep the secret on your server and exchange the code there.

Persist the signed-in account under a database-unique **`(issuer, sub)`** key.
The dots-owned `sub` is stable; email, wallet, username, and social handles are
claims and must never create or merge accounts.

## Scopes cheat-sheet

`openid` (required) · `profile` · `username:create` (first-time claim on `/oauth/claim`; enable per client) · `email` · `wallet` ·
`social:google|twitter|instagram` · `listen` (streaming sources + plays) ·
`data:read` `data:write` (per-app Turso) · `files:read` `files:write` `files:share` ·
`context:read` `context:write` (portable context + MCP `search`/`recent`/`remember`) ·
`pute:read` `pute:spend` `pute:topup` · `mcp:use` (call third-party MCPs connected to the dot) ·
`cosign` `delegate` `org:act` `org:admin` · `offline_access` (refresh tokens).

The canonical list is `scopes_supported` in `/.well-known/openid-configuration`.
Self-serve dynamic registration (`POST /api/oauth/register`) allows a narrower set;
sensitive scopes are enabled per client in the dev portal.

## No browser? Use the device flow

Bots, CLIs, and chat agents can't host a redirect URI. Register a **public** client,
call `POST /api/oauth/device`, show the `user_code` / `verification_uri_complete`, and
poll `POST /api/oauth/token` with `grant_type=urn:ietf:params:oauth:grant-type:device_code`.
The user approves at `https://www.dots.id/oauth/device`. Full details in the
[REST reference](/docs/api).

> The dev portal also issues per-app **redirect URIs** and lets you mark a client internal/verified. Only the client owner can manage their clients.