TOON Protocol
Your machine. Paid per request.
Run your app or agent where it already lives, reachable with no server, no domain and no open port, shown on devnet. TOON gets requests to your app and makes sure each one is paid before your code sees it.
curl -fsSL https://toon.ar.io/install.sh | shHow a request travels
One packet, paid hop by hop.
Whoever pays sends one packet. Each connector on the way keeps its hop fee and passes the rest on. The last connector hands your app a plain HTTP request.
Six commands
From install to a paid app.
Output below is what toon 0.2.0 printed, the release named on the install page. Trimmed lines are marked with an ellipsis, and the wallet in them was thrown away.
-
01
Install
One line puts the release binary on Linux, x86_64 or aarch64. No Rust toolchain, no account.
The shellcurl -fsSL https://toon.ar.io/install.sh | sh Installed toon 0.2.0 (connector 7d0582e29c07…, relay ghcr.io/toon-protocol/relay:rust-sha-1b02f2e@sha256:3eea8d94…) at ~/.local/bin/toon -
02
Create a wallet and a first app
toon initmakes the wallet and a relay that is reachable as a hidden service: an.anyoneaddress on the Anyone network, which needs no open port and no public address. The mnemonic is shown once.toon 0.2.0 · devnettoon init --accept-anyone-terms Wallet created at ~/.toon/agent-node/keystore.json. Your mnemonic. It is shown this once and no command shows it again; write it down now: … … TOON app created: relay. Fund its settlement keys, then run `toon up` to start it. relay is a hidden service. Its … endpoint is jf66qlxvjvyd…c5id.anyone: the connector answers on port 80, and the relay's read port on port 7100. … Run `toon wallet fund` to fund them from the devnet faucet. -
03
Fund it
On devnet the faucet sends test tokens, not ETH. On mainnet you send USDC to the printed address.
toon 0.2.0 · devnettest tokens from the faucettoon wallet fund Asked the devnet faucet for: 0x173780d7…52d9 (evm): asked Every settlement key holds what `toon up` needs. Run `toon up`. The gas a deposit needs is not held: 0x173780d7…52d9 (evm): 0.001 ETH for gas. The devnet faucet sends no ETH: Base Sepolia ETH comes from a public Base Sepolia faucet, which you give the EVM address named here. -
04
Start it
toon upwrites asystemd --userunit, so the node outlives this terminal.toon statusshows what is running and at which address.toon 0.2.0toon up toon status -
05
Join the network
Until now the node reaches nobody.
toon joinpeers your connector toward the project's connector and opens the channel that pays for the hop. From here it can pay anything on the network. The faucet sends no ETH: depositing into a channel, which joining a network does, costs gas, so send a little Base Sepolia ETH from a public faucet to the addresstoon wallet showlists. About 0.001 ETH is enough; Money has the details.toon 0.2.0 · devneta deposit of faucet tokens, plus Base Sepolia ETH for gastoon join devnet --deposit 1000000 --yes -
06
Put your app behind it
Any HTTP service in a container image, at the price you choose. From then on every request that reaches it has been paid for.
toon 0.2.0the price is in units of the token you settle intoon add echo --to relay --image echo-app --price 2 --yes toon route list
What your app sees
It never handles a payment.
The connector sits in front of your app. It refuses an unpaid request and says the price. Once the request is paid, it passes your app plain HTTP. Your app needs no SDK, no wallet and no billing code.
You set the price. There is no protocol fee: the only fees on a route are the hop fees that each connector chooses to charge.
There is no company you sign up with; anyone can run a connector. TOON builds on Interledger, the open protocol that routes value in packets.
Where it is reachable
Reachable with no open port
A new TOON app is reachable as a hidden service, at an .anyone address, with no open port and no public address. A hidden service is reached through the Anyone network, so it hides where your app is, though not who it pays: payments are on a public chain.
# Payer: pay the app behind NAT through the devnet relay, at its public https address (the payer runs no anon daemon. The relay carries the packet over the Anyone overlay to the provider.) FULFILL 200 paid 3 to the hub # Payer: scan the home's public address (masked here) from the Linode linode-payer# nmap -n -Pn -T4 --top-ports 1000 <home-ip> All 1000 scanned ports on <home-ip> are in ignored states. Not shown: 1000 filtered tcp ports (no-response)
Shown on devnet, with test USDC, through one relay the project operates. Demo README · Recording · Settlement transaction
Run it from an agent
The same commands, as JSON.
Every toon command is non-interactive and accepts --json, and prints one JSON document. Every command that pays states its amount and needs --yes. An agent drives the same surface you do.
spaceturtle is an agent that does: it starts a node, funds a wallet, and adds your app on request. Agent keys →
To pay one
One channel, then paid requests
Reads are free. Writes are paid. The client opens one channel toward the node it peers with, and every signed request after that reaches any app on the network, hop by hop, each hop keeping its fee. A refusal comes back as a value, not an exception.
ILP routes, x402 settles. Pay a node →
const client = await ToonClient.create({ connector, mnemonic, channelStore }); await client.channel.open({ deposit: 100_000n }); // once: 0.10 USDC const answer = await client.send({ body: 'hello' }); // every request after answer.fulfilled ? answer.text() : answer.code // a refusal is a value
ILP routes · x402 settles · no fee
No cloud. No domain. Paid per request.
Host what you build on your own machine, set a price, and get paid for every request. The app knows nothing about payment.
curl -fsSL https://toon.ar.io/install.sh | sh