# Liquidity Dashboard auth.md

You are an agent. Liquidity Dashboard (https://liquiditydashboard.net) supports **agentic registration** for read-only access to a person's data: discover, register, claim, exchange for an access token, call the API, handle revocation. Public data needs none of this.

- Resource servers: `https://liquiditydashboard.net/mcp/pro` (Pro MCP server) and `https://api.liquiditydashboard.net` (data API)
- Authorization server (issuer): `https://liquiditydashboard.net`
- Scopes: `data.read` (read the charts and research the person's plan includes; Pro data only if they have Pro) and `data.public` (an unclaimed anonymous agent: public data only)
- Nothing here can change an account, see billing, email settings, alerts, saved charts or webhooks, or buy anything.

## No credentials needed

The MCP server `https://liquiditydashboard.net/mcp`, the A2A agent `https://liquiditydashboard.net/a2a`, `https://liquiditydashboard.net/global-liquidity-index.json`, `https://liquiditydashboard.net/fed-net-liquidity.json`, `https://api.liquiditydashboard.net/api/snapshot` and every page are open. Use them without registering.

## Step 1: Discover

- Protected resource metadata: `https://liquiditydashboard.net/.well-known/oauth-protected-resource` (and `/.well-known/oauth-protected-resource/mcp/pro`; `https://api.liquiditydashboard.net/.well-known/oauth-protected-resource`). A 401 from a protected endpoint carries `WWW-Authenticate: Bearer resource_metadata="…"`.
- Authorization server metadata: `https://liquiditydashboard.net/.well-known/oauth-authorization-server`, with the `agent_auth` block (`register_uri` / `identity_endpoint`, `claim_uri` / `claim_endpoint`). Signing keys: `https://liquiditydashboard.net/.well-known/jwks.json`.

## Step 2: Pick a method

1. **An app a person adds as a connector** (Claude, ChatGPT, any MCP client): OAuth 2.1 authorization code with PKCE. Register at `POST https://liquiditydashboard.net/oauth/register` (RFC 7591, public client, `token_endpoint_auth_method: "none"`) or use a client ID metadata document URL as `client_id`. Send the person to `https://liquiditydashboard.net/oauth/authorize` (`response_type=code`, `code_challenge_method=S256`, `scope=data.read`); they sign in and approve. Exchange the code at `POST https://liquiditydashboard.net/oauth/token` (`grant_type=authorization_code`). You get an access token (1 hour) and a refresh token (30 days, rotated on each use; reusing an old one revokes the connection).
2. **You know the person's email** → `service_auth`.
3. **You know nothing about the person yet** → `anonymous`.

Identity assertions from agent providers (ID-JAG) aren't accepted yet (`issuer_not_enabled`).

## Step 3: Register

```http
POST https://liquiditydashboard.net/agent/identity
Content-Type: application/json

{ "type": "service_auth", "login_hint": "person@example.com", "agent_name": "Your agent's name" }
```

The response has `claim_token` (keep it in memory; it's returned once) and a `claim` block: `user_code` (6 digits), `verification_uri`, `expires_in` (600) and `interval` (5).

```http
POST https://liquiditydashboard.net/agent/identity
Content-Type: application/json

{ "type": "anonymous", "agent_name": "Your agent's name" }
```

The response has an `identity_assertion` (24 hours) that exchanges for a `data.public` access token, and a `claim_token`. To act for a person, start a claim: `POST https://liquiditydashboard.net/agent/identity/claim` with `{ "claim_token": "…", "email": "person@example.com" }`; the response's `claim_attempt` block has the `user_code` and `verification_uri`.

## Step 4: Claim ceremony

Give the person the `verification_uri` and the `user_code` in one message. They open the link, sign in to Liquidity Dashboard with that email, see your agent's name and type the code. The code goes into that page, never back to you. Liquidity Dashboard never emails a code.

Poll the token endpoint, no faster than `interval`:

```http
POST https://liquiditydashboard.net/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:workos:agent-auth:grant-type:claim&claim_token=clm_…
```

While waiting: `authorization_pending` (or `slow_down`: wait longer). If the code expires (`expired_token`), call the claim endpoint again for a new one; registrations last 24 hours. If the person declines: `access_denied`. On success: `access_token` (`data.read`, 1 hour), plus `identity_assertion` and `assertion_expires` (30 days). A claimed anonymous agent's pre-claim token and assertion stop working.

## Step 5: Exchange the assertion

```http
POST https://liquiditydashboard.net/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=<identity_assertion>
```

Returns a fresh access token. Re-use the assertion until it expires or returns `invalid_grant`, then register again.

## Step 6: Use the access token

Send `Authorization: Bearer <access_token>`:

- MCP: `POST https://liquiditydashboard.net/mcp/pro`: the public tools plus `get_chart_data` (the data behind any of the charts) and `get_research_post`.
- API (GET only): `/api/series?id=`, `/api/yahoo?symbol=`, `/api/china?id=`, `/api/eia`, `/api/ism`, `/api/bulk`, `/api/momentum`, `/api/research`, `/api/research/post?slug=` on `https://api.liquiditydashboard.net`.

Pro charts return 402 if the person's account is on the free plan. Pro is a person's decision (US$20 a month after a 10-day trial at https://liquiditydashboard.net/pro); there is no agent checkout.

## Revocation

- Revoke a token: `POST https://liquiditydashboard.net/oauth/revoke` with `token=…` (RFC 7009). Revoking a refresh token ends the connection.
- The person can disconnect any app or agent in Settings on the dashboard; everything issued under it stops working (`invalid_grant` / 401).

## Errors

| Code | Where | What to do |
| --- | --- | --- |
| `invalid_request` | `/agent/identity` | Fix the body (`type`, a valid `login_hint`). |
| `issuer_not_enabled` | `/agent/identity` | Use `service_auth` or `anonymous`. |
| `invalid_claim_token`, `claim_expired` (410) | `/agent/identity/claim` | Register again. |
| `authorization_pending`, `slow_down`, `expired_token`, `access_denied` | token (claim grant) | Wait, wait longer, get a new code, or stop. |
| `invalid_grant` | token | Expired, used or revoked: start again. |
| 429 | any | Back off and retry later. |

Terms: https://liquiditydashboard.net/legal. Contact: contact@liquiditydashboard.net
