# auth.md

You are an agent. This document covers every way to access https://sparkletree.io
and how to register a credential for the SparkleTree platform API that manages
it. This host itself requires no authentication. Follow the steps in order; do
not skip ahead.

There are two tiers:

1. **This host — anonymous.** Everything on https://sparkletree.io is public.
   Registration method: `anonymous`. No credential is issued and none is
   accepted — Step 1 is the entire flow.
2. **SparkleTree platform MCP server — OAuth 2.0.**
   https://app.sparkletree.io/api/mcp (campaign management, analytics) is the
   only protected resource. Registration is dynamic client registration
   ([RFC 7591](https://datatracker.ietf.org/doc/html/rfc7591)); credentials are
   authorization-code + PKCE (S256) bearer access tokens issued by
   https://clerk.sparkletree.io. Steps 2–5. This tier acts on a SparkleTree
   account, so it requires a human user who can sign in — do not attempt it
   without one.

## Step 1 — Use this host anonymously

No registration, no credentials:

```http
GET /llms.txt HTTP/1.1
Host: sparkletree.io
```

Machine catalog: `/.well-known/api-catalog`. Per this host's
protected-resource metadata (`/.well-known/oauth-protected-resource`),
`scopes_supported` is empty — no access token could grant anything here that
anonymous access does not already have.

**What this host does not implement:** there is no claim ceremony — no
`claim_token` is ever issued, no `user_code` / `verification_uri` hand-off
exists, and no identity assertion is minted. The content is public; you already
have everything you need.

## Step 2 — Register a client (platform tier only)

```http
POST /oauth/register HTTP/1.1
Host: clerk.sparkletree.io
Content-Type: application/json

{
  "client_name": "<your agent>",
  "redirect_uris": ["<your callback URL>"]
}
```

The response is an RFC 7591 registration containing your `client_id`. Store
it. Authorization server metadata lives at
https://clerk.sparkletree.io/.well-known/oauth-authorization-server.

## Step 3 — Authorize (user consent)

Authorization-code + PKCE (S256). Send the user to
https://clerk.sparkletree.io/oauth/authorize with `client_id`,
`redirect_uri`, `response_type=code`, `code_challenge`,
`code_challenge_method=S256`, and scopes from `scopes_supported` in the AS
metadata. The user signs in and consents in their browser; the code arrives at
your `redirect_uri`. There is no device-authorization or claim-polling grant —
consent happens in the browser, not via a code you hand the user.

## Step 4 — Exchange the code for an access_token

```http
POST /oauth/token HTTP/1.1
Host: clerk.sparkletree.io
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=<code>&redirect_uri=<your callback URL>&client_id=<client_id>&code_verifier=<verifier>
```

Response: a standard OAuth token response with `access_token` (plus
`refresh_token` when `offline_access` was granted).

## Step 5 — Call the MCP server

```http
POST /api/mcp HTTP/1.1
Host: app.sparkletree.io
Authorization: Bearer <access_token>
```

The server is self-describing: an unauthenticated request returns `401` with
`WWW-Authenticate: Bearer resource_metadata="https://app.sparkletree.io/.well-known/oauth-protected-resource/mcp"`,
from which compliant MCP clients bootstrap this entire flow automatically.
Server card: https://sparkletree.io/.well-known/mcp/server-card.json

## Errors

| Status | Where | Meaning | What to do |
| --- | --- | --- | --- |
| 401 | `https://app.sparkletree.io/api/mcp` | Missing or expired access_token | Refresh (Step 4 with `refresh_token`) or restart at Step 3. |
| 400 `invalid_redirect_uri` | `/oauth/register` | `redirect_uris` missing or invalid | Fix the registration body and retry. |
| 400 `invalid_grant` | `/oauth/token` | Code expired or PKCE verifier mismatch | Restart at Step 3. |
| 429 | any | Rate limited | Exponential backoff, retry. |
| 5xx | any | Transient server error | Exponential backoff, retry the same request. |

Retry policy: 5xx → exponential backoff and retry; 4xx → do not replay the same
payload; act on the table above.

## Revocation

POST `token=<access_token>&token_type_hint=access_token` (form-encoded) to
https://clerk.sparkletree.io/oauth/token/revoke
([RFC 7009](https://datatracker.ietf.org/doc/html/rfc7009)). Idempotent.
Anonymous access to this host has nothing to revoke.

## Questions

Email support@sparkletree.io — a founder replies.
