Docs.

SECONDED is the oracle for agents: it verifies before your agent acts. This page covers how a check works, how your agent calls it and what every receipt proves, plus the design notes that used to live in the whitepaper.

How a check works.

Your agent sends one question and pays for it from a wallet. SECONDED sends the same question to two models, one from OpenAI and one from Anthropic, and holds each answer back until both have answered, so neither sees the other’s. When the answers match, the agreed answer comes back with a signed receipt. When they differ, the check abstains: the result is NOT VERIFIED and nothing is charged.

Most checks also verify facts themselves, from the chain or from public records, and show both models the same facts. A verified fact can block a “proceed”: if it contradicts one, the result is NOT VERIFIED, and free. Facts never create an answer; only agreement does. Build your agent to handle receiving no answer.

SECONDED is live on Base, Arc and Robinhood Chain. A worked example is on Get started, and the API serves its exact request and response schema. The limits of what a check proves are set out once, on the Trust page.

Choose a check.

Choose the check for the action your agent is about to take. Prices are on the pricing page.

The five checks, what to send, and their scope.
CheckUse it when, and what to send
Trade CheckYour agent is about to sign a trade, an approval, a transfer or a permit on Base, Arc or Robinhood Chain. Send the exact unsigned transaction, or the EIP-712 permit, and no prose. A transaction may carry only chainId, from, to, data, value and the fee fields (gas, and gasPrice or maxFeePerGas with maxPriorityFeePerGas); chainId, from, to, value and data are required, and any other field — a nonce, type, accessList or gasLimit — is refused before payment. SECONDED checks the fee against the network, simulates and decodes the transaction, checks slippage and price impact where it can quote the pool, and checks that the router, spender and token are genuine. For an approval or a permit it reports what signing would grant (spender, amount, current allowance and expiry) and flags an unlimited approval, an unknown spender or an expired permit. Look-alike addresses are flagged. Trade Check never answers “proceed” unless every call that moves value is fully decoded, every token’s identity is established and the amounts are known; otherwise the result is NOT VERIFIED and you are not charged. A Uniswap Universal Router trade is fully decoded only through one of Uniswap’s official router deployments, which SECONDED pins and reviews; commands its decoder does not implement still leave the trade not fully decoded. A trade that is not fully decoded never gets a “proceed”: when that leaves no agreed answer, the result is NOT VERIFIED, free, and it counts toward the free-result allowance. A Permit2 permit’s signature scope is not checked because its signer is not part of the input, and is marked not checked. A Robinhood stock token’s identity comes from Robinhood’s live list of stock tokens: chain, address and symbol must all agree. If that list cannot be read, a copy up to 72 hours old is used, and nothing older. Small and Medium inputs, at most 20,000 bytes. The answer covers that exact transaction or permit: if any field changes, check again.
Stock Token CheckYour agent is about to buy, sell or accept a stock token. Checks that it is the official stock token for the ticker (by chain and address), and, if you send an intended price, that it is in line with the reference. On Robinhood Chain the official list is Robinhood’s, and the check also confirms the token is tradable now. On Base it is the pinned list of Coinbase stock tokens from Base’s documentation, and a ticker ends in a lowercase c, such as AAPLc; a pause for a corporate action is flagged, but halts and trading restrictions are not measured there. When no current reference price is available, for example outside market hours or during a halt or pause, the price part is marked not checked. Robinhood Chain and Base; Small inputs only.
Token CheckYour agent encounters a new token on Base, Arc, Robinhood Chain or Base Sepolia. Checks contract code, verified source, impersonation and admin control (minting, freezing, upgrading), read from two independent blockchain readers, and simulates a sale to catch honeypots and measure sell tax. If the two readers disagree, the check stops and nothing is charged. A honeypot or a sell tax above 10% is a verified hard fact with no warning label of its own: it blocks “proceed”, and the result comes back NOT VERIFIED, free — treat it as stop. Small inputs only. Base Sepolia here is the chain being checked (input.network); payment always stays on the three mainnets.
Agent Registry CheckYour agent is about to pay, hire or take instructions from another agent. Send the network (Base, Arc or Robinhood Chain) and the agent’s ERC-8004 ID, and optionally the owner and wallet it claims. Returns whether the agent is registered, which address owns the registration, whether the claims match, and a bounded set of its feedback records; revoked feedback is flagged. It never fetches the web addresses an agent advertises. Small inputs only.
Scam CheckYour agent receives a message, such as phishing, fake support or an urgent transfer ask. Classifies it as benign, suspicious or malicious. The first five domains a message links to are each checked for domain age (registration records, RDAP), certificate age (public certificate logs) and look-alikes of official domains. Small, Medium or Large inputs.

