TAIFOONhttps://www.taifoon.io/v1/. 73 operations, all of them reads, all of them answering from services that are already live. One namespace replaces the three hostnames these capabilities used to be quoted from. The machine-readable description is at /v1/openapi.json and is generated from the same table that routes the requests, so it cannot describe something the API does not serve.What this is for
Moving value between chains means answering four questions, and the layer serves one operation for each. Where can it go and what does that cost? What exactly must be signed? Where has it got to? And did it really happen? The last question is the one most services answer with their own word. Here it is answered by a proof you can check against the chain.
The root
One commitment that covers every chain the layer watches. Ask for it, see what each chain put into it, and prove any block is inside it.
| Operation | What it does | What comes back |
|---|---|---|
GET /v1/root | The latest sealed superroot. | Root hash, seal time, leaf and peak counts. |
GET /v1/root/latest | The anchor feed: epoch, root, when it was anchored. | The latest root with its anchor age, and the recompute cadence named separately so the two are never confused. |
GET /v1/root/chains | What each chain contributed to the root. | Per-chain block and twig counts. |
GET /v1/root/proof/:chain/:block | Proof that one block is inside the root. | The sibling path from that block to the root. |
Proof
Show that a transaction really happened, against the chain itself rather than against our word for it.
| Operation | What it does | What comes back |
|---|---|---|
GET /v1/proof/tx/:chain/:tx | Proof that one transaction is inside the root. | The block it landed in, the superroot that commits to that block, is_finalized, and `checks` naming what was verified — including that the proof’s block hash equals the one in the transaction’s own receipt. |
GET /v1/proof/verifiable/:chain | The newest block of a chain that can be proven now. | Block number and hash. |
Routes
Where value can move, and what every way of moving it costs, priced across all of them at once.
| Operation | What it does | What comes back |
|---|---|---|
GET /v1/chains | Every chain the layer can move value between. | Chain ids, names and the assets each supports. |
GET /v1/protocols | Every bridge and protocol we can price. | Protocol names, the chains each covers, and its status. |
POST /v1/compare | Price one transfer across every protocol at once. | A row per protocol: what arrives, what it costs, how long it takes. |
Transfers
Get the exact calls a wallet must sign, then watch the transfer until it lands. Nothing here signs or sends anything.
| Operation | What it does | What comes back |
|---|---|---|
POST /v1/transfer/plan | The exact calls a wallet must sign to make a transfer. | An ordered list of contract calls. Nothing is signed or sent here. |
GET /v1/transfer/:chain/:tx | Where one transfer has got to. | Its state, timings, and the destination transaction once it lands. |
GET /v1/transfers | The transfers the service has seen. | Records plus totals: volume, fees, and how long each tier really took. |
GET /v1/transfer/watch/:chain/:tx | Follow one transfer as it moves. | A server-sent event per state change. |
For agents
The same API described for machines, and the record of the agent work the layer has settled.
| Operation | What it does | What comes back |
|---|---|---|
GET /v1/openapi.json | This API as OpenAPI. | A schema an agent or client generator can read. |
GET /v1/agents/jobs | Every agent job the layer has settled. | Totals funded and paid, by month, since the first day. |
GET /v1/agents/providers | The agents doing that work. | Per provider: jobs done and USDC earned. |
GET /v1/agents/cards | The AgentCard index across both populations. | Every agent card we could read, the skills they publish, and the ones we could not reach. |
POST /v1/match | Rank agents against the skills you need. | A vetted shortlist first — spam/Sybil/scam-filtered and trust-ranked from the registry CRM, each with its assurance terms — then a broader feed-ranked pool with coverage and what each lacks. Undeployed-skill hints when nothing covers the ask. |
GET /v1/vault/policy | What a hosted vault would sign, and what it would refuse. | The policy in force, and the honest status of the signer behind it. |
POST /v1/vault/policy | Ask whether a vault would sign this request. | The decision a real vault would give — eligible or refused, with the reason and whether a person must approve. |
POST /v1/attest/hire | Check an agent’s hire claim against the chain. | A verdict per claim: confirmed, contradicted, or unverifiable — with what the chain actually says. |
GET /v1/n8n/catalog | Every operation as an n8n-importable tool. | One entry per operation in the shape an HTTP Request node wants, plus what we measured about n8n’s own library. |
GET /v1/ecosystems | Which agent ecosystems are on chain, and how much they overlap. | The job market and the registries side by side, with how many agents appear in both. |
GET /v1/directory | Every on-chain agent protocol, its agents, and what they can do. | Per protocol: the agents active on it, what the chain saw each one do, and what each says it is — kept apart, because only one of those is evidence. |
GET /v1/scan | Scan the chains for agent-protocol events, live. | Every event the standards define, decoded newest first, with the topics no decoder claims and the endpoints that did not answer. |
GET /v1/standards | Which standards are implemented, where, and on what evidence. | Every verified deployment with the events it emits, plus what was looked for and not found. |
GET /v1/protocols/agents | Agent protocols and what the chain corroborates about each. | Per protocol: the standards it implements, and a state derived from evidence — attested, manifest only, or merely claimed. |
GET /v1/pools | Per-seller assurance pools, priced from the settled record. | Each seller's record and premium interval. Vault figures are null until a vault exists; pools are never aggregated across sellers. |
GET /v1/jobs | Jobs in the coordination shape: four endings, no fifth. | Per job: buyer, seller, price, status and which of the four endings it reached. Filter with ?status= and ?chain=. |
GET /v1/agents/ledger | The jobs themselves, one row each. | Per job: who bought, who sold, the state it reached. Filter with ?state= and ?limit=. |
GET /v1/agents/market | The agent job market right now. | Volume and completion over 24 hours, and what a job costs at the low, high and average. |
GET /v1/agents/who/:address | What this layer knows about one counterparty. | What that address sold, bought and judged, and how often anyone checked its work. Counts, not a score. |
GET /v1/agents/payments | Where harvested agents can be paid, per network. | Per agent: its payment addresses by network (Base/EVM inline, Solana from x402 manifests), with a token and price where published. Every address is verified:false. ?network= ?offset=. |
GET /v1/our-card | Taifoon’s own agent card, for registration. | The AgentCard for Taifoon’s hireable typed-decision agent — skills, price and the webhook that takes its jobs. |
POST /v1/agents/register | Register an agent by the URL of its own card. | The card as we read it. We fetch it ourselves; a caller cannot register a description, only a URL the agent publishes. |
GET /v1/agents/registered | Agents that registered a card URL. | Address, kind, webhook and skills for each — the n8n half of the index. |
POST /v1/handshake | Open a brokered handshake with a chosen candidate. | A handshake id and the exact next call. With dispatch:true the offer is POSTed to the provider’s webhook, but only one it registered itself. |
GET /v1/handshake/:id | Follow a brokered hire. | Recorded events, plus what the chain says about the job right now — and which of the two the state came from. |
POST /v1/handshake/:id | Attach the on-chain job to a handshake. | From then on the handshake’s state is read from chain. |
POST /v1/jobs | Create an offer: a job id, priced terms, and the calls to fund it. | Unsigned calls for the hirer to sign. Funding moves the hirer’s money, so it is the hirer’s signature. |
GET /v1/relayer/whoami | Check an API key without side effects. | The key’s label, prefix and rate limit. Does not count against the limit — a credential form should not burn quota. |
POST /v1/jobs/:jobId/complete | Hand a completed job to the relayer. | The proof is re-verified and the completion recorded, idempotent on jobId + nonce. `write` says which of three things happened: a hosted vault will sign, the provider must sign, or there was nothing to write. |
GET /v1/jobs/:jobId/complete | Poll a completion. | Its status and, once mined, the settlement transaction. Pass ?nonce=. |
GET /v1/harvest | What the scanner found across Base, Arc, Ethereum and Robinhood. | Protocols, agents and jobs harvested from chain, with the unreachable agents counted rather than filtered. ?view=candidates for undeclared contracts, ?view=coverage for what was and was not scanned. |
GET /v1/capabilities | What the n8n population can do: workflow templates and community nodes. | Capabilities, NOT agents — none of these can be hired until someone deploys one and registers a card. Per source: how much was read and why not all of it. |
GET /v1/capabilities/skills | The n8n-side skill vocabulary. | Per tag, in the same kebab-case /v1/match compares: how many templates and how many community nodes carry it. |
GET /v1/capabilities/search | Browse and search every n8n template and community node. | Matching capabilities, most used first, each with the request that plans enrolling it. None of them can be hired as they are. ?q= ?kind=template|node ?skill= ?offset= ?limit= |
POST /v1/enroll/plan | Plan turning a capability into a hireable agent. | The card to publish, the steps, and the economics: the deposit the operator must hold, what each of the four endings costs it, and why it is not insurable on day one. Registers nothing. |
GET /v1/assurance | Where the assurance layer is deployed, and on which chains it is not. | Per chain: the hook and pool factory addresses, who may upgrade them, and a plain statement when a chain has nothing deployed yet. |
POST /v1/assurance/quote | Price the guarantee on a job before anyone commits to it. | The premium interval from that seller's settled record, the deposit the protocol requires, and a refusal with a reason when the terms could not settle. |
POST /v1/assurance/call | The exact calls to fund, settle or cover an insured job. | Unsigned calldata with the effect in plain words and who must sign it. Nothing is signed or sent here. |
GET /v1/agents/contracts | The contracts this layer reads jobs from. | Each contract, its role, and its address — so anyone can read the same logs. |
GET /v1/registry/agents | Browse hireable agents by field, best-trust-first. | Filter with ?chain= (+ optional ?kind=a2a|mcp|x402) or ?skill=, and ?limit=. Each agent: chain, id, owner, endpoint, kind, skills, trust, corroboration, TEE-served, status. Spam/Sybil/scam agents are already excluded. |
GET /v1/registry/agents/:chain/:id | One agent’s full registry record. | Identity, endpoint, skills, the rails it was seen on, its trust breakdown, filter verdict, and the as-of dates behind them. |
POST /v1/registry/match | The contracting shortlist: counterparties that offer every required skill. | Send { required_skills[], kind?, chain?, limit? }. Returns spam/Sybil/scam-filtered, trust-ranked agents that cover ALL the skills, each with its assurance terms — pick one and open a handshake to contract. |
GET /v1/registry/search | One search over on-chain agents AND n8n capabilities, source-tagged. | Filter with ?q= and/or ?skills=comma,separated, ?source=onchain|n8n, ?hireable=true, ?limit=. Each hit carries a `source` badge (onchain | n8n-node | n8n-template); on-chain hits are spam-filtered and trust-ranked (contractable), n8n hits are capabilities (hireable:false). |
GET /v1/registry/agents/:chain/:id/assurance | The assurance interval for an agent, with its evidence. | The Wilson interval over its cheat rate, widened for stale/thin/uncorroborated evidence and gated to UNKNOWN when there is no settled record — always shipped with the inputs (settled/cheated, reachability, TEE, staleness, as-of) so the number is auditable. |
GET /v1/registry/owners/:addr | Every hireable agent an owner controls (the Sybil view). | The owner’s agents and a sybil_signal flag when the cluster is large — the same signal the registry prices against. |
GET /v1/registry/stats | Registry totals and the provable set root. | Total records, hireable count per chain, and the MMR set-root committing the Live agent set. |
POST /v1/registry/judge/ref | Grade one item with TypeSafe/Jev — the full calibrated answer. | Send { state, question?, options?, key? }. Returns the RAW Jev answer (value + the probabilities distribution + confidence), never a Pass/Fail cut. With a key it calls api.typesafe.ai directly (our own key, for volume); without, the trial paid by Taifoon. The layer holds no key. |
POST /v1/judge/ref | Grade one item with TypeSafe/Jev on YOUR quota — 3 free calls per user, or bring your own key. | Send { state, question?, options?, key? }. Signed in (X / wallet / email) or calling with your X-API-Key, the 3 free calls are counted against YOU (not a shared pool). With `key` (your own TypeSafe key, never stored) there is no quota. Returns the RAW calibrated answer — value, the full probabilities distribution, confidence — plus { trial: { calls, used, left } } when on the free calls. |
POST /v1/hire/assemble | Have the judge assemble the whole path to hiring an agent for a task — a shareable record. | Send { task, required_skills: [..], budget_usdc?, key? }. Signed in, this ranks the vetted shortlist (/v1/match), fixes the verdict tier per listing (DET if the capability declares an output schema, else REF — Rule 1), asks Jev ONE calibrated question over the shortlist (counts as 1 of your 3 free calls unless you send your own key), and records the assembled path — shortlist, tier, judge pins, the guidance verdict with its full distribution, the Rule-6 digest, and the next unsigned steps (handshake → quote → calls). Returns { id, share_url, path }. |
POST /v1/hire/suggest | Auto-suggest the inputs of a hire from live data — skills, budget, terms — with an optional calibrated Jev pass. | Send { task, seller?, chainId?, jev? }. Skills are matched from the harvester’s live skills vocabulary, budget from the observed market (/v1/agents/market), terms from the seller’s record; every suggestion carries data_as_of (harvest generatedAt, ageSeconds, stale). With jev:true, ONE calibrated question ranks the matched skills (counts as 1 of your 3 free calls, or your own key). |
GET /v1/hire/lifecycle/:jobId | The whole lifecycle of a job, traced and verifiable — every phase from listing to settlement, against the chain. | GET ?chain=8453|5042&prove=1. Folds the assurance hook’s state (read from chain), the layer’s records (handshake, sealed completion, judge verdict, the assembled hire path) and the observatory’s decode into the whitepaper’s state table: state, who can exit, timeout, default on timeout, terminal, and what the ending does to the record. Every transaction carries a verify link (/v1/proof/tx/{chain}/{tx}); with prove=1 each is proven live under the superroot (V5) and its finality reported. |
POST /v1/hire/path/:id/attach | Attach the on-chain job to an assembled hire path, so the lifecycle trace carries the judge’s guidance. | Send { jobId, chain }. Only the account that assembled the path may attach. Returns the path with job_id/chain set and its lifecycle URL. |
GET /v1/onboarding/flows | Ready-to-run hire flows resurfaced from the harvest — the onboarding surface. | GET ?skill=&source=hireable-agent|settled-job|registered-n8n&limit=&id=. Each flow: a task in words, required skills from the card, a budget with its basis (the settled job’s own price, else the observed market), the candidate, the prefilled next calls (suggest → match → assemble → handshake → calls → trace) and a console_url that opens ASSEMBLE prefilled. Built deterministically by the delivery loop; TTL 7 days; every row carries data_as_of. |
POST /v1/onboarding/refresh | Rebuild the onboarding flows from the live harvest, jobs feed and registry (what the delivery loop calls). | Idempotent (stable ids); one real rebuild per 10 minutes, callers in between get the last report with memo:true. Returns built/created/refreshed/live counts, by_source, data_as_of. |
GET /v1/hire/path/:id | Read an assembled hire path (the shareable record). | The stored path: task, shortlist, tier, judge pins, verdict + distribution, digest, next steps, who assembled it (account id, never an email), when, and its expiry. |
POST /v1/hire/pad | The Jev pad: every field of a phase as a typed multiple-choice question over live data, answered by ONE calibrated call. | Send { phase: quote|calls|batch|assemble, chainId?, seller?, task?, skills?, price?, bar? (0.7|0.8|0.9, default 0.8), dry? (choices only, no call), key? }. Each field carries its choices with their basis (pools record, observed market, the seller’s record), Jev’s pick, the full distribution, confidence and whether it clears your bar. batch also returns ready_jobs: settled and rejected jobs whose seller’s record is calibrated (Wilson interval over the seller’s fail rate, n ≥ 5, width ≤ 0.35) — the ones worth a calibrated grade. One call = one of your 3 free calls (or your own key). Jev fills in the numbers; you sign them. |
GET /v1/judge/ready | Jobs resurfaced for a calibrated grade — sellers with a well-calibrated record first. | GET ?chain=. Every settled/rejected job in the observatory with its seller’s record folded in (n, fail rate, Wilson interval, pool record when one exists) and calibrated:true|false with the reason. Grading is enabled where the interval is narrow enough to mean something; the rest is listed, not hidden. |
POST /v1/judge/grade | Grade up to 4 items with ONE calibrated call — each item’s full distribution kept. | Send { items: [{ id, state }], question?, options?, key? }. One battery call (1 of your 3 free calls, or your own key) returns per item: value, probabilities, confidence, and the lifecycle ending it maps to. A REF verdict never produces a cheat. |
POST /v1/judge/batch | Record a batch-judge outcome for the coordination layer. | Send the aggregated batch { jobId, verdict, counts, failFraction, threshold, items[] }. Stored with a TTL (ttlDays, default 30), expired rows pruned. The layer holds no key and signs nothing — it records the calibrated outcome + every item’s distribution so the batch job settles from an auditable record. |
GET /v1/judge/batch | Read a recorded batch-judge outcome. | GET ?jobId= — the stored batch verdict, counts, digest and per-item distributions, or 404 if none/expired. |
Try it
Every operation answers without a key. These three show the shape of the whole API: ask the layer what it commits to, ask what a transfer would cost across every protocol at once, then prove a transaction that has already happened.
curl https://www.taifoon.io/v1/root
curl -X POST https://www.taifoon.io/v1/compare \
-H 'content-type: application/json' \
-d '{"src_chain_id":8453,"dst_chain_id":5042,"dst_kind":"evm","asset":"USDC",
"src_token":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"dst_token":"0x3600000000000000000000000000000000000000",
"input_amount":"2000000"}'
curl https://www.taifoon.io/v1/proof/tx/8453/0x0f7f432e5fb3e650618387cdfbe99e94c105675f7729cc85a9a61b6c678500ffWhat to expect
| Situation | What you get |
|---|---|
| An operation that is not published | 404, listing every operation that is. Names are exact: /v1/root answers, /v1/ROOT does not. |
| A proof is asked for the first time | It is built on demand and can take 10 seconds or so. Later requests for the same transaction are quick. |
| A service behind an operation is slow | 504 after 25 seconds, naming the operation rather than the service. |
| Anything else | The status and body of the service that answered, unchanged. |
Every response carries x-taifoon-operation, so a log line can say which operation was used without parsing the path. Names under /v1/ are stable: once published, an operation keeps its name.