---
name: stacktree-pay-per-publish
description: Put an HTML page online at a permanent, private, shareable link and pay for it per page over x402 (USDC on Base or Solana) or MPP, with no account and no API key. Use when an agent holding a wallet has generated HTML (a report, a dashboard, a landing page) and needs to hand someone a link to it.
---

# Stacktree: pay-per-publish HTML hosting

Stacktree turns HTML an agent made into a private, unguessable link that opens in any browser. One payment publishes one page: no account, no API key, no human in the loop.

## Hosts

- `https://agents.stacktr.ee`: the pay-per-publish front door. x402 (USDC on Base or Solana) or MPP (USDC.e on Tempo).
- `https://api.stacktr.ee`: the main API. The same keyless publish over x402 (USDC on Base or Solana) or MPP (evm method on Base), API keys for repeat publishing, free 24-hour pages, revisions, and MCP at `https://api.stacktr.ee/mcp`.

## Paid routes

| Request | Price | Body | You get |
|---|---|---|---|
| `POST https://agents.stacktr.ee/api/publish` | $0.50 | `{"html": "<!doctype html>..."}` | a permanent private page |
| `POST https://api.stacktr.ee/publish` | $0.50 | `{"html": "<!doctype html>..."}` | a permanent private page |
| `POST https://api.stacktr.ee/provision` | $1.00 | none | a persistent `stk_live_` API key, shown once |

`html` is required and must not be empty. A paid request is checked before the payment settles, so one that cannot be published is refused and never charged. The exception is an MPP credential you broadcast yourself: that money moved before we saw the request.

Free, no payment: `POST https://api.stacktr.ee/sites` with the same body publishes a page that lasts 24 hours. It needs a direct connection: from a datacenter or a proxy it returns 400, so pay or use an API key there.

## Example

```
curl -i -X POST https://agents.stacktr.ee/api/publish \
  -H 'content-type: application/json' \
  -d '{"html":"<!doctype html><h1>Hello</h1>"}'
```

Without a payment this returns `402 Payment Required` with the terms. Pay them and send the same request again. The paid response carries `url`, the link to share, and `claim_token`, which revises the page.

## How payment works

1. Send the request without payment. The 402 carries the terms in the `PAYMENT-REQUIRED` header (x402 v2: base64 JSON whose `accepts` lists scheme, network, amount, asset and payTo) and in a `WWW-Authenticate: Payment` header (MPP). The JSON body repeats them.
2. Choose one entry of `accepts`. Base is always `accepts[0]`.
3. Sign, do not transfer. An x402 client signs a USDC authorization and sends the same request again with it in the `PAYMENT-SIGNATURE` header. Gas is covered and the facilitator settles it. A plain USDC transfer to `payTo` pays for no request and publishes nothing.
4. Check `payTo` against `https://api.stacktr.ee/.well-known/x402-service` before you sign, and never copy it from transaction history: lookalike addresses are in circulation.

From Node, with a wallet holding USDC on Base (`npm install @x402/fetch @x402/evm viem`):

```js
import { wrapFetchWithPaymentFromConfig } from '@x402/fetch';
import { ExactEvmScheme } from '@x402/evm';
import { privateKeyToAccount } from 'viem/accounts';

const account = privateKeyToAccount(process.env.WALLET_PRIVATE_KEY);
const payingFetch = wrapFetchWithPaymentFromConfig(fetch, {
  schemes: [{ network: 'eip155:8453', client: new ExactEvmScheme(account) }],
});
const res = await payingFetch('https://agents.stacktr.ee/api/publish', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ html: '<!doctype html><html>...</html>' }),
});
const page = await res.json(); // page.url, page.claim_token
```

With AgentCash: `npx agentcash@latest fetch https://agents.stacktr.ee/api/publish -m POST -b '{"html":"<!doctype html>..."}'`

With MPP: answer the `WWW-Authenticate: Payment` challenge with an MPP client such as mppx.

## Errors

Error bodies are JSON, and a refusal names its cause in `error`.

- `402` before you pay: read the terms and pay. `402` after you paid: the payment was refused. Check network, asset, amount and payTo against `accepts` and sign again.
- `400`: no `html` in the body. `413`: the page is too large. `422`: the content was refused. None of these is charged.
- `404` or `405`: wrong path or method. Publishing is a POST to a route above, not to the host root.
- `503` with `payment_setup_unavailable` (front door): retry in a few seconds. Nothing was charged.

## After publishing

- Revise the page for free at the same URL: `PUT https://api.stacktr.ee/sites/{id}` with `Authorization: Claim <claim_token>` and the same JSON body. Paying again makes a second page at a different URL.
- Full payment guide: https://stacktr.ee/x402.md
- The full Stacktree skill (whether the page was opened, handing it to a person, passcodes): https://stacktr.ee/.well-known/skills/stacktree/SKILL.md
- OpenAPI: https://api.stacktr.ee/openapi.json and https://agents.stacktr.ee/openapi.json
