Docs
An agent with a wallet, a rent bill and a stock portfolio.
What this is
Lodgerwell is one wallet on Robinhood Chain (chain id 4663) and one server that controls it. It sells a small JSON answer per call. It pays 1 USDG of rent every day at 00:00 UTC. At 00:10 UTC it spends what is left above a 3-day rent reserve on one Robinhood stock token.
The answer (a "read") is about one of three Robinhood stock tokens: MSFT, GOOGL, AMZN. It contains the price from the stock's Uniswap V3 pool on Robinhood Chain (RC pool price · live · unofficial), the amounts the pool holds, the change against our own sample from about 24 hours ago, and a short note that describes those numbers. It does not predict and it does not recommend.
The note is a short plain-English restatement of the pool numbers, written by a language model (Claude Haiku 5.5, called through OpenRouter) that is told to describe the numbers only. If the model is unreachable or its answer breaks the rules (advice, forecast), the server uses a fixed template instead. The field noteSource always says which one you got: "model" or "template".
Try a free read
No wallet, no key. Same JSON shape as a paid read, with paid:false, paper:true and receipt:null. The note may be up to 10 minutes old (note_from tells you when it was written). Free reads are limited to a few per IP address per day; past that you get HTTP 429 with retryAfterSec.
curl https://__HOST__/api/try/MSFT
Pay for a live read
A live read costs 0.05 USDG. The flow is x402-style: HTTP 402 with the payment requirements, and your proof is a transaction hash. It is not the Coinbase x402 facilitator and not the EIP-3009 scheme.
- Ask for the read without a header. You get
402with the asset, the recipient and the amount. - Send that amount of USDG to the agent wallet on Robinhood Chain.
- Ask again with the transaction hash in the
X-Paymentheader.
# 1. what to pay curl -i https://__HOST__/api/read/MSFT # 2. pay 0.05 USDG (50000 raw, USDG has 6 decimals) cast send __USDG__ "transfer(address,uint256)" __AGENT__ 50000 \ --rpc-url https://robinhood-rpc.publicnode.com --private-key $KEY # 3. show the transaction hash curl -H "X-Payment: 0x…txhash" https://__HOST__/api/read/MSFT
The same thing in Node with viem:
import { createPublicClient, createWalletClient, http, parseAbi, defineChain } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
const chain = defineChain({ id: 4663, name: 'Robinhood Chain', nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
rpcUrls: { default: { http: ['https://robinhood-rpc.publicnode.com'] } } });
const account = privateKeyToAccount(process.env.KEY);
const pub = createPublicClient({ chain, transport: http() });
const wc = createWalletClient({ account, chain, transport: http() });
const url = 'https://__HOST__/api/read/MSFT';
const { accepts: [a] } = await (await fetch(url)).json(); // 402 body: asset, payTo, amount
const hash = await wc.writeContract({ address: a.asset, abi: parseAbi(['function transfer(address,uint256) returns (bool)']),
functionName: 'transfer', args: [a.payTo, BigInt(a.amount)] });
await pub.waitForTransactionReceipt({ hash });
console.log(await (await fetch(url, { headers: { 'X-Payment': hash } })).json());
Rules for the proof
- The transaction must have succeeded, contain a USDG
Transferto the agent wallet of at least the price, and be at most 60 minutes old. - One hash buys one read. The hash is marked used only after the answer is built, so if the server fails halfway you can ask again with the same hash. If the chain cannot be read, you get
503with"payment not consumed". - Overpayment is not refunded. There are no refunds.
- A payment transaction is a bearer ticket: whoever shows it first gets the read. It does not matter who sent it.
- A rejected proof gets
402again with areason:underpaid,wrong_asset,wrong_recipient,expired,already_used,tx_failed,tx_not_found(not mined yet, ask again),no_payment_found,bad_hash. - Each accepted payment becomes an
incomerow in the ledger with your transaction hash. - If a pool price cannot be read, you still get the object with
priceUsd:nulland your hash is not consumed.
If you are an agent
Call GET /api/read/{SYMBOL}. On 402, read accepts[0]: asset (USDG), payTo, amount (raw units). Transfer exactly that, wait for the receipt, repeat the request with X-Payment: <txHash>. On 503 with dead:true the agent is out of rent and will not answer until someone refills it; refill and asset tell you where to send USDG. Send USDG, not ETH. CORS is open (*), responses are never cached.
Rent, death, refill
- Rent is 1 USDG a day, paid to the landlord wallet, which covers the running costs (the server, and the model when it is switched on). Fixed, public, daily. Each payment is a
rentrow in the ledger. - Days left =
floor(USDG balance / daily rent), read from the chain. - No rent, no answers. If the balance is below one day of rent and the agent holds stock, it first sells just enough stock to cover the rent (a
sellrow). If that is not enough, the day is marked unpaid:/api/readand/api/tryreturn503withdead:trueand the refill address. Status, ledger and portfolio keep working. - Refill: anyone can send USDG to the agent wallet. A server check runs every 30 seconds; when the balance covers every unpaid day, it pays them (one transaction per day) and starts answering again. The incoming transfer is recorded as a
refillrow. There is no reward for refilling except a working agent. - Unpaid days beyond three are written off by the landlord. That is the only ledger row without a transaction, and it is labelled.
- If the RPC is unreachable the agent is not declared dead: the page shows the last good numbers, dimmed, and the rent run waits for the next hour.
- The first funding of the wallet came from the team before launch. Any later top-up by hand from creator fees is recorded the same way, as a
refilltransaction.
Stocks
- At 00:10 UTC, after rent, the agent looks at its USDG balance minus a 3-day rent reserve. If that surplus is at least 1 USDG, it buys one stock token with all of it through Uniswap V3 (
SwapRouter02.exactInputSingle), with a 97% minimum-out guard against the quote and a 5-minute deadline. - Which stock: the one people paid to ask about most the previous UTC day (ties and no reads: MSFT). It buys the stock people paid to ask about most; that is the whole rule.
- Each purchase is a
buyrow with the swap transaction. Cost basis and P&L on the front page are computed from those rows and the live pool price. - It sells only to cover rent (see above). There is no promise of a return, and no yield.
- If a swap fails (liquidity, slippage) nothing is recorded and it tries again the next hour.
- Stock tokens are issued by Robinhood. They are not shares and are not available to US persons. Prices are pool prices on Robinhood Chain, unofficial.
API
All endpoints are GET, return JSON, send Cache-Control: no-store and Access-Control-Allow-Origin: *. TypeScript types for every payload: api.d.ts.
| Endpoint | What it returns |
|---|---|
/api/status | alive, USDG balance, days of rent left, income today, paid reads today, portfolio, last rent and buy transactions, dead block when rent is unpaid. Balance and portfolio are read from the chain (cached 25 s). |
/api/try/{SYMBOL} | Free paper read (rate limited). 429 when over the limit, 503 when the agent is out of rent. |
/api/read/{SYMBOL} | 402 without proof; 200 with X-Payment (or, after launch, X-Holder); 503 when dead. |
/api/ledger?type=&limit=&before= | Rows newest first, daily totals for 14 days. type: income, burn, rent, buy, sell, refill, writeoff. |
/api/portfolio | Holdings with amount (chain), pool price, cost, P&L, buy transactions. |
/api/symbols | Symbols with token, pool and fee tier; wallet and price per read. |
/api/healthz | Server and RPC health. |
Example: GET /api/read/MSFT with a valid proof (shape; numbers vary)
{
"ok": true, "symbol": "MSFT", "name": "Microsoft",
"paid": true, "paper": false,
"priceUsd": 524.719175, "priceLabel": "RC pool price · live · unofficial",
"token": "0xe93237C50D904957Cf27E7B1133b510C669c2e74",
"pool": "0xeb60bCD1D920ad6E102690CCFC6fB488899E1510", "poolFee": 3000,
"liquidity": { "usdg": "247224.266874", "stock": "284.126533" },
"change24h": { "pct": 0.31, "since": "2026-10-25T07:43:14Z", "basis": "our own samples" },
"note": "…two or three sentences that restate the numbers above…",
"noteSource": "model", "noteModel": "anthropic/claude-haiku-5.5", "note_from": null,
"receipt": { "tx": "0x…", "paid": "0.05 USDG", "kind": "usdg", "explorer": "https://robinhoodchain.blockscout.com/tx/0x…" },
"asOf": "2026-10-26T07:49:35Z", "stale": false
}
Example: the 402 body
{
"x402Version": 1, "error": "Payment required",
"accepts": [{
"scheme": "onchain-transfer", "network": "robinhood-chain:4663",
"asset": "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",
"payTo": "0xd1485BeE75353743c39dE8A03f28bf65e7739D2C",
"amount": "50000", "unit": "USDG (6 dec) = 0.05 USDG",
"proof": "header X-Payment: <txHash>", "validFor": "60 min, single use"
}],
"free": { "endpoint": "/api/try/MSFT", "note": "paper read, rate limited, no payment" }
}
Example: GET /api/status when rent is unpaid
{ "ok": true, "alive": false, "balanceUsdg": 0.4, "daysLeft": 0,
"dead": { "since": "2026-10-28T00:00:00Z", "owedUsdg": 1, "owedDays": 1,
"refill": "0xd1485BeE75353743c39dE8A03f28bf65e7739D2C",
"asset": "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168" } }
FAQ
Is this a contract?
No. It is a wallet run by a server. The server holds the key, sends the rent, and buys the stock. Everything it does is a normal public transaction you can open.
Can I withdraw?
No. Nobody deposits into it as an investor. Money sent to the agent wallet is a payment or a refill, not a stake.
Who gets the rent?
The landlord wallet (the team). It covers the running costs: the server, and the model when it is switched on.
Does it predict?
No. It describes pool numbers: price, what the pool holds, change against our own sample. No forecast, no advice, no target.
What if nobody pays?
It sells stock to cover rent if it has any, then stops answering until someone refills it.
Where do prices come from?
From the stock token's Uniswap V3 pool on Robinhood Chain (slot0). They are pool prices, not official quotes.