# Have an AI set up smidgen for you

This document is the source of truth for **coding agents** (Cursor, Claude Code, Copilot, Aider, and similar) that set up and manage smidgen **for a human publisher**.

Read this file completely before calling any API. Do not invent endpoints. Do not skip the human signup or approval steps.

**Preferred path:** `npx @smidgen/cli` (`login`, `init`, `doctor`). Raw HTTP is the fallback if the CLI cannot run.

- HTML version: https://smidgen.io/integrations/publisher-agents
- This markdown: https://smidgen.io/integrations/publisher-agents.md
- OpenAPI: https://smidgen.io/integrations/publisher-agents/openapi.json
- CLI: https://smidgen.io/integrations/publisher-agents (and GitHub `packages/cli`)
- Agent catalog: https://smidgen.io/.well-known/ai-catalog.json
- LLM index: https://smidgen.io/llms.txt

## Two kinds of agents (do not mix them)

1. **Paying agents** (x402 buyers) discover paid URLs, receive HTTP 402, pay USDC, and retry. They never create a smidgen account. Guide: https://smidgen.io/integrations/agents
2. **Publisher coding agents** (you) help a human ship a paywall on their site. The human owns the account. You hold a delegated token after they approve you.

If you were asked to *pay* for content, stop and use https://smidgen.io/integrations/agents instead.

## What you must never do

- Do not create a smidgen account. There is **no signup API**.
- Do not ask the human to paste a magic-link URL or session cookie into chat.
- Do not commit `smid_ag_` or `smid_sk_` tokens to git. Put them in ignored env files.
- Do not change payout wallets on an **existing** project. The API rejects that. The human updates payouts in the dashboard.
- Do not use a Publisher API key (`smid_sk_`) as an agent token. Those keys only sync WordPress rules for **one** project.
- Do not log tokens.

## Step 0 — Human creates the account

Tell the human (call them George):

1. Open https://smidgen.io/login
2. Sign in with email (magic link) or a wallet (MetaMask on Base, or Phantom on Solana)
3. Confirm they can see https://smidgen.io/dashboard
4. Come back to you when that is done

Wait. Do not continue until George says he is signed in.

Free plan: 1 project, 5 paywall rules, one chain (Base **or** Solana). Plan limits return HTTP 403 with `code` `PROJECT_LIMIT`, `RULE_LIMIT`, or `CHAIN_LIMIT`.

## Preferred — CLI (do this unless it cannot run)

```bash
npx @smidgen/cli login
npx @smidgen/cli init --name "George blog" --site https://example.com --evm-wallet 0xGeorgeBaseAddress --path "/premium/*" --stack next
npx @smidgen/cli doctor --url https://example.com/premium
```

From the smidgen git repo before the package is on npm:

```bash
npm run smidgen -- login
npm run smidgen -- init --name "George blog" --site https://example.com --evm-wallet 0xGeorgeBaseAddress --stack next
```

`login` runs RFC 8628 device authorization: it prints a URL + user code, George clicks Authorize, the token is stored in `~/.smidgen/credentials.json` (not git). `init` creates the project and a paywall rule, writes `.env.local` (gitignored), and for `--stack next` writes `middleware.ts` if missing. `doctor` GETs George's URL as a bot and expects HTTP 402.

Ask George for the site URL and the payout wallet **before** `init`. Stacks: `next` (default), `html`, `wordpress` (mints `smid_sk_` into `.env.local`).

If `npx @smidgen/cli` is not published yet, use `npm run smidgen` from this repo or the curl fallback below.

## Fallback — device authorization (RFC 8628)

George approves you in the browser. He never pastes a secret into chat.

### 1a. Request a device code

```bash
curl -sS -X POST https://smidgen.io/api/v1/agent/device/code \
  -H "Content-Type: application/json" \
  -d '{"client_name":"Cursor"}'
```

Example response:

```json
{
  "device_code": "high-entropy-secret-for-you-only",
  "user_code": "WDJB-MJHT",
  "verification_uri": "https://smidgen.io/device",
  "verification_uri_complete": "https://smidgen.io/device?user_code=WDJB-MJHT",
  "expires_in": 900,
  "interval": 5
}
```

Keep `device_code` secret (it is not the user code). Show George `verification_uri_complete` and the `user_code`.

Codes expire in 15 minutes. Poll no faster than `interval` seconds or you get `slow_down`.

### 1b. George approves

Tell George, verbatim:

> Open this URL while signed into smidgen, confirm the code matches **USER_CODE**, and click **Authorize this agent**: VERIFICATION_URI_COMPLETE

If he is not signed in, the page sends him to login and returns to `/device`.

### 1c. Poll for the access token

```bash
curl -sS -X POST https://smidgen.io/api/v1/agent/device/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=DEVICE_CODE"
```

JSON is also accepted: `{"grant_type":"urn:ietf:params:oauth:grant-type:device_code","device_code":"DEVICE_CODE"}`.

Poll every `interval` seconds until one of:

| HTTP | `error` | Meaning |
| --- | --- | --- |
| 400 | `authorization_pending` | George has not approved yet. Keep polling. |
| 400 | `slow_down` | You polled too fast. Wait longer, then continue. |
| 400 | `expired_token` | Start again from 1a. |
| 400 | `access_denied` | George clicked deny. Stop. |
| 400 | `invalid_grant` | Bad or already-used device_code. |
| 200 | (none) | Success. Save `access_token`. |

