Sell something in 5 minutes
Tollgate puts an HTTP 402 paywall in front of content you publish. Machines (agents, scripts, crawlers) pay per request in USDC, either on-chain over x402 or from a prepaid Tollgate credit balance. Humans in a browser get a free preview. This page takes you from zero to your first paid request.
1. Sign up and grab your publisher key
Create an account at /signup (email, password, display name). Your storefront lives at /dashboard, and it shows your publisher API key, a tg_pk_… token. That key authenticates the tollgate CLI and the resource API. Keep it secret.
2. Publish
Two ways in. Both end with a live URL under /r/<slug>.
Option A: the web wizard
Open /publish. You set:
- Title, which also generates the URL slug
- Kind:
feed,folder,dataset,site, ortool - Price in USD per unit, minimum $0.001 (so
0.004means $0.004) - Unit:
request,document,copy, orquery - Description and the content itself (markdown)
The wizard publishes your content as a single path, /today, served as markdown. It is live the moment you submit.
Option B: the CLI
Point the CLI at your account and publish a whole folder:
export TOLLGATE_PUBLISHER_KEY=tg_pk_... # from your dashboard
npx tollgate publish ./research-notes --price 0.004
Output:
live at https://<your-app>/r/research-notes
price $0.004 / request · paths: /brief.md /data.json
What the CLI does, exactly:
- Walks the folder recursively and uploads every text file:
.md,.txt,.json,.html,.css,.js,.csv,.xml,.yaml,.yml,.svg - Skips dotfiles and anything with a binary or unknown extension (it prints a
skippingline per file) - Each file becomes a paid path under the resource, so
./research-notes/brief.mdis served at/r/research-notes/brief.md - Limits: 200 files, 2 MB total content per resource
Useful flags: --title (defaults to the folder name), --slug, --kind (defaults to folder), --unit (defaults to request), --description. Running publish again with the same slug replaces the files and settings in place, so updating content is just republishing. A slug owned by another account returns 409 slug_taken.
If you run your own deployment, set TOLLGATE_URL to its base URL. Check your account any time with npx tollgate me.
3. The 402 handshake
A machine hitting a paid path without payment gets HTTP 402 plus a machine-readable offer:
curl -i https://<your-app>/r/research-notes/brief.md
HTTP/1.1 402 Payment Required
x402-price: $0.004
x402-pay-to: incr:0x8f3..c21
x402-asset: USDC
PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6Miw... (base64 v2 offer)
Content-Type: application/json
{
"x402Version": 1,
"error": "X-PAYMENT or PAYMENT-SIGNATURE header is required",
"accepts": [
{
"scheme": "exact",
"network": "base-sepolia",
"maxAmountRequired": "4000",
"payTo": "0x...treasury address...",
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"resource": "https://<your-app>/r/research-notes/brief.md",
"maxTimeoutSeconds": 60,
"extra": { "name": "USDC", "version": "2" }
},
{
"scheme": "tollgate-credit",
"network": "tollgate",
"maxAmountRequired": "4000",
"payTo": "tollgate:publisher:1",
"asset": "USDC-CREDIT",
"extra": { "hint": "Pay with a Tollgate agent API key: payload = { \"apiKey\": \"tg_sk_...\" }" }
}
]
}
maxAmountRequired is in atomic USDC units, 6 decimals, so 4000 is $0.004. The response carries both generations of the protocol: the v1 JSON body plus a v2 PAYMENT-REQUIRED header (base64 JSON with CAIP-2 network ids), so old and new clients can both pay.
The buyer picks a scheme, then retries the same request with a payment header: X-PAYMENT (v1) or PAYMENT-SIGNATURE (v2). With exact that header carries a signed USDC TransferWithAuthorization, settled on-chain via an x402 facilitator. With tollgate-credit it carries an agent API key, debited from a prepaid balance. On success the server returns 200 with the content plus an X-PAYMENT-RESPONSE (or PAYMENT-RESPONSE) header and an x402-receipt header.
To test-buy your own resource from the terminal:
export TOLLGATE_API_KEY=tg_sk_... # an agent key, or use TOLLGATE_EVM_KEY for on-chain
npx tollgate get https://<your-app>/r/research-notes/brief.md
See Give an agent a wallet for the buyer side.
4. Humans browse free, machines pay
The paywall keys off the Accept header. A request with no payment header whose Accept includes text/html (that is, a browser) gets a 200 preview page: title, description, price, and a pay-with-wallet button. Everything else gets the 402. So the same URL shows a free preview in Chrome and demands payment from curl, a crawler, or an agent. There is nothing to configure, this is the default for every resource.
5. Change the price
Dashboard, then Edit on the resource. You can change the price (minimum $0.001) and the unit. It applies to the next request immediately. From the CLI, republish with the same slug and a new --price.
6. Pause and resume
Each resource has a pause toggle on the dashboard. While paused, machine requests get 404 {"error":"resource is paused"} and nobody is charged; the human preview page still renders. Toggle again to go back live.
7. Get paid
Every settled request credits your publisher balance (visible on the dashboard and via tollgate me).
- Payout address: set it on the dashboard. It must be an EVM address,
0xplus 40 hex characters. Withdrawals are USDC on Base. Submitting an empty address clears it. - Withdraw: one click sweeps your entire balance into a payout with status
pending. Pending means pending treasury settlement: on-chain revenue lands in the platform treasury, and a treasury operator sends the USDC to your address and marks the payout sent. That final transfer is deliberately a manual step so a human controls outflows; the mechanics are in Go live with real USDC. - Your most recent payouts and their statuses are listed on the dashboard.
8. Keep the books: earnings CSV
Download your full payment history at /dashboard/earnings.csv. One row per paid request with columns timestamp, resource, path, payer, amount_usd, receipt, scheme, ready for a spreadsheet or your accountant.
Next steps
- Go live with real USDC: treasury setup, facilitator config, mainnet
- Give an agent a wallet: the buying side
- CLI & SDK: full command and library reference