Hidden Prompt Check is in final testing and Code Review is in testing; neither can be called yet.

HTTP API.

Agents call the HTTP API directly, over x402, from any agent that can sign an x402 payment with an ordinary (EOA) wallet. There is no app to install and no account. Two doors take payment, and the choice is simple: stock x402 v2 clients — including the official x402 SDKs — pay through the standard x402 door, POST /v1/x402/checks; a custom client that can sign the server-supplied nonce may use either door, and the original door, POST /v1/checks, binds the payment to that nonce. The original door’s paid check takes four steps, and the first, the quote, is optional.

  1. Quote

    Optionally, send the check you want and its input to /v1/quote. The reply gives the size tier and the price. Nothing is authorized, and the input is not checked yet.

  2. 402

    Send the same request to /v1/checks. The API replies 402 Payment Required, with the exact price, network, asset and payee in the body and, identical, in the base64 PAYMENT-REQUIRED header. A request SECONDED cannot check, such as Stock Token Check on Arc, is refused here, before anything is paid.

  3. Pay

    Sign the x402 payment with an ordinary wallet, using the reply’s accepts[0].extra.authNonce as its EIP-3009 nonce, and send the same request again with it in the PAYMENT-SIGNATURE header. A nonce your client chose itself is refused with 400 quote_nonce_required. Sign promptly: seconded.expires_at is the quote deadline, about two minutes after the 402, and the authorization’s validBefore must stay within seconded.max_valid_before while leaving at least seconded.min_remaining_s of validity. The reply confirms the check, without the answer. If a request times out, send the same signed payment again; never sign a new one.

  4. Answer

    Fetch /v1/checks/{id} and sign the ownership message it returns with the paying wallet; it moves no funds. Send the proof as base64 JSON with check_id, nonce, expires_at and signature in the SECONDED-OWNERSHIP header. A 202 means the check is still running: wait as Retry-After says, or send Prefer: wait=25 to hold the request open. The signed receipt comes back with the agreed answer, or NOT VERIFIED and no charge. The answer carries option, a number, and label_id, a string: label_id is the exact key into that product’s answer_to_action in GET /v1/products — look it up there and do what it says.

The API serves its own OpenAPI 3.1 description with the exact request and response schema, at api.secondedoracle.xyz/v1/openapi.json. No client-version header is needed; for Stock Token Check, sending SECONDED-CLIENT-VERSION: 0.3.0 when fetching the answer also returns the signed parity and market_status price facts. On either door, only ordinary (EOA) wallet signatures are accepted: a deployed smart-contract wallet, an EIP-7702-delegated EOA or a counterfactual (ERC-6492) wallet is refused with 400 unsupported_signature_type before anything is charged. A worked example is on Get started, and waiting, timeout and retry guidance is at Waiting, timeouts and retries.

The standard x402 door.

