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_orsmid_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)
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/premiumFrom the smidgen git repo before the package is on npm:
npm run smidgen -- login
npm run smidgen -- init --name "George blog" --site https://example.com --evm-wallet 0xGeorgeBaseAddress --stack nextlogin 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
curl -sS -X POST https://smidgen.io/api/v1/agent/device/code \
-H "Content-Type: application/json" \
-d '{"client_name":"Cursor"}'Example response:
{
"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
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:
{
"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
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.
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):
{
"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):
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
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:
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 projectsprojects:write— Create projects and update site URLs / default price (not payout wallets after create)rules:write— Create, update, and delete paywall ruleskeys: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) vssmid_sk_(WordPress) vssmid_(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.jsonon 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.