Rift Documentation Audit
Rift's docs read well as a narrative but break down at the load-bearing joints: the central "verify our code" link 404s, the API reference points at a production Railway deployment URL instead of the branded host the marketing site advertises, there's no documented auth and no way to track an order after you've sent funds to it, and the four surfaces (what-is-rift, use-cases, FAQ, marketing site) disagree about what's actually supported and what the protocols are even called.
1. The verifiability link the entire trust model depends on is a 404 (critical)
Location: /security-model and /what-is-rift (GitHub link in footer/nav of every page: https://github.com/riftresearch/tee-router)
Problem: The security model's core claim is that "anyone can verify the machine is running the contract code we claim it is by comparing the attestation hash of the system image with the protocol code on our GitHub," and what-is-rift states "Rift's protocol code is 100% open source for anyone to verify, audit, or contribute to." The GitHub link rendered on every docs page, github.com/riftresearch/tee-router, returns HTTP 404 (confirmed three independent ways: WebFetch on the raw README, TinyFish fetch, and the org listing). The riftresearch org exists but contains no tee-router repository.
Consequence: The single most important claim of a TEE-based, audit-it-yourself protocol — "here is the code, check the attestation hash against it" — cannot be acted on. A developer or security researcher who clicks through to verify the attestation hits a dead page, which undermines the entire premise that trust is replaced by verifiable hardware attestation.
The fix: Point the link at the actual code. The org's protocol repo ("Rift Protocol Monorepo," Rust, Apache-2.0) appears to be the live target. Update the footer/nav link on every page, and on /security-model state exactly which repo and which file/commit the attestation hash corresponds to, so the hash-comparison step is reproducible.
2. API base URL is a production Railway deployment URL, contradicting the branded host (critical)
Location: /api/quotes/get-a-market-quote, /api/orders/create-a-market-order, /api/status/* (vs www.rift.trade)
Problem: Every documented endpoint uses base URL https://router-gateway-v3-production.up.railway.app. The official marketing/app site at www.rift.trade advertises the API as api.rift.trade/quote. The two surfaces disagree on the canonical API host: a raw Railway PaaS deployment URL vs. a branded domain.
Consequence: Integrators copy the Railway URL straight from the API reference. Raw PaaS deployment hostnames are not stable contract surfaces — they can rotate, be rate-limited differently, or change on redeploy. An integrator who hardcodes router-gateway-v3-production.up.railway.app may have working code today and a dead host after the next infra change, while the "real" branded endpoint goes undocumented.
The fix: Use api.rift.trade consistently in all reference examples, or explicitly document which host is canonical and supported. If the Railway URL is an internal artifact, it should not appear in public docs at all.
3. No authentication documented anywhere, despite a paid integrator program (critical)
Location: /api/quotes/get-a-market-quote, /api/orders/create-a-market-order
Problem: Neither endpoint documents any authentication — no API key, no Authorization header, no token exchange. The curl examples send only Content-Type: application/json. Yet the FAQ describes a referral program that pays "when an approved integrator goes live with our API," and the order body accepts an integrator field, both of which imply some notion of registered/authenticated callers.
Consequence: An "approved integrator" has no documented way to authenticate, attribute volume, or receive referral credit. A developer cannot tell whether these endpoints are open/unauthenticated by design or whether auth is silently required and simply omitted — and an agent generating an integration will produce unauthenticated requests with no way to know they're incomplete.
The fix: Document the auth model explicitly. If endpoints are public, say so. If integrators need a key, show the header, where to obtain the key, how it maps to the integrator field, and how it ties to referral attribution.
4. Takers send funds to an address with no documented way to track the order (critical)
Location: /api/orders/create-a-market-order and /api/status/*
Problem: Creating a market order returns orderId, an orderAddress (e.g. bc1q...), and status: "quoted" — implying an order lifecycle (quoted → … → settled). The flow on /use-cases is "Taker sends BTC to market order contract," and what-is-rift promises "the destination asset magically appears in your wallet." But the only endpoints filed under "status" are global health (GET /health) and execution-provider checks (GET /providers). There is no documented per-order status endpoint keyed by orderId.
Consequence: A taker (or integrator) sends real funds to orderAddress and then has no documented, programmatic way to confirm receipt, watch settlement progress, detect failure, or trigger a refund. For a cross-chain router where settlement spans Bitcoin, bridges, and an orderbook, "send funds and hope" is not a viable integration contract.
The fix: Document a GET /order/{orderId} (or equivalent) status endpoint with the full set of status enum values and their meanings (quoted, pending, settled, refunded, expired, failed, etc.), and link it from the create-order response.
5. refundToken / refundMode / refundAuthorizer are returned but never explained (significant)
Location: /api/orders/create-a-market-order
Problem: The order response includes refundToken (rgt_abcdefghijklmnopqrstuvwxyz), refundMode (evmSignature | token), and refundAuthorizer (an EVM address). The request body also accepts refundAuthorizer, refundAddress, and refundMode. Nothing in the docs explains what these are, when a refund occurs, how refundToken is redeemed, what the difference between evmSignature and token modes is, or who the refundAuthorizer must be.
Consequence: Refunds are the safety net when a cross-chain swap fails after the taker has already sent funds. Without documentation, integrators cannot implement refund handling — the exact path that matters most when something goes wrong is undefined.
The fix: Add a refunds section: explain each field, both refundMode flows end-to-end, how refundToken is presented to claim funds, and the role/constraints of refundAuthorizer.
6. No error responses documented on any endpoint (significant)
Location: /api/quotes/get-a-market-quote, /api/orders/create-a-market-order, /api/status/*
Problem: Every endpoint documents only the 200 success case. There are no 4xx/5xx examples, no error schema, and no error codes — despite required fields with strict constraints (idempotencyKey 16–128 chars with regex ^[A-Za-z0-9._:-]+$, from/to length 1–96, UUID quoteId) that will obviously reject malformed input, and despite quote expiry timestamps that imply an "expired quote" failure path.
Consequence: Developers can't build error handling (validation failures, expired quotes, unsupported routes, rate limits) without trial-and-error against a live endpoint that moves real money. Agents generating integration code will omit error handling entirely because no error shape exists to code against.
The fix: Document the error envelope (status codes, error body schema, machine-readable codes) and give concrete examples for at least: validation failure, expired/unknown quote, and unsupported route.
7. Pages disagree about supported order types, and three of four products have zero API coverage (significant)
Location: /what-is-rift vs /use-cases vs /faq vs /api/*
Problem: what-is-rift states "We currently support market orders and vault deposits/withdrawals" — only two. /use-cases says "We currently support BTC, ETH, and USDC for limit orders" and describes OTC as "currently live for BTC to cbBTC on Ethereum and Base." The FAQ also treats OTC as a live revenue source. So limit orders and OTC are described as live on some pages and omitted from the "currently support" sentence on the landing page. Meanwhile the API reference documents endpoints for none of vaults, OTC, or limit orders — only POST /quote, POST /order/market, GET /health, and GET /providers. There is no quote or order endpoint for vault deposits/withdrawals, OTC settlement, or limit orders.
Consequence: A reader cannot determine what is actually shippable today. Worse, three of the four advertised product surfaces (vaults, OTC, limit orders) have zero API documentation — a developer who reads the use-cases page and then opens the API reference to build a vault-deposit or limit-order flow finds nothing to call.
The fix: State one authoritative, dated support matrix (order type × asset × chain × live/coming-soon) and reconcile all four pages to it. Add API reference pages for any order type claimed as live, or mark them explicitly as "no public API yet."
8. llms.txt is linked in the nav of every page but 404s (significant)
Location: /llms.txt (first entry in the DOM-extracted nav on every docs page)
Problem: The docs nav links /llms.txt as its first entry, but the file returns HTTP 404 (confirmed via both WebFetch and TinyFish). /llms-full.txt and /docs/llms-full.txt likewise 404.
Consequence: AI coding agents (Claude Code, Cursor, etc.) follow the advertised llms.txt to index the docs efficiently and hit a dead file — so they fall back to scraping prose, exactly the outcome llms.txt exists to prevent. A linked-but-missing llms.txt is worse than none: it signals support that isn't there.
The fix: Either publish a real llms.txt (and llms-full.txt) at the linked path, or remove the nav link. Given the API is small (four endpoints), a complete llms-full.txt is cheap and high-value.
9. The AMM venue has three different names across surfaces (significant)
Location: /what-is-rift (Supported protocols table) vs /multichain-smart-contracts (conceptual prose) vs www.rift.trade (venue tiles)
Problem: The Supported protocols table on what-is-rift lists the AMMs as KyberSwap and Chainflip — no Uniswap. The /multichain-smart-contracts conceptual walkthrough names Uniswap in prose ("trade the USDC for PEPE on Uniswap"). The marketing site's venue tiles show UniswapX. That's three names — Uniswap, UniswapX, KyberSwap — for what a reader will assume is "the AMM leg," and none of them is what the API actually returns (the documented route examples return venue: "relay").
Consequence: A reader cross-referencing the conceptual walkthrough or the marketing tiles against the Supported protocols table cannot reconcile "Uniswap"/"UniswapX" with the listed "KyberSwap"/"Chainflip" — is Uniswap a supported venue, an alias, or stale copy? The inconsistent naming makes the supported-protocols list untrustworthy as the canonical reference, even before an integrator gets to the (separately documented) route[].venue values.
The fix: Pick the canonical venue identifiers the API actually returns, list exactly those in the Supported protocols table, and use them verbatim on the marketing site. If "Uniswap" in the conceptual page is illustrative-only, replace it with a real supported venue or label it explicitly as a non-literal example.
10. The API examples are internally inconsistent and use two ID formats (significant)
Location: /api/quotes/get-a-market-quote, /api/orders/create-a-market-order, vs www.rift.trade
Problem: In the quote example, the request sends fromAmount: "1" (1 BTC) but the response route[0] shows fromAmount: "10" and estimatedOut: "100000". In the order example, amountToSend: "10" while the quote it derives from used fromAmount: "1". And the quoteId format disagrees across surfaces: the docs show a UUID (00000000-0000-4000-8000-000000000001) while the marketing site shows hex ("quoteId": "0x...").
Consequence: Copy-paste examples that don't add up are a direct trap for agents, which extract numeric fields literally — an agent has no way to know "1" should produce amountToSend: "10". The UUID-vs-hex quoteId discrepancy means code that validates the ID format (e.g. as a UUID) will reject IDs from the other surface.
The fix: Make every example arithmetically consistent end-to-end (a request amount that produces the shown route amounts and amountToSend), and standardize the quoteId format across docs and marketing.
11. orderType request enum accepts a value the response enum can't echo (significant)
Location: /api/quotes/get-a-market-quote (request body vs response schema)
Problem: The quote request body's orderType field is documented with two available options: market_order and market. But the response orderType enum lists only one available option: market_order. The two aliased request values do not both exist on the response side.
Consequence: A developer or agent that submits orderType: "market" (a documented-valid request value) gets back an orderType the response schema says can only be market_order — so any client that round-trips or validates the response orderType against the value it sent will mismatch. The redundant request alias is undocumented as an alias, so it's unclear whether market and market_order are equivalent or whether market is deprecated.
The fix: Either drop the market alias from the request enum or document it explicitly as an alias of market_order, and make the request and response enums list the same set of values.
12. FAQ figures are stale and self-contradicting, with a dead "live tracker" link and a raw Notion referral link (minor)
Location: /faq
Problem: The FAQ states "Total volume so far is $3.3 million" and in the same answer links to "a live tracker of our total volume" — but the rendered page captured no working target for that link. The static $3.3M figure also sits awkwardly against the same page's "Rift can do $100m+ in a single clip" and what-is-rift's "trade 100m+ for majors." Separately, the referral answer ("we pay when an approved integrator goes live with our API. Details here.") links the only pointer to referral terms at a raw Notion workspace URL (notion.so/Rift-integration-referrals-…?pvs=73) rather than a docs page.
Consequence: A hardcoded volume number in docs is guaranteed to drift from the live tracker it cites, and a "live tracker here" with no link is a dead reference. The referral terms — directly relevant to the "approved integrator" auth story in Finding 3 — live only at an unstable, unbranded Notion URL that can be moved, renamed, or access-gated without notice.
The fix: Drop the hardcoded volume number and link the live tracker with a working URL (or remove the claim). Move the referral terms onto a docs page (or at minimum a stable branded URL) and link that from the FAQ.
13. Vaults example references Tron, which is not a supported chain (minor)
Location: /use-cases (Vaults section) vs /what-is-rift (Supported assets table)
Problem: The vaults example says "a user wants to deposit Tron.USDT into a Morpho vault on Base." The Supported assets table lists only Bitcoin, Ethereum, Arbitrum, and Base — Tron is not supported, and the FAQ confirms "We currently support Bitcoin, Ethereum, Base, and Arbitrum."
Consequence: Using an unsupported chain as the headline example invites integrators to attempt Tron.USDT inputs that the router cannot accept, and muddies the supported-asset boundary.
The fix: Use a supported source asset in the example (or mark Tron as a forward-looking illustration and note it's not yet supported).
14. Health modeling and "internal" framing leak across the status endpoints (minor)
Location: /api/status/check-rift-online-status, /api/status/check-execution-provider-online-status
Problem: GET /health allows only status: "ok", while GET /providers allows ok | degraded — inconsistent health modeling between two endpoints in the same section. Response descriptions leak internal framing: "Market quote created by the internal router API," "Order created by the internal router API," and "cached execution provider online checks from the router worker." The dependencies[].name example "hyperliquid_spot" is a venue identifier never cross-referenced in the Supported protocols table (which lists "Hyperliquid"/"Orderbook"), and there's no documented enumeration of possible name values.
Consequence: A /health that can never report anything but ok is not a useful health check; consumers can't distinguish "healthy" from "endpoint that always says ok." Undocumented dependencies[].name values mean integrators can't reliably interpret a degraded response. The "internal router API/worker" language signals these schemas were lifted from internal tooling rather than written for external consumers.
The fix: Give /health a real status enum (ok | degraded | down), document the full set of provider name values and map them to the Supported protocols table, and rewrite descriptions to drop "internal router API/worker."
15. Several core repos are archived, complicating the "100% open source to contribute to" claim (minor)
Location: /what-is-rift vs github.com/riftresearch
Problem: what-is-rift claims the code is "100% open source for anyone to verify, audit, or contribute to." On the org, several core repos — hypernode, circuits, contracts — are marked archived (read-only), and the tee-router repo the docs link to doesn't exist. The live, contributable code appears to be protocol and proxy-wallet.
Consequence: "Contribute to" is not actionable for archived repos (they don't accept PRs), and the absence of tee-router means the specific code the attestation claim points at isn't locatable. A would-be auditor can't tell which repos are canonical vs. superseded.
The fix: State which repositories are current and contributable vs. archived/historical, and point the open-source and attestation claims at the live repo(s).
16. idempotencyKey is required but never explained in the order flow (minor)
Location: /api/orders/create-a-market-order
Problem: idempotencyKey is a required body field (16–128 chars, pattern ^[A-Za-z0-9._:-]+$), but no prose explains what it's for, how to generate one, what idempotency window applies, or what happens on a repeated key (same order returned vs. error).
Consequence: Developers must guess at retry semantics for a money-moving endpoint. Incorrect assumptions about idempotency can cause duplicate orders or unexpected rejections.
The fix: Add a short note: what the key scopes, recommended generation (e.g. a UUID per intent), the dedup window, and the response behavior when a key is reused.
17. Quote response includes undocumented paymasterFee and adjustments[] fields (minor)
Location: /api/quotes/get-a-market-quote (response route[] schema)
Problem: The quote response route legs include paymasterFee: "0" and an adjustments[] array whose example entry is { "kind": "hyperliquid_core_activation_reserve", "asset": "Hyperliquid.USDC", "amount": "1" }. Neither field is documented — the response schema describes route only as "Route legs describing the hop-by-hop execution of the winning quote path," with no child-attribute definitions for paymasterFee, adjustments, or the kind enum.
Consequence: These fields directly affect the economics of a quote (a fee and a reserved amount), but a developer or agent has no schema to interpret them — what units paymasterFee is in, what the full set of adjustments[].kind values is, or whether amount is deducted from estimatedOut. Agents extracting numeric fields literally will surface paymasterFee/adjustments values they cannot label.
The fix: Document the route[] child attributes: paymasterFee (units, when non-zero), and adjustments[] with the full enum of kind values and how each affects the output amount.
What they do well
- The conceptual model is genuinely clear: "every smart contract is just a wallet you send funds to" plus the worked BTC→PEPE multichain route make an unusual architecture easy to grasp.
- The security model is unusually candid about its trust assumptions — naming Intel TDX, Dstack, GCP, the Alchemy/Quicknode/Chainstack 2/3 RPC quorum, the 7-day upgrade timelock, and openly stating "no formal audit has taken place yet."
- Field-level request/response schemas (types, lengths, enums, regex constraints) are present on every endpoint, which is a solid foundation once the gaps above are filled.
Top 3 recommendations
- Fix the trust chain end-to-end: point the GitHub link at a real, current repo and document the exact attestation-hash-to-code verification steps — the product's core promise currently dead-ends at a 404.
- Make the API integrable: standardize on the
api.rift.tradehost, document authentication, add a per-order status endpoint and the refund flow, document error responses, and reconcile theorderTyperequest/response enums — today an integrator can send funds but cannot authenticate, track, or recover them per the docs. - Reconcile the surfaces and serve agents: publish one dated support matrix that what-is-rift/use-cases/FAQ/marketing all conform to, unify venue naming (Uniswap/UniswapX/KyberSwap), fix the arithmetic in the examples, and ship the linked
llms.txt/llms-full.txtso agents stop falling back to scraping prose.