
Tollgate
Agents pay per API call in HBAR or an HTS token: x402 paywall, metered, no keys, no subscriptions.
Demo
About
Tollgate turns an ordinary HTTP API into a pay-per-call resource that an autonomous agent can use with no account, no API key and no subscription. An unpaid request returns HTTP 402 carrying a machine-readable price for that exact request. The agent signs a Hedera TransferTransaction for the quoted amount and retries with an X-PAYMENT header; the server verifies and settles that payment through the Blocky402 facilitator and only then serves the data. Pricing is metered rather than flat — a base charge plus a per-record charge plus a surcharge for full detail — so a one-record query costs a fraction of a hundred-record one, and the schedule is published at /schedule so an agent can budget before it spends anything. The same request can be paid in HBAR or in X402T, a Hedera Token Service token that carries a 2% fractional fee. Both prices come from one meter — the token amount is derived from the tinybar quote — so choosing the token never changes what a request costs. The token was created with every key empty, so neither its fee nor its supply can be changed by anyone, including us. The demo endpoint is live on a public host and serves real Hedera mirror-node data. The server holds no private key at all: the buyer signs, the facilitator submits the transaction and pays the network fee, and every settlement is independently verifiable on the mirror node by anyone, without trusting us or the facilitator. Payments can also be recorded as receipts on a Hedera Consensus Service topic created with no admin key, so the trail is append-only and not even the operator can rewrite or delete a record after the fact. Writing receipts needs an operator key, so it is opt-in and switched off on the public demo, which keeps that box keyless. Reading needs no key, no account and no SDK: the /receipts endpoint hands back the raw mirror-node URL alongside its own answer, so anyone can audit the same trail from a source we do not control.
How it's made
Node.js with zero runtime dependencies — the server is plain ESM, deploys as about 100 KB with no node_modules directory at all, and runs under systemd on a 1 GB box. The Hedera SDK is a buyer-side dependency only, which is precisely what allows the hosted server to hold no key material. Settlement is native HBAR on Hedera testnet through the Blocky402 facilitator (x402 "exact" scheme, CAIP-2 network hedera:testnet). We picked the native TransferTransaction over the EVM relay because a native cryptotransfer settles for roughly 107x less than an ethereumtransaction on this network. The repo carries the measurement tool rather than the claim: tools/measure-settlement-fee.mjs reads live transactions off the mirror node and reported a median charged fee of 129,394 tinybar over 100 successful transfers, which is what the base charge is pinned above so that a minimum request is never underwater on its own settlement. Verification never trusts the facilitator's own answer: the server reads the settled transfer list from the mirror REST API and sums every entry for each account, because Hedera transfer lists are double-entry and first-match reporting silently turns a gross figure into a wrong "net" one. Three things worth naming as hacky. The facilitator returns HTTP 200 for a rejected payment — the verdict is isValid in the body, not the status line — so a client written the obvious way (if (res.ok) serve()) accepts forged and underpaid payments while looking perfectly correct; only a literal true passes here. The replay key is claimed after verification passes but before settlement, and an indeterminate settlement deliberately does not release it, because a settle that timed out may still have landed and freeing the key would invite an honest buyer to pay twice. And the buyer supplies exactly one field, the signed transaction: every payment term is rebuilt from server config, so an attacker cannot hand us favourable terms and have the facilitator compare their claim with itself. 189 tests, no network in the test path, with negative controls that fail when the defence is removed. The token rail uses HTS token 0.0.10464963 (X402T) with a 2% fractional fee paid to collector 0.0.10464960, created during the event by the repo's own tools/create-fee-token.mjs. Two traps shaped it. A fractional fee marked inclusive is taken out of the transfer, so under the exact scheme the payee lands short and every settlement is rejected as underpaid; the server reads net_of_transfers off the mirror node and refuses such a token by name. And a token's treasury and fee collectors are exempt from its fees, so a demo they fund shows the fee never firing; both are refused as buyers. The buyer never names the asset: the server tries its own offers and the signature selects one, and a facilitator outage aborts instead of falling through to the other asset. On testnet a token settlement costs the facilitator about 2.8 million tinybar at steady state, against roughly a quarter of a million for HBAR. The first one cost 69 million because it included the payee auto-associating the token, a one-time cost we keep out of the per-request figure. Payment receipts go to Hedera Consensus Service topic 0.0.10446488 using the schema Hedera's own harness PRD specifies (x402.receipt.v1), rather than a shape we invented. Read and write are deliberately split. Reading is over the mirror REST API with no key at all, which is what makes an audit trail independently checkable rather than our word for it; writing needs an operator key and is therefore switched off on the hosted demo, and /health reports holdsPrivateKey and writeEnabled from the running config instead of as constants, so the box cannot advertise itself as keyless while holding a key. The topic has no submit key, so anyone can append to it, and the reader treats every message as untrusted input. The receipt operator is deliberately not the payee: it signs records and pays their sub-cent fees and can never move revenue. A receipt records the asset that actually moved: sequence 2 on the topic, written from a local instance with writing enabled, is a 300-unit X402T payment, not 300 tinybar. Emission happens after the buyer has been served and is never awaited, because a consensus round must not sit between a paying buyer and their data; a test injects an emitter that never resolves and asserts the response still lands.