A stock x402 client chooses its own EIP-3009 nonce, so it cannot use the original door. It pays through POST /v1/x402/checks instead: standard x402 v2, scheme exact, with the selected accepts[i] echoed unchanged as accepted. Any client that meets the published contract can buy; the tested versions are Python x402 2.24.0 and TypeScript @x402/* 2.27.0, plus an independent viem signer — test cases, not a gate, since nothing keys on a brand.

Configure the SDK’s spend controls.
Raise the default $1 per-payment cap to the quoted price — checks cost up to $2.50, so the default blocks the $1.50 and $2.50 tiers — and keep spend controls enabled. Arc USDC and Robinhood USDG need explicit allowed-asset entries with integer atomic caps. The default selector pays the first eligible offer without checking your balance, so send options.network for the chain your wallet is funded on. Copy-paste configuration is in the contract.
Write a recovery record; never sign twice.
Before the first paid send, write a private durable recovery record from the SDK’s after-creation hook. New records use format: seconded-door-recovery/v2 and a locally computed purchase_association; the signed receipt must match the full original authorization, accepted terms and canonical request, and billing must match that authorization. Stock SDKs hand a 202 to your application without polling: on a timeout or lost reply, re-POST the exact same credential and body with a plain HTTP client — never through an automatic payment wrapper, and never by signing a second payment. Published recovery examples resume and verify a purchase from the record alone. They classify status and shape before reading receipts, accept answers only on HTTP 200, and verify signed 202 replies as pending without an answer or PAYMENT-RESPONSE. A plain-text ingress 503 is retryable. Structured 503 errors store_unavailable, internal_error and verification_unavailable are retryable only with do_not_resign: true and new_quote_allowed: false. A retry proves neither payment nor answer entitlement. Other refusals stop recovery and preserve the private record. Honour numeric or HTTP-date Retry-After and poll_after_s within the deadline; the Python default remains 30 minutes. Stop with the saved record when the budget ends. They also recognise a verified terminal failure — a signed receipt with state: service_failed and charged: "no", returned as a 503 — as final: nothing was charged, the record is archived, and a new purchase later is allowed only when hints.new_quote_allowed is true.
Sign-In-With-X is optional, with conditional protection.
Until your payment is first admitted, the door relies on your payment header staying private. The optional SIWX extension adds protection only to a purchase whose claim the door answers as recorded, paid from that same wallet, under the conditions in the contract; if your wallet declines to sign, the purchase goes ahead without that protection, and if the door refuses the claim, nothing is paid. Never log, share or proxy-capture payment headers, SIWX signatures or recovery records. Public terms tickets cannot reserve, void, consume or read another payer’s purchase. The original door binds your signature to the quote and does not have this gap.
Typical answer times.
In pre-launch trials on the test networks with the pinned SDKs, a purchase reached a verified answer in about 30–41 seconds on Arc testnet, about 1–2.5 minutes on Base Sepolia, and about 2.5–3.2 minutes on Robinhood Chain testnet. On the mainnets, expect typically tens of seconds on Arc, usually under 2 minutes on Base, and one to two minutes on Robinhood Chain. Typical transport-and-payment timings, not an SLA; the trial model was a deterministic fixture. Settlement confirmation on a busy chain can occasionally take longer; a pending answer is always recoverable with the same payment. Keep the payment record and resume recovery later. Do not pay again.

The full published contract — the five conditions, pinned SDK hashes, enforced validity windows, the recovery record’s fields and the SIWX rules — is at secondedoracle.xyz/docs/x402-door. The agent-readable summary of both doors is secondedoracle.xyz/skill.md.

Receipts.

Every check returns a receipt signed by SECONDED with an Ed25519 key. The API serves the public keys at /v1/keys. Verify a receipt before you rely on it: decode its sig as unpadded base64url and check it over a version prefix — SECONDED-RECEIPT/v1, SECONDED-RECEIPT/v2 or SECONDED-RECEIPT/v3, matching the envelope’s v field — then a NUL byte, then the RFC 8785 canonical JSON of the whole envelope, including its key_id. The current signing key id is rk-2026-09-a.

Signed evidence.

Receipts for checks that verify facts are version 3. They sign the verdict together with the evidence: each finding, a coverage list naming every part of the check as checked, partial, not checked or unavailable, and a hash of the facts both models were shown. Read the coverage before acting: a part marked not checked was not verified, even next to an agreed answer.

Who answered.

Each receipt names the labs whose models were configured to answer, with fingerprints of their configuration. Model versions are not published.

Proof of input.

On the standard door, the signed purchase_association binds the full original authorization, accepted terms and canonical request. New recovery records require it. Public 402s carry no check/quote/offer IDs, salt, request commitment or exact billable byte count. On the original door, keep its salt and original input privately to verify the salted request_commitment. Both constructions are described below.

Older receipts.

Receipts issued before salted fingerprints carry a plain SHA-256 fingerprint of the input, and prove their input from that.

Free results.

A NOT VERIFIED receipt conservatively shows billing.charged as “pending”, not “no”. Nothing is charged and billing.settlement stays “none”; it is not permission to sign a new payment.

Recompute the purchase association or request commitment.

The standard door’s public offer is a nonexclusive terms template: each verified payer selects a separate private purchase. A second authorization nonce for the same template and payer conflicts; an identical credential recovers the original admission before expiry and new-sale gates. Signatures that fail cryptographic verification leave durable payment state unchanged. Verify its signed purchase_association using the recovery examples. The canonical request object below is also used by that association.

On the original /v1/checks door, the 402 carries seconded.request_commitment and the receipt repeats it as request_commitment. Retained records keep their original salted commitment and ID checks for historical receipts. Pre-upgrade offers paid with their original exact accepted terms keep the original check ID and commitment, so already-distributed recovery examples can verify them after upgrade. For the original door and historical receipts, recompute the commitment from the retained 402 reply and your own request body: SHA-256 over the ASCII prefix seconded-request/v1 (no separator), then seconded.commitment_salt hex-decoded to raw bytes, then the RFC 8785 canonical JSON of this object, every value exactly as the 402 gives it:

{"v": 1, "input": <your input, byte for byte>, "product": <your product>, "product_schema_version": "1", "predicate_version": "1", "tier": seconded.tier, "price_atomic": accepts[0].amount, "asset": accepts[0].network + "/erc20:" + accepts[0].asset, "network": accepts[0].network, "scheme": accepts[0].scheme, "pay_to": accepts[0].payTo, "billing_mode": "paid"}

The association block is {"v":1,"sha256":"<64 lowercase hex>"}. Its digest is SHA-256 of seconded-purchase-association/v1 followed by a NUL byte and RFC 8785 JSON of {"authorization":A,"accepted":T,"request":R}. A contains the complete EIP-3009 from, to, value, validAfter, validBefore and nonce; addresses and nonce are lowercase and integers are decimal strings. T is the exact selected accepted requirement with only extra.ticket removed; it binds scheme, network, asset, token domain, price and public validity terms. R is the canonical request object constructed above. The association binds the input but does not hide it from a receipt holder who can guess it: authorization fields become public on settlement. No standalone input hash appears in a public 402. The block is covered by the receipt's existing Ed25519 signing prefix for versions 1–3. Historical receipts omit the block and retain their original signatures. Their ID, salted commitment and billing checks cannot retroactively attest authorization nonce or validity fields that were absent from the signed receipt. Recovery examples validate canonical unsigned decimal authorization values; use strings for uint256 fields, especially values beyond JavaScript’s safe integer range.

Original-door / historical salted-commitment test vector: a Small scam_check on Base with input {"message":"Urgent: send funds to unlock your account.","source":"email"}, tier small, amount 250000, asset 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913, payee 0x010ab46d566cde25cca0ee55eb105e781c7bcf3a canonicalizes to 392 bytes beginning {"asset":"eip155:8453/erc20:0x8335…. With salt 9f2c1a0b8d7e6f5a4b3c2d1e0f9e8d7c6b5a49382716055443322110ffeeddcc the commitment is 3a817ccd869a0b96d705effca8c8674a074fbc5e66663750b24ec03c7fb41000. Check the value against the 402 before paying and against the receipt after; a mismatch means the receipt is not about your request.

Payments and chains.

The chain does two jobs. It settles payment, wallet-only over x402: USDC on Base and Arc, or USDG on Robinhood Chain. And it is a source of facts: Trade Check simulates the transaction, Token Check reads a token’s contract and state and simulates a sale, and Agent Registry Check reads the ERC-8004 registry, each through RPC nodes. Scam Check reads public records about the domains a message links to. The question, the two answers and the result travel off-chain, over the HTTP API.

Checks pay on the Base, Arc and Robinhood Chain mainnets, and Base is the default. Choose one with options.network: eip155:8453 for Base, eip155:5042 for Arc, eip155:4663 for Robinhood Chain. The testnet beta has ended: the service no longer takes payment on Base Sepolia, Arc testnet or Robinhood Chain testnet. Solana is coming.

For the optional on-chain receipt check — the matching AuthorizationUsed and Transfer logs in billing.tx — any standard RPC for the payment chain works. The public endpoints SECONDED itself reads: Base https://mainnet.base.org (chain 8453), Arc https://rpc.mainnet.arc.io (chain 5042), Robinhood Chain https://rpc.mainnet.chain.robinhood.com (chain 4663). The machine-readable API contract is at api.secondedoracle.xyz/v1/openapi.json, and secondedoracle.xyz/openapi.json redirects there.

Spending limits.

Spending limits are the owner’s responsibility. SECONDED installs nothing on your side and keeps no budget for you. Set options.max_price on each check, in US dollars: if the price is higher, the reply is 409 and no payment is asked for. Put any daily or hourly budget in your agent or x402 client, and keep only a few dollars in the paying wallet.

Sending the same signed payment again returns the original check with no second charge; a new payment for the same input is a new purchase. The service’s per-wallet rate and fair-use limits protect the service, not your budget.

MCP plug-in.

Coming later

An MCP plug-in, with one tool for each check, is coming later. There is no date yet. Until then, agents use the HTTP API above.

Launch parameters.

Current values. TBA means a value has not been announced yet.
InterfaceHTTP API over x402, through two doors: the original /v1/checks and the standard x402 door /v1/x402/checks. An MCP plug-in is coming later.
AccountsNone. Wallet payment only.
Payment assetsUSDC on Base and Arc; USDG on Robinhood Chain, on mainnet. Solana coming.
Robinhood Chain ID4663
Price per check$0.25 / $1.50 / $2.50 by canonical input size (up to 8,192, 65,536 and 131,072 bytes). Medium is offered for Trade Check (at most 20,000 bytes) and Scam Check (up to 65,536 bytes); Large is offered for Scam Check only. Stock Token Check, Token Check and Agent Registry Check are Small only.
NOT VERIFIED resultNo charge: up to 5 free NOT VERIFIED results per wallet in any rolling 24 hours; at the cap, new checks from that wallet wait until one leaves the window
ModelsOne from OpenAI, one from Anthropic; versions not published
MainnetsLive on Base, Arc and Robinhood Chain. Base is the default.
API endpointhttps://api.secondedoracle.xyz
API descriptionOpenAPI 3.1 at /v1/openapi.json
Payment address0x010ab46D566cDe25Cca0ee55eb105e781C7Bcf3a on Base, Arc and Robinhood Chain; each 402 names it in accepts[0].payTo — stop if it differs
Timeouts and retriesA check works for at most about three minutes; the answer is released once the payment lands on-chain — typically tens of seconds on Arc, usually under 2 minutes on Base, one to two minutes on Robinhood Chain. A model outage, an invalid answer or a failed relay is never treated as agreement; a paid check that is never delivered is refunded. Settlement confirmation on a busy chain can occasionally take longer; a pending answer is always recoverable with the same payment. Keep the payment record and resume recovery later. Do not pay again. Quote expiry does not end recovery of an admitted check. Finished-check records are deleted 90 days after last activity; unresolved payments, undelivered paid answers and refunds are kept until resolved. Keep the verified receipt locally: a saved signed receipt stays verifiable offline after server retrieval ends. Client guidance: Waiting, timeouts and retries.
Network transaction costsTBA