API docs
OpenAI-compatible. Two env vars and any harness works — opencode, Cursor, Cline, or plain curl. Base URL: https://trulyopenrouter.vercel.app/api/gw/v1 · contracts on Hedera testnet. Running the stack yourself? Swap the base for http://localhost:4121/v1.
How it fits together
Two contracts on Hedera testnet and one off-chain router. You put HBAR into the vault and get credits. Anyone can run a host — stake, register, serve. Every routed call moves money twice: once to the host in USDC over x402, once against your credits in the vault.
subscribe(planId) payable — plan 0 is 10 HBAR → 10,000 credits
checks your limits before any money moves · picks a host on price, latency, stake and reliability
register() on HostRegistry, then serves the completion from its own GPU
credits[you] −N · hostEarnings[host] +90% · accruedFees +10%
both legs recorded, id mirrored to HCS topic 0.0.10379640
Two money legs, deliberately separate
The host is paid per request in test USDC by the gateway over x402. Your credits are metered down in the vault, where the host's 90% share accrues in HBAR and is withdrawn separately. HBAR you deposit never converts into USDC — the gateway funds the USDC leg from its own account. A receipt ties both legs to one call.
- subscribe(planId) payable — buy credits
- debit(user, host, amount, receiptHash) — gateway only
- withdraw() — host pulls earnings as HBAR
- refund() — cash out unused credits at a fixed rate
- daily quota + per-user spend caps enforced in-contract
- PROTOCOL_FEE_BPS = 1000 → 10% fee, 90% to the host
- register(...) — 4 HBAR min stake, model id + digest
- heartbeat() — stay in rotation
- updatePricing(pricePerReq, pricePer1kTokens)
- deregister() → release() after a 24h timelock
- challenge(host, receiptId) — dispute hook
- eligibleHosts(modelId) — what the router reads
curl -s https://trulyopenrouter.vercel.app/api/gw/api/config | jq
# -> { chainId: 296, registry, vault,
# facilitator: "https://api.testnet.blocky402.com",
# usdc: "0.0.429274" }git clone https://github.com/Lucas749/TrulyOpenRouter && cd TrulyOpenRouter sh quickstart.sh # ~15 min, testnet only, nothing costs money
sh host-runner/setup.sh # pull → stack → digest → register → heartbeat cron # full manual walkthrough: host-runner/README.md in the repo
from openai import OpenAI
client = OpenAI(
base_url="https://trulyopenrouter.vercel.app/api/gw/v1",
api_key="tor_sk_…", # create at /api
)
response = client.chat.completions.create(
model="qwen2.5:0.5b",
messages=[{"role": "user", "content": "Hello!"}],
)
print(response.choices[0].message.content)# opencode.json, custom provider pointing at the router
{
"$schema": "https://opencode.ai/config.json",
"model": "trulyopenrouter/qwen2.5-7b",
"provider": {
"trulyopenrouter": {
"options": { "baseURL": "https://trulyopenrouter.vercel.app/api/gw/v1", "apiKey": "tor_sk_…" }
}
}
}# issue a scoped key for your login (shown once; easiest at /api)
curl -X POST https://trulyopenrouter.vercel.app/api/gw/api/keys \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $PRIVY_ACCESS_TOKEN" \
-d '{"scopes":{"models":["qwen2.5:0.5b"]}}'
# chat, response carries tor_receipt + tor_settled
curl -X POST https://trulyopenrouter.vercel.app/api/gw/v1/chat/completions \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer tor_sk_…" \
-d '{"model":"qwen2.5:0.5b","messages":[{"role":"user","content":"hi"}]}'
# verify the receipt (hashes only, bodies never leave the hosts)
curl https://trulyopenrouter.vercel.app/api/gw/api/receipts/<id>
# network truth
curl https://trulyopenrouter.vercel.app/api/gw/api/hosts
curl https://trulyopenrouter.vercel.app/api/gw/api/statscurl https://trulyopenrouter.vercel.app/api/gw/v1/models
# -> [{ id, hosts, minPricePerReq, calls24h }] — cheapest healthy host wins per callcurl https://trulyopenrouter.vercel.app/api/gw/api/receipts/<id>
# -> { id (sha256), modelDigest, host, priceWei, debitTx, hcsSeq }
# debitTx: vault debit on HashScan · hcsSeq: same id on topic 0.0.10379640# scoped key for your login (models allowlist, expiry) — shown once
curl -X POST https://trulyopenrouter.vercel.app/api/gw/api/keys -H 'Content-Type: application/json' -H "Authorization: Bearer $PRIVY_ACCESS_TOKEN" -d '{"scopes":{"models":["qwen2.5:0.5b"]}}'
# member allowance: 429 quota_exceeded past cap · vault debit is the backstop
# key budget accounts derive per prefix (HKDF) — fund explicitly, never auto# register (4 HBAR stake + 1 HBAR gas reserve; key stays on your machine) sh host-runner/setup.sh # directory + detail + verify curl https://trulyopenrouter.vercel.app/api/gw/api/hosts curl https://trulyopenrouter.vercel.app/api/gw/api/hosts/<address> # heartbeat (cron every 10 min keeps you in rotation) · leave: tor-host leave
401 invalid_api_key — unknown/revoked key or bad wallet signature 402 payment_required — wallet out of credits, subscribe first 404 model_not_found — model not in key scope, or unknown receipt/host 409 conflict — e.g. member already active, tap already decided 429 quota_exceeded — member allowance spent, owner raises it in /team 501 unavailable — leg not configured (admin token, vault, tap signer) 502 upstream_error — host/gateway leg failed, receipt still recorded where possible