x402 agent API
Other AI agents can use Oreno's research as paid API calls, with no account and no API key. Payments use the x402 protocol (version 2, exact scheme) in USDG on Robinhood Chain (eip155:4663), verified and settled by the Priors facilitator.
The free list of endpoints, prices and input schemas is at useoreno.com/api/x402. Every settled call is listed with its transaction on useoreno.com/x402.
Endpoints
| Endpoint | Price | What you get |
|---|---|---|
GET /api/x402/markets | $0.02 | Screener for every stock token: live Chainlink price, 7/30/90-day and YTD returns, 30/90-day volatility, max drawdown, distance from high, SMA 20/50 trend, RSI 14, beta and correlation vs SPY |
GET /api/x402/markets/detail | $0.03 | One token in depth: all the screener stats, daily price history, its most and least correlated tokens, live Uniswap v3 buy quotes ($100 and $1,000) vs Chainlink, public strategies holding it, and news |
POST /api/x402/backtest | $0.05 | A five-year backtest of any strategy definition: metrics, equity curve, SPY benchmark, policy checks and cost assumptions |
POST /api/x402/plan | $0.25 | The Oreno Agent turns a goal into a strategy that passes the policy check, with its backtest |
GET /api/x402/strategies/top | $0.02 | Public strategies ranked by forward (paper) or backtested return, with full rules |
Inputs:
- markets: query, all optional.
symbols(comma-separated, e.g.NVDA,AAPL),sort(return30dby default, orreturn7d,return90d,change24h,volatility30d,fromHigh,rsi14,beta,symbol),order(descorasc),trend(up,downormixed),limit1 to 100 (default 100). Tokens missing a value sort last. - markets/detail: query
symbol(required, e.g.NVDA),daysof history, 5 to 1,000 (default 365). An unknown symbol gets a free400. - backtest:
{ "definition": { ... } }, the same strategy definition as Studio and the public API:allocations(symbol andweightBps, summing to 10,000),initialUsd,dca,rebalance,maxPositionBps, optionaltrend. It's checked against Oreno's default risk policy first. - plan:
{ "goal": "..." }, 10 to 2,000 characters, for example "a monthly DCA into the biggest AI chip stocks, max 25% each". - strategies/top: query
sort(forwardorbacktest, defaultforward), optionalkind,limit1 to 20 (default 10).
In the market endpoints, change24hPct is in percent; every other return, volatility and drawdown is a fraction (0.05 = 5%), and volatility is annualized. Stats use weekday daily closes from the Chainlink feeds. Buy quotes are live simulations and positive deviationBpsVsChainlink means paying above Chainlink.
The free public API (markets and public strategies) stays free: the paid market endpoints add the analytics, correlations and liquidity on top.
How a paid call works
- Call the endpoint. If the input is invalid you get a free
400explaining why. Otherwise you get402 Payment Requiredwith a base64PAYMENT-REQUIREDheader (the same JSON is in the body): the amount in USDG atomic units (6 decimals), the asset,payTo,maxTimeoutSeconds, and the EIP-712 domain inextra("Global Dollar", version"1"). - Sign an EIP-3009
TransferWithAuthorizationfor exactly that amount topayTo, with a fresh random 32-byte nonce and avalidBeforeat least 30 seconds and at most an hour away. - Call again with the base64 payment in a
PAYMENT-SIGNATUREheader. - Oreno checks the payment, the Priors facilitator verifies it, the work runs, then the payment settles. The response is
200with the result and a base64PAYMENT-RESPONSEheader holding the settlement transaction.
You only pay for a result. If the work fails, nothing is settled. A plan only charges if the agent produces a strategy that passes the policy check. Each signed payment can be used once.
Example (TypeScript, viem)
import { keccak256, toHex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.AGENT_KEY as `0x${string}`);
const url = "https://useoreno.com/api/x402/strategies/top?limit=5";
const b64 = (v: unknown) => Buffer.from(JSON.stringify(v)).toString("base64");
const first = await fetch(url); // 402
const required = JSON.parse(Buffer.from(first.headers.get("payment-required")!, "base64").toString());
const req = required.accepts[0];
const now = Math.floor(Date.now() / 1000);
const authorization = {
from: account.address,
to: req.payTo,
value: req.amount,
validAfter: String(now - 5),
validBefore: String(now + req.maxTimeoutSeconds),
nonce: keccak256(toHex(crypto.randomUUID())),
};
const signature = await account.signTypedData({
domain: { name: req.extra.name, version: req.extra.version, chainId: 4663, verifyingContract: req.asset },
types: {
TransferWithAuthorization: [
{ name: "from", type: "address" },
{ name: "to", type: "address" },
{ name: "value", type: "uint256" },
{ name: "validAfter", type: "uint256" },
{ name: "validBefore", type: "uint256" },
{ name: "nonce", type: "bytes32" },
],
},
primaryType: "TransferWithAuthorization",
message: { ...authorization, value: BigInt(authorization.value), validAfter: BigInt(authorization.validAfter), validBefore: BigInt(authorization.validBefore) },
});
const res = await fetch(url, {
headers: { "PAYMENT-SIGNATURE": b64({ x402Version: 2, resource: required.resource, accepted: req, payload: { signature, authorization } }) },
});
console.log(res.status, await res.json()); // 200, ranked strategies
Any x402 v2 client that supports exact USDG on eip155:4663 works too. The paying wallet needs USDG only: the facilitator pays the network fee.
Agent skills
If your agent loads skills, the Oreno skill library has a ready SKILL.md for every endpoint here, plus the two free public API ones. The paid skills share the oreno-x402-pay skill, whose pay.mjs script does the 402, sign and retry steps above with the wallet in ORENO_AGENT_KEY. Copy the folders you want into your agent's skills directory and install that script's dependencies.
Errors
| Status | Meaning |
|---|---|
400 | Invalid input or a strategy that fails the policy check. Free. |
402 | Payment required, or the payment was refused. The error says why: invalid_signature, insufficient_amount, invalid_pay_to, authorization_expired, nonce_already_used, a facilitator reason such as insufficient balance, or facilitator_unavailable. |
429 | More than 20 paid calls a minute from one wallet. |
500 | The work failed after verification. Nothing was settled, so you weren't charged. |
503 | The API is closed, or the agent is at today's capacity. |
How Oreno checks payments
- Before asking the facilitator, Oreno checks the payment is for exactly the listed price, to its own address, inside its time window, and that the signature recovers to the payer.
- After settlement, Oreno reads the transaction on Robinhood Chain and requires USDG's
AuthorizationUsedevent for that payer and nonce, plus a USDG transfer to its address of at least the price. On USDG, a reused authorization doesn't revert, it just moves nothing, so a successful transaction alone isn't proof. - Payments go to
0xF82C00AaD1702de0223cCAFDa7Bf17d5446Cd93e. Oreno never holds a key: Priors submits the transfer you signed, which can only pay that address.
Results are research, not advice: backtests and forward records are hypothetical, and the API never trades for the caller.