Success body:

```json
{
  "access_token": "smid_ag_…",
  "token_type": "Bearer",
  "expires_in": 7776000,
  "scope": "projects:read projects:write rules:write keys:write"
}
```

Store `access_token` as `SMIDGEN_AGENT_TOKEN` in a local env file that is gitignored. The token is shown once. Default lifetime is 90 days. George can revoke it at https://smidgen.io/dashboard/settings.

### Alternative: dashboard token

If George prefers, he can open https://smidgen.io/dashboard/settings → **Connect an agent** → generate a token → paste `smid_ag_` into your env. Same API after that. Prefer device flow so the secret never sits in the chat.

## Step 2 — Confirm the token

```bash
curl -sS https://smidgen.io/api/v1/agent/me \
  -H "Authorization: Bearer smid_ag_…"
```

Expect `user.plan` and `token.scopes`. If 401, the token is wrong, expired, or revoked.

## Step 3 — Create a project

You **may** set the payout wallet **only when creating** the project. Ask George for the address USDC should go to (MetaMask 0x… on Base, and/or Phantom on Solana). You cannot change it later via this API.

```bash
curl -sS -X POST https://smidgen.io/api/v1/agent/projects \
  -H "Authorization: Bearer smid_ag_…" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "George blog",
    "siteUrl": "https://example.com",
    "evmEnabled": true,
    "evmWallet": "0xGeorgeBaseAddress",
    "evmNetwork": "eip155:8453"
  }'
```

Solana instead (or in addition on Pro/Business):

```json
{
  "name": "George blog",
  "siteUrl": "https://example.com",
  "solanaEnabled": true,
  "solanaWallet": "GeorgeSolanaBase58Address",
  "solanaNetwork": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
}
```

Common networks:

- Base mainnet: `eip155:8453`
- Base Sepolia: `eip155:84532`
- Solana mainnet: `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`
- Solana devnet: `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1`

Response `project.id` is the public id (`smid_…`). Use that in every later path. It is not a secret.

List projects: `GET https://smidgen.io/api/v1/agent/projects`

Update name, site URLs, or default price (not payouts):

```bash
curl -sS -X PATCH https://smidgen.io/api/v1/agent/projects/smid_PROJECT \
  -H "Authorization: Bearer smid_ag_…" \
  -H "Content-Type: application/json" \
  -d '{"siteUrl":"https://example.com\nhttps://www.example.com","defaultPriceCents":10}'
```

`defaultPriceCents` is USDC cents (`10` = $0.10).

## Step 4 — Paywall rules

```bash
curl -sS -X PUT https://smidgen.io/api/v1/agent/projects/smid_PROJECT/rules \
  -H "Authorization: Bearer smid_ag_…" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Premium article",
    "pathPattern": "/premium/*",
    "selector": "premium-article",
    "selectorType": "data-attribute",
    "priceCents": 10,
    "enabled": true,
    "origin": "https://example.com"
  }'
```

`selectorType` is `data-attribute`, `class`, or `css-selector`. For the HTML snippet, mark content with `data-x402-paywall="premium-article"` matching `selector`.

List: `GET https://smidgen.io/api/v1/agent/projects/smid_PROJECT/rules`  
Delete: `DELETE https://smidgen.io/api/v1/agent/projects/smid_PROJECT/rules/RULE_UUID`

Then install the matching publisher integration so the **publisher origin** returns HTTP 402 (not smidgen.io): https://smidgen.io/integrations

## Step 5 — WordPress Publisher API key (optional)

WordPress uses a **different** key (`smid_sk_`), bound to one project:

```bash
curl -sS -X POST https://smidgen.io/api/v1/agent/projects/smid_PROJECT/publisher-key \
  -H "Authorization: Bearer smid_ag_…"
```

Shown once. Paste into WordPress → Settings → smidgen.io with API URL `https://smidgen.io` and the project id. Then enable **Paywall this content** on posts (rules sync; you usually do not PUT rules by hand).

## Scopes

Default device-flow tokens include:

- `projects:read` — List and read your projects
- `projects:write` — Create projects and update site URLs / default price (not payout wallets after create)
- `rules:write` — Create, update, and delete paywall rules
- `keys:write` — Mint or rotate the WordPress Publisher API key (smid_sk_…)

There is no `payouts:write` scope. After create, payout changes are dashboard-only.

## Security model (why this is safe)

- Identity: George proves email or wallet at signup. You cannot mint users.
- Delegation: RFC 8628 device grant. George sees the user code and scopes before authorize.
- Storage: tokens hashed SHA-256 at rest; raw value shown once; prefix only in the dashboard.
- Least privilege: no payout mutation, no billing, no account delete.
- Revocation: https://smidgen.io/dashboard/settings
- Rate limits on device code, polling, and API calls.
- `smid_ag_` (you) vs `smid_sk_` (WordPress) vs `smid_` (public project id).

## After setup

- Humans pay in the browser; bots pay via x402 on George's domain. Paying-agent snippets: https://smidgen.io/integrations/agents
- Catalog from rules: `/.well-known/ai-catalog.json` on George's site. Hub catalog: https://smidgen.io/.well-known/ai-catalog.json
- Coinbase Bazaar can list a URL after the first successful settle.

If anything 401s, stop and have George revoke + re-approve. If 403 with a plan `code`, explain the Free-plan cap and the pricing page https://smidgen.io/pricing.
