# auth.md

How an AI agent registers with and authenticates to Stacktree.

Stacktree is an MCP-native publish primitive: an agent publishes HTML and
gets back a private, unguessable URL. There are three ways to authenticate,
from zero-setup to full OAuth.

## Audience

AI agents and MCP clients (Claude Code, Cursor, Codex, Claude.ai) and any
server-side or CLI tool that publishes to Stacktree's REST API.

## Machine-readable metadata

- OAuth authorization server: `https://api.stacktr.ee/.well-known/oauth-authorization-server` (includes an `agent_auth` block)
- OAuth protected resource: `https://api.stacktr.ee/.well-known/oauth-protected-resource`
- OpenAPI: `https://stacktr.ee/openapi.json`

## Registration methods

### 1. OAuth 2.1 with Dynamic Client Registration (recommended for connectors)

For MCP connectors and any agent acting on behalf of a signed-in user.

- Register a client: `POST https://api.stacktr.ee/oauth/register` (RFC 7591)
- Authorize: `https://api.stacktr.ee/oauth/authorize` (authorization code + PKCE, S256)
- Exchange code for token: `POST https://api.stacktr.ee/oauth/token`
- Revoke: `POST https://api.stacktr.ee/oauth/revoke` (RFC 7009)
- Scopes: `sites:write`, `sites:read`
- Send the access token as `Authorization: Bearer <token>`

Most clients discover all of this automatically from
`https://api.stacktr.ee/.well-known/oauth-authorization-server`.

### 2. API key (recommended for server-side and CLI agents)

- Create a key in the dashboard: `https://app.stacktr.ee/api-keys`
- Send it as `Authorization: Bearer stk_live_...`
- Keys are long-lived; revoke them from the same dashboard page.

### 3. Anonymous (no registration)

For ephemeral, one-off publishes that need no account.

- `POST https://api.stacktr.ee/sites` with a `multipart/form-data` body and no
  Authorization header.
- You get back a private, unguessable URL that lives for 24 hours.
- Example: `curl -X POST https://api.stacktr.ee/sites -F file=@index.html`

### 4. Pay-to-provision (no human in the loop)

For an agent that wants a persistent identity without a human creating an
account. The agent pays, and the payment is the credential. Payment replaces
the human sign-up step as the anti-abuse gate.

- `GET https://api.stacktr.ee/provision` returns the rail menu: which agentic-commerce
  protocols are accepted and which are currently live.
- `POST https://api.stacktr.ee/provision` carries the payment. Dispatch is by mechanism:
  - **x402** (USDC): send a base64 `PAYMENT-SIGNATURE` header. A bare POST
    returns `402` with a `PAYMENT-REQUIRED` header describing the terms.
  - **MPP** (Machine Payments Protocol): send `Authorization: Payment
    <credential>`; the Stripe method carries a shared payment token.
  - **ACP** (Agentic Commerce Protocol): `POST { "acp_shared_payment_token":
    "spt_..." }` — Stacktree redeems it as an ACP-compatible seller.
  - **AP2** (the payment layer behind UCP and Google surfaces): `POST {
    "ap2_mandate": {...} }`.
- On success you receive an `stk_live_...` API key, shown once. Use it as in
  method 2. Price is flat and shown in the rail menu.

### 5. Pay link (hand the payment to a nearby human)

For an agent with no wallet whose human is right there at the terminal.
The payment twin of the device-code flow:

- `POST https://api.stacktr.ee/pay/sessions` with `{ "feature": "provision" }` (no
  auth), or `{ "feature": "custom_domain" }` etc. with your API key.
- The response includes a short URL and a ready-to-print terminal QR
  (`qr` field). Print it; the human scans and pays by card on their phone
  (Stripe Checkout, about two taps).
- Poll `GET https://api.stacktr.ee/pay/sessions/{code}/poll` every few seconds. On
  `provision` the poll returns the new API key once; on unlocks it confirms
  the entitlement is active. Continue your task immediately.
- **Scan once, draw silently:** pass `"amount_minor"` above the price (up to
  2000 = $20) on `provision`, or use `{ "feature": "topup", "amount_minor":
  1000 }` later, and the surplus becomes a prepaid balance on the identity.
  Future paid actions draw from it automatically — no 402, no scan — until it
  runs out. Unlock 402 responses show the current balance.

## Notes

- Anonymous and API-key publishing use the same REST endpoint; the
  difference is whether an Authorization header is present.
- There is no separate signup step for agents: registration and first use
  are the same call. Sign in via the dashboard to claim and persist
  anonymously-published sites.
