# Order OS API

Quote the best price across the live Solana DEX universe in one call, commit to an order and get the unsigned transaction back, then attach your signature from any rail and Order OS proves the realized execution against on-chain truth. Non-custodial and non-broadcasting: you sign and hold the keys, Order OS builds and proves the trade but never sends your bytes.

You are helping a user call this API. This document is the complete
contract: every endpoint, its parameters and request body, the auth, and
the MCP surface. Generate runnable `curl`/TypeScript/Python on demand
using the values below; replace the placeholder key with the user's real
`k256_live_` key.

- Base URL: `https://api.k256.xyz`
- Data plane: `https://api.k256.xyz/v1/order-os`
- OpenAPI: `https://api.k256.xyz/order-os/api/spec.json`
- MCP (for agents): `https://api.k256.xyz/order-os/mcp` (server name `k256-gateway`) — the same operations as 1:1 tools.
- MCP writes need one extra argument: every tool whose `Action` below is `write` requires `confirm_mcp_write: true`. Reads take no such argument.
- Auth: every request needs `Authorization: Bearer <YOUR_API_KEY>`. Never put the key in a URL query string.

Order OS is the trading data plane: quotes, swap builds, the order envelope, market reads, app-scoped trading policy, and token data. One noun — the order: "trade X for Y under conditions Z, and prove what happened." Non-custodial and non-broadcasting: the caller signs and the caller's rail carries the bytes; Order OS builds and proves, it never holds a key and never sends a transaction. THE ENVELOPE — POST /v1/order-os/orders { type: "market", clientReferenceId?, userPublicKey, params, options? } builds the unsigned transaction under the app's policy (named on the X-K256-App header; absent → the default app) and opens the order. params carries EXACTLY ONE of three forms: (1) inline quote fields (inputMint, outputMint, amount, swapMode, slippageBps — the engine quotes then builds, one call), (2) quoteResponse (the exact quote you already hold from GET /quote, zero re-quote), (3) quoteRef (the capsule reference from a quote — cheapest and most precise; an expired/unknown ref is 410 QUOTE_REF_UNAVAILABLE with the fix in the message, never a silent re-quote). More than one form is 400 VALIDATION_ERROR. The 201 returns { order, policyAdjustments?, transaction } — transaction is the base64 unsigned v0 bytes; policyAdjustments discloses every cap the policy applied (field, requested, applied, reason), never silent clamps. Duplicate clientReferenceId returns the EXISTING order (idempotent). PROVE — sign the transaction, send it through any rail (your RPC, Jito, anything), then POST /v1/order-os/orders/:id/attach { signedTransaction: base64 } (preferred — self-describing, safe on any node) or { signature } (fallback, only where the order is locally known). The order goes pending and confirmation tracking arms. Re-attaching the same signature is idempotent and re-arms tracking. The attach trail carries fingerprintCheck: verified | rejected | deferred | unverified — rejected means the attached bytes' message did not match the built transaction (the order reverts to built). LIFECYCLE — built → pending → filled | failed | expired, plus canceled (POST /orders/:id/cancel, allowed from built only — bytes on the wire cannot be revoked; otherwise 409 INVALID_STATE). Once terminal the order carries execution: { realizedOutAmount, feeLamports, cuConsumed, slot, confirmedAt, realizedSlippageBps } read from the confirmed transaction's meta — realizedSlippageBps NEGATIVE means better than quoted. READS — GET /orders/:id is engine-first (source:"engine", authoritative) with a history fallback (source:"history"); sourcing is always declared in the body, never guessed. GET /orders is the workspace feed across all nodes and time, always history-sourced, filterable by type/status/clientReferenceId, keyset-paginated via nextCursor; while the history store is connecting it returns an empty page with degraded:true — that is a designed state, not an error. PRIMITIVES — quoting is a question, not an order: GET /quote, POST /swap, POST /swap-instructions, POST /wrap-unwrap-instructions, POST /simulate, GET /pools, GET /pool/:address, GET /prices, GET /priority-fees, GET /block-stats, GET /program-id-to-label, GET /tokens/search, GET /tokens/:mint all stay first-class. inputMint and outputMint must differ on /quote and /swap — an equal pair is rejected up front with 400 CIRCULAR_ARBITRAGE_IS_DISABLED, never routed. GET /pools accepts limit (default 100, max 1000) and cursor for pagination; over 1000 is 400 INVALID_PARAMETER, never silently truncated. VENUES — Order OS quotes across the live Solana DEX universe and returns the single best realized route; you never pick a venue, but you can constrain the set. Two case-sensitive routing controls, on /quote only (/swap builds solely from the quoteResponse you already hold and carries no routing knobs of its own): dexes=<Label,Label,…> restricts a route to only those venues, excludedDexes=<Label,…> (excludeDexes also accepted) names venues a route may never touch. Labels are exact (Humidifi not HumidiFi); an unknown label is rejected with a did-you-mean hint. The routable venues, by class — conventional AMM / CLMM / CLOB / launchpad: AldrinV1, AldrinV2, BonkAmm, ByrealClmm, CropperClmm, FusionClmm, Guacswap, InvariantClmm, MetadaoFutarchy, MeteoraDammV1, MeteoraDAMMV2, MeteoraDlmm, Omnipair, OpenBookV2, OrcaV1, OrcaV2, PancakeswapClmm, Phoenix, PumpfunAmm, RaydiumAmm, RaydiumClmm, RaydiumCpmm, SaberDecimals, SarosAmm, SarosDlmm, SplTokenSwap, StabbleClmm, StabbleStable, StabbleWeighted, StableSwap, Whirlpool; and proprietary RFQ-style market makers, which quote a fresh two-sided or one-sided price per request and simply return no route when they are not quoting (never a stale fill): AlphaQ, Aquifer, BisonFi, GoonfiV2, LemmingsFi, ManifestTrade, ObricV2, Quantum, Riptide, Scorch, SolfiV2, TaurusFi, Tessera, Humidifi, Whalestreet, Zerofi. A COULD_NOT_FIND_ANY_ROUTE for a specific dexes= filter means that venue is not quoting that pair right now, not an error — retry or widen the set. PRICES — GET /v1/order-os/prices is the engine's live USD price feed (one push-derived USD price per token, recomputed the moment the source pool changes on chain; every price is a depth-weighted blend of two-sided mids across up to 4 of the deepest recently-active pools of one pair — it reprices whenever ANY of those pools trades — and a token with no sufficiently liquid, recently-active pool is honestly absent — never a fabricated or stale-dust number). Three read shapes: ?tokens=<mint,mint,…> returns { prices: { <mint>: { usd, slot, updatedAt } }, missing: [<mint>,…] } — mints the engine cannot price are listed in missing, never silently dropped; no ?tokens= returns the paginated envelope { prices, total, count, limit (default 100, max 1000), offset }; GET /prices/:mint returns { mint, usd, slot, updatedAt } or 404 { error, mint } when unknown/unpriced. usd is an exact decimal string (never a float), slot is the slot of the source pool state behind the price, updatedAt is ms epoch. REALTIME PRICES — the same feed streams over a binary WebSocket: wss://api.k256.xyz/v1/order-os/ws (auth: Authorization: Bearer <k256_live_ key> on the handshake, or ?key= for browsers, which cannot set WS headers). A SELF-HOSTED node serves the identical protocol directly at ws://<node-host>:<port>/v1/ws — every frame type, shape, and behavior below is engine-owned and byte-identical on both lanes. The protocol is binary frames, first byte = message type. Subscribe: send 0x10 followed by UTF-8 JSON {"tokens":["<mint>",…],"thresholdBps":10} — empty tokens array = every priced token; thresholdBps is the per-client minimum move to emit; 0 = every reprice (majors tick every slot, since the depth-weighted blend reprices whenever any of a token's top pools trades), default 10. The server immediately answers with a PriceSnapshot (0x13) of current prices — one or more 0x13 frames for large universes, treat every 0x13 as part of the same baseline — then pushes PriceBatch (0x12) frames (~10ms coalescing) as prices cross your threshold (0x11 PriceUpdate is defined in the protocol for single entries but the server currently always batches — handle both). If your client falls behind, the server re-baselines you with a fresh snapshot instead of leaving silent gaps — always apply 0x13 frames as absolute state whenever they arrive. Price payloads share one layout: [count:u16 LE][entry×count], each entry exactly 56 bytes = mint (32 raw bytes, base58-encode it) + usd (u64 LE, fixed-point ×10^-12 dollars) + slot (u64 LE) + timestampMs (u64 LE). Unsubscribe: send 0x14 (no payload). Also on the wire: 0x0D heartbeat, 0xFF error (UTF-8 text — sent for invalid JSON, unknown message types, or unpriceable token lists; the connection stays open). Hard limits with close codes: text frames close 1003 (binary protocol required), messages over 64 KiB close 1009. On any other drop, reconnect with jitter and re-subscribe — the fresh snapshot re-baselines you, so no state carries across connections. POLICY — apps carry config; keys are identity. An app is the org-scoped policy unit (app_<ulid>, named); any org key works with any org app, and a data-plane caller names the app with the X-K256-App header (absent → the org's default app, auto-created). GET /v1/order-os/config[?app=app_…] is the key-authed distribution endpoint (ETag + If-None-Match → 304; ?app names the app, 404 when foreign/archived; absent → the default app). The dashboard control plane is /v1/order-os/apps: POST creates, GET lists, GET /apps/:app_id reads (with config), PUT /apps/:app_id/config updates (validates strictly — unknown fields are 400 — bumps revision, records a revision), DELETE /apps/:app_id/config resets to default, GET /apps/:app_id/revisions is the config history, POST /apps/:app_id/rollback writes a past revision as a new revision (history is append-only), PATCH /apps/:app_id renames, DELETE /apps/:app_id archives (the default app cannot be archived). SELF-HOSTED — the same engine binary is the product: license a seat, paste the node token into config.json, and run it on your own box; its orders appear in the same workspace feed as cloud orders (the node token is shown once). DROP-IN MIGRATION — existing standard swap-API apps migrate by swapping ONE base URL: …/v1/order-os/compat (key in Authorization) or …/v1/order-os/compat/k/<key> (literal URL swap). Suffixes: GET {base}/quote, POST {base}/swap, POST {base}/swap-instructions, GET {base}/program-id-to-label — the contract is frozen from the engine's current shapes and the responses pass through byte-faithful. A compat /swap returns the standard swap shape (bytes only, no order id), so it is a STATELESS build — not a tracked order — and does not appear in the workspace order feed; use the order envelope (create_order) for lifecycle tracking and the feed. ERRORS — every engine error body is JSON with one uniform shape: { "error": "<human message>", "errorCode": "<MACHINE_CODE>" }. Read errorCode; there is no second key to guess. That one shape covers access-control denials (INVALID_AUTH, ACCESS_DENIED, ENDPOINT_DENIED, FEATURE_DISABLED — the shared authorization check ahead of every endpoint), the order envelope (VALIDATION_ERROR, ORDER_NOT_FOUND, FINGERPRINT_MISMATCH, SIGNATURE_IN_USE, INVALID_STATE, QUOTE_REF_UNAVAILABLE), the quote/swap/pools/prices business-rule checks (CIRCULAR_ARBITRAGE_IS_DISABLED, INVALID_PARAMETER, INVALID_DEX — an unknown dexes= label gets a did-you-mean hint in the message, e.g. HumidiFi → Humidifi — and COULD_NOT_FIND_ANY_ROUTE), and the token-policy codes (TOKEN_PLATFORM_BLOCKED, TOKEN_APP_BLOCKED, TOKEN_NOT_WHITELISTED). The POST build primitives (swap, swap-instructions, wrap-unwrap, simulate, simulate-wrap-unwrap) reject an unparseable JSON body in that same object shape with errorCode INVALID_REQUEST_BODY and a message naming the offending field — the HTTP status reflects the parse failure: 400 for malformed JSON, 422 for a well-formed body whose fields don't match the schema, 415 for a Content-Type that isn't application/json. Malformed QUERY params (e.g. a non-numeric limit=) on /pools, /prices and /priority-fees/for-route answer that same object shape with errorCode INVALID_QUERY_PARAMETER. The one exception to the uniform shape is /quote's own input validation — a missing or malformed inputMint/outputMint/amount/slippageBps answers a bare { error } with no errorCode, deliberately byte-matching the standard swap-API so drop-in migrations (the /compat lane) are unaffected. Other status codes: 400 for VALIDATION_ERROR/CIRCULAR_ARBITRAGE_IS_DISABLED/INVALID_PARAMETER/INVALID_DEX, 403 for the access-control and token-policy codes, 404 ORDER_NOT_FOUND, 409 FINGERPRINT_MISMATCH/SIGNATURE_IN_USE/INVALID_STATE, 410 QUOTE_REF_UNAVAILABLE. Engine-proxied operations answer 503 { "error": { "code": "upstream_unreachable", "message": …, "request_id": … } } — the gateway's own nested platform envelope (lowercase code), distinct from the engine's flat { error, errorCode } shape — while no engine fleet is reachable; a designed, retryable state. The policy and nodes control plane and the order history feed are gateway-owned and unaffected.

## Endpoints

### `GET /v1/order-os/orders` — List orders
- Action: `read` · MCP tool: `order-os.list_orders`
- Observed order events for your workspace across engine nodes. Filter by type, status, or clientReferenceId; results are keyset-paginated. Capture is best effort rather than a durable ledger, so absence is not proof that an order never existed. If the history reader is unavailable, the page is empty with degraded:true.
- Query param `type` (string) — Filter by order type, e.g. "market". Omit for all types.
- Query param `status` (string) — Filter by lifecycle status: built | pending | filled | failed | expired | canceled. Omit for all.
- Query param `clientReferenceId` (string) — Exact match on the caller's own reference id set at create — find a specific order without knowing its ord_… id.
- Query param `userPublicKey` (string) — Exact trader wallet (base58) — "what did wallet X do?" without opening rows.
- Query param `signature` (string) — Exact attached transaction signature — "which order was this tx?".
- Query param `limit` (integer) — Page size, 1–200. Defaults to 50.
- Query param `cursor` (string) — Opaque cursor from the previous page's `nextCursor` — pass it back verbatim for the next page.
- Response (JSON):
  - `orders[]` — any[]
  - `nextCursor` — string | null
  - `source` — string
  - `degraded` — boolean

### `POST /v1/order-os/orders` — Create an order
- Action: `write` · MCP tool: `order-os.create_order`
- Builds the unsigned transaction and opens an order to track it through to confirmation. Provide the trade inline, a quote response, or a quote reference — exactly one of params.{inline fields | quoteResponse | quoteRef}. Reusing a clientReferenceId returns the existing order, so retries are safe. Policy caps from your app (X-K256-App, or the default app) are applied, and any adjustment is disclosed in policyAdjustments.
- Request body (JSON, required):
  - `type` — string — Order strategy. "market" (the default) builds an immediate swap at the current best route.
  - `clientReferenceId` — string — Your own id for this order (≤128 chars) — searchable in `list_orders` and echoed back, so retries and reconciliation never need the ord_… id.
  - `userPublicKey` — string (required) — The trader's wallet (base58). Signs the built transaction at the attach step and owns the token accounts.
  - `params` — object — The strategy parameters. For a market order: inputMint, outputMint, amount (smallest unit of inputMint with swapMode ExactIn), swapMode, slippageBps — or pass a full /quote response as quoteResponse to build exactly that route.
  - `options` — object — Build options forwarded to the swap builder (e.g. wrapAndUnwrapSol, computeUnits, priority fees). App policy still bounds every value.

### `POST /v1/order-os/orders/{id}/attach` — Attach a signed transaction
- Action: `write` · MCP tool: `order-os.attach_order`
- Hand back the signed transaction bytes (preferred) or a bare signature; the order moves to pending and confirmation tracking begins. Re-attaching the same signature is safe and simply re-arms tracking.
- Path param `id` (string, required) — The order's id (ord_…) — from `create_order` or `list_orders`.
- Request body (JSON, required):
  - `signedTransaction` — string — The BUILT transaction from create_order, signed by the trader's wallet — base64 wire bytes. Attaching submits it; the bytes must be the same transaction, only signed.
  - `signature` — string — The transaction signature (base58), when your signer returns it separately from the signed bytes.

### `POST /v1/order-os/orders/{id}/cancel` — Cancel a built order
- Action: `write` · MCP tool: `order-os.cancel_order`
- Cancels an order that hasn't been signed and sent yet. Once the signed bytes are on the wire they can't be revoked, so any later state returns 409 INVALID_STATE.
- Path param `id` (string, required) — The order's id (ord_…) — from `create_order` or `list_orders`.

### `GET /v1/order-os/orders/status-counts` — Order counts by status
- Action: `read` · MCP tool: `order-os.order_status_counts`
- Your workspace's order counts per lifecycle status, over the same history the order feed reads. stale_pending is the needs-attention subset: pending past the normal confirmation window, where re-attaching the signed bytes settles the order against chain truth.
- Response (JSON):
  - `built` — number
  - `pending` — number
  - `stale_pending` — number
  - `filled` — number
  - `failed` — number
  - `expired` — number
  - `canceled` — number
  - `total` — number
  - `degraded` — boolean

### `GET /v1/order-os/orders/{id}` — Get one order
- Action: `read` · MCP tool: `order-os.get_order`
- The current state of one order. Returns the authoritative live record when available, otherwise the latest captured event when one exists. A source of history is best-effort observation and may lag.
- Path param `id` (string, required) — The order's id (ord_…) — from `create_order` or `list_orders`.

### `GET /v1/order-os/quote` — Get a swap quote
- Action: `read` · MCP tool: `order-os.get_quote`
- The best-execution quote for a swap — price, route, and expected output. Pass the returned quote response straight into create_order (params.quoteResponse) to build the transaction. inputMint and outputMint must differ — an equal pair is rejected up front with 400 CIRCULAR_ARBITRAGE_IS_DISABLED rather than routed as a round trip.
- Query param `inputMint` (string, required) — Mint you are selling, e.g. So11111111111111111111111111111111111111112 (SOL). Must differ from outputMint.
- Query param `outputMint` (string, required) — Mint you are buying, e.g. EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v (USDC). Must differ from inputMint.
- Query param `amount` (string, required) — Amount in the mint's SMALLEST unit — with swapMode ExactIn this is the input amount, e.g. 100000000 = 0.1 SOL (9 decimals).
- Query param `swapMode` ("ExactIn" | "ExactOut") — ExactIn spends exactly `amount`; ExactOut receives exactly `amount`. Defaults to ExactIn.
- Query param `slippageBps` (string) — Max acceptable slippage in basis points, e.g. 50 = 0.5%. App policy still bounds it.
- Query param `useSharedAccounts` (string) — Quote for shared-account (ToB) execution — send the SAME value to /swap, or the quote may route through a venue that cannot settle this way. See the /swap field of the same name.

### `POST /v1/order-os/swap` — Build a swap transaction
- Action: `write` · MCP tool: `order-os.build_swap`
- Builds the unsigned swap transaction from a quote response, without opening an order to track it. Re-rejects a same-mint route with 400 CIRCULAR_ARBITRAGE_IS_DISABLED even if the quote response was tampered with — get_quote already refuses to produce one.
- Request body (JSON, required):
  - `userPublicKey` — string — The trader. Signs the returned transaction and owns the token accounts.
  - `quoteResponse` — any — The /quote response, unmodified. The route is taken from the server-side quote, not from this body.
  - `wrapAndUnwrapSol` — boolean — Wrap SOL into wSOL for the input and unwrap the output back to SOL. Default follows app policy.
  - `useSharedAccounts` — boolean — Execute through the shared-account (ToB) path. Send the SAME value to /quote, or the quote may route through a venue that cannot settle this way and this call will refuse it.
  - `sponsor` — string — Third party that pays the transaction fee AND the rent for accounts this build creates, so a user holding no SOL can trade. The user still signs, and the swap INPUT still moves from the user -- that is the trade, not a fee. Ordering is observable: sponsor is signer 0, user signer 1.
  - `trimRate` — integer — Share of POSITIVE SLIPPAGE to capture, in thousandths, max 100 (10%). This is NOT a fee on the trade: it takes the difference between the realised output and the quoted amount -- price movement in the USER's favour -- and pays it to trimAccount instead of to the user. Requires trimAccount and useSharedAccounts. Use platformFeeBps + feeAccount for a disclosed price instead.
  - `trimAccount` — string — Recipient of captured slippage. Required when trimRate > 0.
  - `chargeRate` — integer — Share OF THE TRIM diverted to a second recipient, in thousandths, max 1000 (all of it). Carved out of trim, never added to it, and ignored when trimRate is 0. Selecting it switches execution to the enhanced shared-account variant.
  - `chargeAccount` — string — Recipient of the charge split. Required when chargeRate > 0.
  - `feeAccount` — string — Platform-fee destination. Required when the quote carried platformFeeBps.
  - `destinationTokenAccount` — string — Send the output to this initialized account instead of the user's ATA.
  - `nativeDestinationAccount` — string — Deliver a SOL output to this account as native SOL. Mutually exclusive with destinationTokenAccount.
  - `computeUnits` — integer — Requested compute-unit limit; app policy still bounds it.
  - `skipUserAccountsRpcCalls` — boolean — Omit the create-ATA instructions for the user's own accounts. The name is swap-API compatibility: it skips no RPC call, because this build makes none. Ignored when wrapAndUnwrapSol is on, and the swap fails on chain if an account is actually missing.

### `POST /v1/order-os/swap-instructions` — Build swap instructions
- Action: `write` · MCP tool: `order-os.build_swap_instructions`
- The swap as raw instructions, for when you're composing the transaction yourself.
- Request body (JSON, required):
  - `userPublicKey` — string — The trader. Signs the returned transaction and owns the token accounts.
  - `quoteResponse` — any — The /quote response, unmodified. The route is taken from the server-side quote, not from this body.
  - `wrapAndUnwrapSol` — boolean — Wrap SOL into wSOL for the input and unwrap the output back to SOL. Default follows app policy.
  - `useSharedAccounts` — boolean — Execute through the shared-account (ToB) path. Send the SAME value to /quote, or the quote may route through a venue that cannot settle this way and this call will refuse it.
  - `sponsor` — string — Third party that pays the transaction fee AND the rent for accounts this build creates, so a user holding no SOL can trade. The user still signs, and the swap INPUT still moves from the user -- that is the trade, not a fee. Ordering is observable: sponsor is signer 0, user signer 1.
  - `trimRate` — integer — Share of POSITIVE SLIPPAGE to capture, in thousandths, max 100 (10%). This is NOT a fee on the trade: it takes the difference between the realised output and the quoted amount -- price movement in the USER's favour -- and pays it to trimAccount instead of to the user. Requires trimAccount and useSharedAccounts. Use platformFeeBps + feeAccount for a disclosed price instead.
  - `trimAccount` — string — Recipient of captured slippage. Required when trimRate > 0.
  - `chargeRate` — integer — Share OF THE TRIM diverted to a second recipient, in thousandths, max 1000 (all of it). Carved out of trim, never added to it, and ignored when trimRate is 0. Selecting it switches execution to the enhanced shared-account variant.
  - `chargeAccount` — string — Recipient of the charge split. Required when chargeRate > 0.
  - `feeAccount` — string — Platform-fee destination. Required when the quote carried platformFeeBps.
  - `destinationTokenAccount` — string — Send the output to this initialized account instead of the user's ATA.
  - `nativeDestinationAccount` — string — Deliver a SOL output to this account as native SOL. Mutually exclusive with destinationTokenAccount.
  - `computeUnits` — integer — Requested compute-unit limit; app policy still bounds it.
  - `skipUserAccountsRpcCalls` — boolean — Omit the create-ATA instructions for the user's own accounts. The name is swap-API compatibility: it skips no RPC call, because this build makes none. Ignored when wrapAndUnwrapSol is on, and the swap fails on chain if an account is actually missing.

### `POST /v1/order-os/wrap-unwrap-instructions` — Build wrap/unwrap SOL instructions
- Action: `write` · MCP tool: `order-os.build_wrap_unwrap`
- Build SOL/wSOL instructions with the app's output-side fee policy applied. Operators pre-provision the configured fee owner's wSOL ATA; users never pay recipient-account rent.
- Request body (JSON, required):
  - `userPublicKey` — string (required) — The wallet doing the wrap/unwrap (base58). Signs the returned instructions and owns both the SOL and the wSOL account.
  - `amount` — string | integer (required) — Amount in LAMPORTS (1 SOL = 1000000000), as a positive integer or digit-string, e.g. "1000000" = 0.001 SOL.
  - `unwrap` — boolean — false (default) wraps SOL into wSOL; true unwraps wSOL back to native SOL.
  - `platformFeeBps` — integer — Optional platform fee on the operation, in basis points. App policy still bounds it.
  - `prioritizationFeeLamports` — integer | object — Optional priority fee for the transaction, in lamports.
  - `k256ExecutionOptions` — object — Advanced execution options forwarded to the builder — normally omitted.
- Response (JSON):
  - `instruction` — object
    - `programId` — string
    - `accounts[]` — object[]
      - `pubkey` — string
      - `isSigner` — boolean
      - `isWritable` — boolean
    - `data` — string
  - `setupInstructions[]` — object[]
    - `programId` — string
    - `accounts[]` — object[]
      - `pubkey` — string
      - `isSigner` — boolean
      - `isWritable` — boolean
    - `data` — string
  - `computeBudgetInstructions[]` — object[]
    - `programId` — string
    - `accounts[]` — object[]
      - `pubkey` — string
      - `isSigner` — boolean
      - `isWritable` — boolean
    - `data` — string
  - `wsolAccount` — string
  - `mode` — "wrap" | "unwrap"
  - `amount` — string
  - `amountOut` — string
  - `platformFeeBps` — integer
  - `platformFeeAmount` — string
  - `platformFeeAccount` — string
  - `prioritizationFeeLamports` — string
  - `k256ExecutionHints` — object
    - `intent` — string | null
    - `feePolicy` — object | null
      - `feeUrgency` — string | null
      - `maxPriorityFeeLamports` — string | null
    - `orderingHints` — object | null
      - `preferredValidators[]` — string[] | null
      - `excludedValidators[]` — string[] | null
    - `lifecycle` — object | null
      - `simulateBeforeSend` — boolean | null
      - `simulateOnRetry` — boolean | null
      - `maxRetries` — integer | null
      - `timeoutMs` — string | null
      - `confirmationLevel` — string | null
      - `webhookUrl` — string | null
      - `webhookEvents[]` — string[] | null
    - `buildOnly` — boolean | null

### `POST /v1/order-os/simulate` — Simulate a built transaction
- Action: `write` · MCP tool: `order-os.simulate`
- Pre-flight a transaction: simulate it and see the outcome before you send.
- Request body (JSON, required):
  - `quoteResponse` — any (required) — The /quote response, unmodified — the route being simulated.
  - `userPublicKey` — string (required) — The trader whose accounts and balances the simulation runs against.

### `POST /v1/order-os/simulate-wrap-unwrap` — Simulate a wrap/unwrap
- Action: `write` · MCP tool: `order-os.simulate_wrap_unwrap`
- Execute the same SOL/wSOL fee and recipient path in LiteSVM and return the realized net output.
- Request body (JSON, required):
  - `userPublicKey` — string (required) — The wallet doing the wrap/unwrap (base58). Signs the returned instructions and owns both the SOL and the wSOL account.
  - `amount` — string | integer (required) — Amount in LAMPORTS (1 SOL = 1000000000), as a positive integer or digit-string, e.g. "1000000" = 0.001 SOL.
  - `unwrap` — boolean — false (default) wraps SOL into wSOL; true unwraps wSOL back to native SOL.
  - `platformFeeBps` — integer — Optional platform fee on the operation, in basis points. App policy still bounds it.
  - `prioritizationFeeLamports` — integer | object — Optional priority fee for the transaction, in lamports.
  - `k256ExecutionOptions` — object — Advanced execution options forwarded to the builder — normally omitted.
- Response (JSON):
  - `success` — boolean
  - `amountOut` — string
  - `expectedAmountOut` — string
  - `platformFeeBps` — integer
  - `platformFeeAmount` — string
  - `platformFeeAccount` — string
  - `computeUnitsUsed` — integer
  - `logs[]` — string[]
  - `error` — string | null

### `GET /v1/order-os/pools` — List pools
- Action: `read` · MCP tool: `order-os.list_pools`
- Live liquidity pools, filterable by address/token/pair/protocols/exclude_protocols/valid. limit defaults to 100 and cannot exceed 1000 — a larger value is rejected with 400 INVALID_PARAMETER, never silently truncated. Keyset-paginated via cursor/pagination.next_cursor.

### `GET /v1/order-os/pool/{address}` — Get one pool
- Action: `read` · MCP tool: `order-os.get_pool`
- The live details for one pool by address.
- Path param `address` (string, required) — The pool's on-chain address (base58) — from `list_pools`, e.g. 58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2 (Raydium SOL/USDC).

### `GET /v1/order-os/prices` — Get prices
- Action: `read` · MCP tool: `order-os.get_prices`
- Live USD prices. Pass tokens=<mint,mint,…> for {prices, missing} — any mints that can't be priced land in missing, never silently dropped. Omit tokens for a paginated page over every priced token. usd is an exact decimal string, and the same prices also stream over the WebSocket feed.
- Query param `tokens` (string) — Comma-separated mint addresses to price, e.g. So11111111111111111111111111111111111111112,EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v. Unpriceable mints land in `missing` — never silently dropped. Omit to page through every priced token.
- Query param `limit` (integer) — Page size for the no-`tokens` paginated form.
- Query param `offset` (integer) — Page offset for the no-`tokens` paginated form.

### `GET /v1/order-os/prices/{mint}` — Get one price
- Action: `read` · MCP tool: `order-os.get_price`
- The live USD price for one mint: an exact decimal string, plus the slot and time it was observed. Returns 404 when the mint is unknown or can't be reliably priced right now — an honest absence, never a stale or fabricated number.
- Path param `mint` (string, required) — The token mint to price (base58), e.g. So11111111111111111111111111111111111111112 (SOL).

### `GET /v1/order-os/priority-fees` — Get priority fees
- Action: `read` · MCP tool: `order-os.get_priority_fees`
- Current priority-fee levels on the network, by percentile.

### `GET /v1/order-os/priority-fees/for-route` — Get priority fees for a route
- Action: `read` · MCP tool: `order-os.get_priority_fees_for_route`
- Priority-fee guidance tuned to the specific accounts your route touches.

### `GET /v1/order-os/block-stats` — Get block stats
- Action: `read` · MCP tool: `order-os.get_block_stats`
- Recent block production / fee statistics.

### `GET /v1/order-os/program-id-to-label` — Map program ids to labels
- Action: `read` · MCP tool: `order-os.get_program_labels`
- A map from on-chain program ids to human-readable protocol labels.

### `GET /v1/order-os/config` — Get an app's policy
- Action: `read` · MCP tool: `order-os.get_config`
- The effective policy an app enforces, with every default filled in and tagged with its org, app, and name. Pass `?app=app_…` to name an app (404 if it isn't yours or is archived); omit it for your default app. Supports ETag / If-None-Match for 304 caching.
- Query param `app` (string) — App id (app_…) or app name whose effective policy to read. Omit for the workspace's default app.
- Response (JSON):
  - `org_id` — string
  - `app_id` — string
  - `app_name` — string
  - `revision` — integer

### `GET /v1/order-os/meta` — Routing catalog and defaults
- Action: `read` · MCP tool: `order-os.get_meta`
- Platform constants the policy editor loads instead of hardcoding them: the routing catalog its picker draws from, plus the default policy it diffs your overrides against. No app or org context.
- Response (JSON):
  - `dexes[]` — object[]
    - `value` — string
    - `label` — string
  - `defaults` — object
    - `rate_limit_rps` — integer
    - `allowed_ips[]` — string[]
    - `blocked_ips[]` — string[]
    - `allowed_origins[]` — string[]
    - `allowed_countries[]` — string[]
    - `blocked_countries[]` — string[]
    - `allowed_user_agents[]` — string[]
    - `blocked_user_agents[]` — string[]
    - `allowed_endpoints[]` — string[] | null
    - `denied_endpoints[]` — string[] | null
    - `simulation_enabled` — boolean
    - `priority_fee_enabled` — boolean
    - `wrap_unwrap_enabled` — boolean
    - `pools_enabled` — boolean
    - `program_labels_enabled` — boolean
    - `multi_split_enabled` — boolean
    - `jit_enabled` — boolean
    - `enforce_jit` — boolean
    - `allow_jit_override` — boolean
    - `jit_allocation_denominator` — integer | null
    - `platform_fee_bps` — integer
    - `fee_account` — string | null
    - `tracking_account` — string | null
    - `enforce_platform_fee` — boolean
    - `allow_platform_fee_override` — boolean
    - `wrap_unwrap_fee_bps` — integer
    - `wrap_unwrap_fee_owner` — string | null — System-owned wallet receiving unwrap fees as SOL and wrap fees through its operator-provisioned canonical wSOL ATA
    - `max_wrap_amount_lamports` — integer | null
    - `max_unwrap_amount_lamports` — integer | null
    - `exclude_dexes[]` — string[]
    - `only_direct_routes` — boolean
    - `max_accounts` — integer | null
    - `enforce_dex_restrictions` — boolean
    - `allow_dex_override` — boolean
    - `default_slippage_bps` — integer | null
    - `max_slippage_bps` — integer | null
    - `min_slippage_bps` — integer | null
    - `enforce_slippage` — boolean
    - `allow_slippage_override` — boolean
    - `default_compute_units` — integer | null
    - `max_compute_units` — integer | null
    - `min_compute_units` — integer | null
    - `enforce_compute_units` — boolean
    - `allow_compute_units_override` — boolean
    - `default_max_hops` — integer | null
    - `max_hops` — integer | null
    - `enforce_max_hops` — boolean
    - `allow_max_hops_override` — boolean
    - `prefer_liquid_dexes` — boolean
    - `default_route_splits` — integer | null
    - `max_route_splits` — integer | null
    - `enforce_route_splits` — boolean
    - `allow_route_splits_override` — boolean
    - `force_algorithm` — string | null
    - `algorithm_mode` — string | null
    - `auction_algorithms[]` — string[] | null
    - `enforce_algorithm` — boolean
    - `allow_algorithm_override` — boolean
    - `default_auction_timeout_ms` — integer | null
    - `auction_timeout_ms` — integer | null
    - `max_auction_timeout_ms` — integer | null
    - `min_auction_timeout_ms` — integer | null
    - `enforce_auction_timeout` — boolean
    - `allow_auction_timeout_override` — boolean
    - `allowed_swap_modes[]` — string[] | null
    - `default_wrap_and_unwrap_sol` — boolean
    - `allow_wrap_and_unwrap_sol_override` — boolean
    - `ws_enabled` — boolean
    - `ws_denied_topics[]` — string[] | null
    - `allowed_tokens[]` — string[] | null
    - `blocked_tokens[]` — string[]

### `GET /v1/order-os/apps` — List apps
- Action: `read` · MCP tool: `order-os.list_apps`
- Every non-archived app in the workspace (default first). The default app is auto-created on first need.
- Response (JSON):
  - `apps[]` — object[]
    - `id` — string
    - `name` — string
    - `is_default` — boolean
    - `revision` — integer
    - `etag` — string
    - `created_at` — string
    - `updated_at` — string
    - `updated_by` — string

### `POST /v1/order-os/apps` — Create an app
- Action: `write` · MCP tool: `order-os.create_app`
- Creates a named app in your workspace, starting from the platform default policy. Any of your keys can use any of your apps; name one on X-K256-App when you call the data plane. Duplicate names return 409.
- Request body (JSON, required):
  - `name` — string (required) — Human-readable app name (1–120 chars). The new app starts from the platform default policy.
- Response (JSON):
  - `id` — string
  - `name` — string
  - `is_default` — boolean
  - `revision` — integer
  - `etag` — string
  - `created_at` — string
  - `updated_at` — string
  - `updated_by` — string
  - `config` — object
    - `rate_limit_rps` — integer
    - `allowed_ips[]` — string[]
    - `blocked_ips[]` — string[]
    - `allowed_origins[]` — string[]
    - `allowed_countries[]` — string[]
    - `blocked_countries[]` — string[]
    - `allowed_user_agents[]` — string[]
    - `blocked_user_agents[]` — string[]
    - `allowed_endpoints[]` — string[] | null
    - `denied_endpoints[]` — string[] | null
    - `simulation_enabled` — boolean
    - `priority_fee_enabled` — boolean
    - `wrap_unwrap_enabled` — boolean
    - `pools_enabled` — boolean
    - `program_labels_enabled` — boolean
    - `multi_split_enabled` — boolean
    - `jit_enabled` — boolean
    - `enforce_jit` — boolean
    - `allow_jit_override` — boolean
    - `jit_allocation_denominator` — integer | null
    - `platform_fee_bps` — integer
    - `fee_account` — string | null
    - `tracking_account` — string | null
    - `enforce_platform_fee` — boolean
    - `allow_platform_fee_override` — boolean
    - `wrap_unwrap_fee_bps` — integer
    - `wrap_unwrap_fee_owner` — string | null — System-owned wallet receiving unwrap fees as SOL and wrap fees through its operator-provisioned canonical wSOL ATA
    - `max_wrap_amount_lamports` — integer | null
    - `max_unwrap_amount_lamports` — integer | null
    - `exclude_dexes[]` — string[]
    - `only_direct_routes` — boolean
    - `max_accounts` — integer | null
    - `enforce_dex_restrictions` — boolean
    - `allow_dex_override` — boolean
    - `default_slippage_bps` — integer | null
    - `max_slippage_bps` — integer | null
    - `min_slippage_bps` — integer | null
    - `enforce_slippage` — boolean
    - `allow_slippage_override` — boolean
    - `default_compute_units` — integer | null
    - `max_compute_units` — integer | null
    - `min_compute_units` — integer | null
    - `enforce_compute_units` — boolean
    - `allow_compute_units_override` — boolean
    - `default_max_hops` — integer | null
    - `max_hops` — integer | null
    - `enforce_max_hops` — boolean
    - `allow_max_hops_override` — boolean
    - `prefer_liquid_dexes` — boolean
    - `default_route_splits` — integer | null
    - `max_route_splits` — integer | null
    - `enforce_route_splits` — boolean
    - `allow_route_splits_override` — boolean
    - `force_algorithm` — string | null
    - `algorithm_mode` — string | null
    - `auction_algorithms[]` — string[] | null
    - `enforce_algorithm` — boolean
    - `allow_algorithm_override` — boolean
    - `default_auction_timeout_ms` — integer | null
    - `auction_timeout_ms` — integer | null
    - `max_auction_timeout_ms` — integer | null
    - `min_auction_timeout_ms` — integer | null
    - `enforce_auction_timeout` — boolean
    - `allow_auction_timeout_override` — boolean
    - `allowed_swap_modes[]` — string[] | null
    - `default_wrap_and_unwrap_sol` — boolean
    - `allow_wrap_and_unwrap_sol_override` — boolean
    - `ws_enabled` — boolean
    - `ws_denied_topics[]` — string[] | null
    - `allowed_tokens[]` — string[] | null
    - `blocked_tokens[]` — string[]

### `GET /v1/order-os/apps/{app_id}` — Get an app
- Action: `read` · MCP tool: `order-os.get_app`
- An app's identity and its effective policy. Returns 404 when archived.
- Path param `app_id` (string, required) — The app's id (app_…) — from `list_apps`. Every workspace has an auto-created default app.
- Response (JSON):
  - `id` — string
  - `name` — string
  - `is_default` — boolean
  - `revision` — integer
  - `etag` — string
  - `created_at` — string
  - `updated_at` — string
  - `updated_by` — string
  - `config` — object
    - `rate_limit_rps` — integer
    - `allowed_ips[]` — string[]
    - `blocked_ips[]` — string[]
    - `allowed_origins[]` — string[]
    - `allowed_countries[]` — string[]
    - `blocked_countries[]` — string[]
    - `allowed_user_agents[]` — string[]
    - `blocked_user_agents[]` — string[]
    - `allowed_endpoints[]` — string[] | null
    - `denied_endpoints[]` — string[] | null
    - `simulation_enabled` — boolean
    - `priority_fee_enabled` — boolean
    - `wrap_unwrap_enabled` — boolean
    - `pools_enabled` — boolean
    - `program_labels_enabled` — boolean
    - `multi_split_enabled` — boolean
    - `jit_enabled` — boolean
    - `enforce_jit` — boolean
    - `allow_jit_override` — boolean
    - `jit_allocation_denominator` — integer | null
    - `platform_fee_bps` — integer
    - `fee_account` — string | null
    - `tracking_account` — string | null
    - `enforce_platform_fee` — boolean
    - `allow_platform_fee_override` — boolean
    - `wrap_unwrap_fee_bps` — integer
    - `wrap_unwrap_fee_owner` — string | null — System-owned wallet receiving unwrap fees as SOL and wrap fees through its operator-provisioned canonical wSOL ATA
    - `max_wrap_amount_lamports` — integer | null
    - `max_unwrap_amount_lamports` — integer | null
    - `exclude_dexes[]` — string[]
    - `only_direct_routes` — boolean
    - `max_accounts` — integer | null
    - `enforce_dex_restrictions` — boolean
    - `allow_dex_override` — boolean
    - `default_slippage_bps` — integer | null
    - `max_slippage_bps` — integer | null
    - `min_slippage_bps` — integer | null
    - `enforce_slippage` — boolean
    - `allow_slippage_override` — boolean
    - `default_compute_units` — integer | null
    - `max_compute_units` — integer | null
    - `min_compute_units` — integer | null
    - `enforce_compute_units` — boolean
    - `allow_compute_units_override` — boolean
    - `default_max_hops` — integer | null
    - `max_hops` — integer | null
    - `enforce_max_hops` — boolean
    - `allow_max_hops_override` — boolean
    - `prefer_liquid_dexes` — boolean
    - `default_route_splits` — integer | null
    - `max_route_splits` — integer | null
    - `enforce_route_splits` — boolean
    - `allow_route_splits_override` — boolean
    - `force_algorithm` — string | null
    - `algorithm_mode` — string | null
    - `auction_algorithms[]` — string[] | null
    - `enforce_algorithm` — boolean
    - `allow_algorithm_override` — boolean
    - `default_auction_timeout_ms` — integer | null
    - `auction_timeout_ms` — integer | null
    - `max_auction_timeout_ms` — integer | null
    - `min_auction_timeout_ms` — integer | null
    - `enforce_auction_timeout` — boolean
    - `allow_auction_timeout_override` — boolean
    - `allowed_swap_modes[]` — string[] | null
    - `default_wrap_and_unwrap_sol` — boolean
    - `allow_wrap_and_unwrap_sol_override` — boolean
    - `ws_enabled` — boolean
    - `ws_denied_topics[]` — string[] | null
    - `allowed_tokens[]` — string[] | null
    - `blocked_tokens[]` — string[]

### `PATCH /v1/order-os/apps/{app_id}` — Rename an app
- Action: `write` · MCP tool: `order-os.rename_app`
- Renames a non-archived app. Duplicate names are 409.
- Path param `app_id` (string, required) — The app's id (app_…) — from `list_apps`. Every workspace has an auto-created default app.
- Request body (JSON, required):
  - `name` — string (required) — The new app name (1–120 chars). Rename only — the policy document is untouched.
- Response (JSON):
  - `id` — string
  - `name` — string
  - `is_default` — boolean
  - `revision` — integer
  - `etag` — string
  - `created_at` — string
  - `updated_at` — string
  - `updated_by` — string
  - `config` — object
    - `rate_limit_rps` — integer
    - `allowed_ips[]` — string[]
    - `blocked_ips[]` — string[]
    - `allowed_origins[]` — string[]
    - `allowed_countries[]` — string[]
    - `blocked_countries[]` — string[]
    - `allowed_user_agents[]` — string[]
    - `blocked_user_agents[]` — string[]
    - `allowed_endpoints[]` — string[] | null
    - `denied_endpoints[]` — string[] | null
    - `simulation_enabled` — boolean
    - `priority_fee_enabled` — boolean
    - `wrap_unwrap_enabled` — boolean
    - `pools_enabled` — boolean
    - `program_labels_enabled` — boolean
    - `multi_split_enabled` — boolean
    - `jit_enabled` — boolean
    - `enforce_jit` — boolean
    - `allow_jit_override` — boolean
    - `jit_allocation_denominator` — integer | null
    - `platform_fee_bps` — integer
    - `fee_account` — string | null
    - `tracking_account` — string | null
    - `enforce_platform_fee` — boolean
    - `allow_platform_fee_override` — boolean
    - `wrap_unwrap_fee_bps` — integer
    - `wrap_unwrap_fee_owner` — string | null — System-owned wallet receiving unwrap fees as SOL and wrap fees through its operator-provisioned canonical wSOL ATA
    - `max_wrap_amount_lamports` — integer | null
    - `max_unwrap_amount_lamports` — integer | null
    - `exclude_dexes[]` — string[]
    - `only_direct_routes` — boolean
    - `max_accounts` — integer | null
    - `enforce_dex_restrictions` — boolean
    - `allow_dex_override` — boolean
    - `default_slippage_bps` — integer | null
    - `max_slippage_bps` — integer | null
    - `min_slippage_bps` — integer | null
    - `enforce_slippage` — boolean
    - `allow_slippage_override` — boolean
    - `default_compute_units` — integer | null
    - `max_compute_units` — integer | null
    - `min_compute_units` — integer | null
    - `enforce_compute_units` — boolean
    - `allow_compute_units_override` — boolean
    - `default_max_hops` — integer | null
    - `max_hops` — integer | null
    - `enforce_max_hops` — boolean
    - `allow_max_hops_override` — boolean
    - `prefer_liquid_dexes` — boolean
    - `default_route_splits` — integer | null
    - `max_route_splits` — integer | null
    - `enforce_route_splits` — boolean
    - `allow_route_splits_override` — boolean
    - `force_algorithm` — string | null
    - `algorithm_mode` — string | null
    - `auction_algorithms[]` — string[] | null
    - `enforce_algorithm` — boolean
    - `allow_algorithm_override` — boolean
    - `default_auction_timeout_ms` — integer | null
    - `auction_timeout_ms` — integer | null
    - `max_auction_timeout_ms` — integer | null
    - `min_auction_timeout_ms` — integer | null
    - `enforce_auction_timeout` — boolean
    - `allow_auction_timeout_override` — boolean
    - `allowed_swap_modes[]` — string[] | null
    - `default_wrap_and_unwrap_sol` — boolean
    - `allow_wrap_and_unwrap_sol_override` — boolean
    - `ws_enabled` — boolean
    - `ws_denied_topics[]` — string[] | null
    - `allowed_tokens[]` — string[] | null
    - `blocked_tokens[]` — string[]

### `DELETE /v1/order-os/apps/{app_id}` — Archive an app
- Action: `write` · MCP tool: `order-os.archive_app`
- Archives a non-default app (the default app can't be archived — 409). After that, a data-plane call naming it returns 404 app_not_found.
- Path param `app_id` (string, required) — The app's id (app_…) — from `list_apps`. Every workspace has an auto-created default app.
- Response (JSON):
  - `id` — string
  - `name` — string
  - `is_default` — boolean
  - `revision` — integer
  - `etag` — string
  - `created_at` — string
  - `updated_at` — string
  - `updated_by` — string

### `PUT /v1/order-os/apps/{app_id}/config` — Update an app's policy
- Action: `write` · MCP tool: `order-os.update_app_config`
- Updates an app's policy as a new revision (previous ones are kept). Unknown fields are rejected, so a typo fails loudly instead of being silently dropped.
- Path param `app_id` (string, required) — The app's id (app_…) — from `list_apps`. Every workspace has an auto-created default app.
- Request body (JSON, required):
  - `config` — object (required) — The complete policy document to store — replaces the app's config wholesale and bumps its revision. Read the current one with `get_app` first and edit from it.
  - `expected_revision` — integer — Optimistic-concurrency guard: the revision this edit was based on. If it is no longer current the update answers 409 config_revision_conflict instead of overwriting a concurrent editor. Omit for an unconditional write.
- Response (JSON):
  - `id` — string
  - `name` — string
  - `is_default` — boolean
  - `revision` — integer
  - `etag` — string
  - `created_at` — string
  - `updated_at` — string
  - `updated_by` — string
  - `config` — object
    - `rate_limit_rps` — integer
    - `allowed_ips[]` — string[]
    - `blocked_ips[]` — string[]
    - `allowed_origins[]` — string[]
    - `allowed_countries[]` — string[]
    - `blocked_countries[]` — string[]
    - `allowed_user_agents[]` — string[]
    - `blocked_user_agents[]` — string[]
    - `allowed_endpoints[]` — string[] | null
    - `denied_endpoints[]` — string[] | null
    - `simulation_enabled` — boolean
    - `priority_fee_enabled` — boolean
    - `wrap_unwrap_enabled` — boolean
    - `pools_enabled` — boolean
    - `program_labels_enabled` — boolean
    - `multi_split_enabled` — boolean
    - `jit_enabled` — boolean
    - `enforce_jit` — boolean
    - `allow_jit_override` — boolean
    - `jit_allocation_denominator` — integer | null
    - `platform_fee_bps` — integer
    - `fee_account` — string | null
    - `tracking_account` — string | null
    - `enforce_platform_fee` — boolean
    - `allow_platform_fee_override` — boolean
    - `wrap_unwrap_fee_bps` — integer
    - `wrap_unwrap_fee_owner` — string | null — System-owned wallet receiving unwrap fees as SOL and wrap fees through its operator-provisioned canonical wSOL ATA
    - `max_wrap_amount_lamports` — integer | null
    - `max_unwrap_amount_lamports` — integer | null
    - `exclude_dexes[]` — string[]
    - `only_direct_routes` — boolean
    - `max_accounts` — integer | null
    - `enforce_dex_restrictions` — boolean
    - `allow_dex_override` — boolean
    - `default_slippage_bps` — integer | null
    - `max_slippage_bps` — integer | null
    - `min_slippage_bps` — integer | null
    - `enforce_slippage` — boolean
    - `allow_slippage_override` — boolean
    - `default_compute_units` — integer | null
    - `max_compute_units` — integer | null
    - `min_compute_units` — integer | null
    - `enforce_compute_units` — boolean
    - `allow_compute_units_override` — boolean
    - `default_max_hops` — integer | null
    - `max_hops` — integer | null
    - `enforce_max_hops` — boolean
    - `allow_max_hops_override` — boolean
    - `prefer_liquid_dexes` — boolean
    - `default_route_splits` — integer | null
    - `max_route_splits` — integer | null
    - `enforce_route_splits` — boolean
    - `allow_route_splits_override` — boolean
    - `force_algorithm` — string | null
    - `algorithm_mode` — string | null
    - `auction_algorithms[]` — string[] | null
    - `enforce_algorithm` — boolean
    - `allow_algorithm_override` — boolean
    - `default_auction_timeout_ms` — integer | null
    - `auction_timeout_ms` — integer | null
    - `max_auction_timeout_ms` — integer | null
    - `min_auction_timeout_ms` — integer | null
    - `enforce_auction_timeout` — boolean
    - `allow_auction_timeout_override` — boolean
    - `allowed_swap_modes[]` — string[] | null
    - `default_wrap_and_unwrap_sol` — boolean
    - `allow_wrap_and_unwrap_sol_override` — boolean
    - `ws_enabled` — boolean
    - `ws_denied_topics[]` — string[] | null
    - `allowed_tokens[]` — string[] | null
    - `blocked_tokens[]` — string[]

### `DELETE /v1/order-os/apps/{app_id}/config` — Reset an app's policy
- Action: `write` · MCP tool: `order-os.reset_app_config`
- Resets an app to the platform default policy as a new revision; history is preserved.
- Path param `app_id` (string, required) — The app's id (app_…) — from `list_apps`. Every workspace has an auto-created default app.
- Response (JSON):
  - `id` — string
  - `name` — string
  - `is_default` — boolean
  - `revision` — integer
  - `etag` — string
  - `created_at` — string
  - `updated_at` — string
  - `updated_by` — string
  - `config` — object
    - `rate_limit_rps` — integer
    - `allowed_ips[]` — string[]
    - `blocked_ips[]` — string[]
    - `allowed_origins[]` — string[]
    - `allowed_countries[]` — string[]
    - `blocked_countries[]` — string[]
    - `allowed_user_agents[]` — string[]
    - `blocked_user_agents[]` — string[]
    - `allowed_endpoints[]` — string[] | null
    - `denied_endpoints[]` — string[] | null
    - `simulation_enabled` — boolean
    - `priority_fee_enabled` — boolean
    - `wrap_unwrap_enabled` — boolean
    - `pools_enabled` — boolean
    - `program_labels_enabled` — boolean
    - `multi_split_enabled` — boolean
    - `jit_enabled` — boolean
    - `enforce_jit` — boolean
    - `allow_jit_override` — boolean
    - `jit_allocation_denominator` — integer | null
    - `platform_fee_bps` — integer
    - `fee_account` — string | null
    - `tracking_account` — string | null
    - `enforce_platform_fee` — boolean
    - `allow_platform_fee_override` — boolean
    - `wrap_unwrap_fee_bps` — integer
    - `wrap_unwrap_fee_owner` — string | null — System-owned wallet receiving unwrap fees as SOL and wrap fees through its operator-provisioned canonical wSOL ATA
    - `max_wrap_amount_lamports` — integer | null
    - `max_unwrap_amount_lamports` — integer | null
    - `exclude_dexes[]` — string[]
    - `only_direct_routes` — boolean
    - `max_accounts` — integer | null
    - `enforce_dex_restrictions` — boolean
    - `allow_dex_override` — boolean
    - `default_slippage_bps` — integer | null
    - `max_slippage_bps` — integer | null
    - `min_slippage_bps` — integer | null
    - `enforce_slippage` — boolean
    - `allow_slippage_override` — boolean
    - `default_compute_units` — integer | null
    - `max_compute_units` — integer | null
    - `min_compute_units` — integer | null
    - `enforce_compute_units` — boolean
    - `allow_compute_units_override` — boolean
    - `default_max_hops` — integer | null
    - `max_hops` — integer | null
    - `enforce_max_hops` — boolean
    - `allow_max_hops_override` — boolean
    - `prefer_liquid_dexes` — boolean
    - `default_route_splits` — integer | null
    - `max_route_splits` — integer | null
    - `enforce_route_splits` — boolean
    - `allow_route_splits_override` — boolean
    - `force_algorithm` — string | null
    - `algorithm_mode` — string | null
    - `auction_algorithms[]` — string[] | null
    - `enforce_algorithm` — boolean
    - `allow_algorithm_override` — boolean
    - `default_auction_timeout_ms` — integer | null
    - `auction_timeout_ms` — integer | null
    - `max_auction_timeout_ms` — integer | null
    - `min_auction_timeout_ms` — integer | null
    - `enforce_auction_timeout` — boolean
    - `allow_auction_timeout_override` — boolean
    - `allowed_swap_modes[]` — string[] | null
    - `default_wrap_and_unwrap_sol` — boolean
    - `allow_wrap_and_unwrap_sol_override` — boolean
    - `ws_enabled` — boolean
    - `ws_denied_topics[]` — string[] | null
    - `allowed_tokens[]` — string[] | null
    - `blocked_tokens[]` — string[]

### `GET /v1/order-os/apps/{app_id}/revisions` — List an app's policy history
- Action: `read` · MCP tool: `order-os.list_app_revisions`
- An app's policy revisions, newest first — each with who changed it, when, and the full document. Keyset-paginated.
- Path param `app_id` (string, required) — The app's id (app_…) — from `list_apps`. Every workspace has an auto-created default app.
- Query param `limit` (integer) — Page size, 1–200. Defaults to 50. Revisions come newest first.
- Query param `cursor` (integer) — The previous page's `nextCursor` — pass it back for the next (older) page.
- Response (JSON):
  - `revisions[]` — object[]
    - `revision` — integer
    - `etag` — string
    - `updated_by` — string
    - `updated_at` — string
    - `config` — object
      - `rate_limit_rps` — integer
      - `allowed_ips[]` — string[]
      - `blocked_ips[]` — string[]
      - `allowed_origins[]` — string[]
      - `allowed_countries[]` — string[]
      - `blocked_countries[]` — string[]
      - `allowed_user_agents[]` — string[]
      - `blocked_user_agents[]` — string[]
      - `allowed_endpoints[]` — string[] | null
      - `denied_endpoints[]` — string[] | null
      - `simulation_enabled` — boolean
      - `priority_fee_enabled` — boolean
      - `wrap_unwrap_enabled` — boolean
      - `pools_enabled` — boolean
      - `program_labels_enabled` — boolean
      - `multi_split_enabled` — boolean
      - `jit_enabled` — boolean
      - `enforce_jit` — boolean
      - `allow_jit_override` — boolean
      - `jit_allocation_denominator` — integer | null
      - `platform_fee_bps` — integer
      - `fee_account` — string | null
      - `tracking_account` — string | null
      - `enforce_platform_fee` — boolean
      - `allow_platform_fee_override` — boolean
      - `wrap_unwrap_fee_bps` — integer
      - `wrap_unwrap_fee_owner` — string | null — System-owned wallet receiving unwrap fees as SOL and wrap fees through its operator-provisioned canonical wSOL ATA
      - `max_wrap_amount_lamports` — integer | null
      - `max_unwrap_amount_lamports` — integer | null
      - `exclude_dexes[]` — string[]
      - `only_direct_routes` — boolean
      - `max_accounts` — integer | null
      - `enforce_dex_restrictions` — boolean
      - `allow_dex_override` — boolean
      - `default_slippage_bps` — integer | null
      - `max_slippage_bps` — integer | null
      - `min_slippage_bps` — integer | null
      - `enforce_slippage` — boolean
      - `allow_slippage_override` — boolean
      - `default_compute_units` — integer | null
      - `max_compute_units` — integer | null
      - `min_compute_units` — integer | null
      - `enforce_compute_units` — boolean
      - `allow_compute_units_override` — boolean
      - `default_max_hops` — integer | null
      - `max_hops` — integer | null
      - `enforce_max_hops` — boolean
      - `allow_max_hops_override` — boolean
      - `prefer_liquid_dexes` — boolean
      - `default_route_splits` — integer | null
      - `max_route_splits` — integer | null
      - `enforce_route_splits` — boolean
      - `allow_route_splits_override` — boolean
      - `force_algorithm` — string | null
      - `algorithm_mode` — string | null
      - `auction_algorithms[]` — string[] | null
      - `enforce_algorithm` — boolean
      - `allow_algorithm_override` — boolean
      - `default_auction_timeout_ms` — integer | null
      - `auction_timeout_ms` — integer | null
      - `max_auction_timeout_ms` — integer | null
      - `min_auction_timeout_ms` — integer | null
      - `enforce_auction_timeout` — boolean
      - `allow_auction_timeout_override` — boolean
      - `allowed_swap_modes[]` — string[] | null
      - `default_wrap_and_unwrap_sol` — boolean
      - `allow_wrap_and_unwrap_sol_override` — boolean
      - `ws_enabled` — boolean
      - `ws_denied_topics[]` — string[] | null
      - `allowed_tokens[]` — string[] | null
      - `blocked_tokens[]` — string[]
  - `nextCursor` — integer | null

### `POST /v1/order-os/apps/{app_id}/rollback` — Roll back an app's policy
- Action: `write` · MCP tool: `order-os.rollback_app_config`
- Restores a past revision by writing it as a new revision — history is append-only, never rewritten. Returns 404 if the revision doesn't exist.
- Path param `app_id` (string, required) — The app's id (app_…) — from `list_apps`. Every workspace has an auto-created default app.
- Request body (JSON, required):
  - `revision` — integer (required) — The historical revision number to restore, from `list_app_revisions` (1 = the first stored config). The restore is written as a NEW head revision.
- Response (JSON):
  - `id` — string
  - `name` — string
  - `is_default` — boolean
  - `revision` — integer
  - `etag` — string
  - `created_at` — string
  - `updated_at` — string
  - `updated_by` — string
  - `config` — object
    - `rate_limit_rps` — integer
    - `allowed_ips[]` — string[]
    - `blocked_ips[]` — string[]
    - `allowed_origins[]` — string[]
    - `allowed_countries[]` — string[]
    - `blocked_countries[]` — string[]
    - `allowed_user_agents[]` — string[]
    - `blocked_user_agents[]` — string[]
    - `allowed_endpoints[]` — string[] | null
    - `denied_endpoints[]` — string[] | null
    - `simulation_enabled` — boolean
    - `priority_fee_enabled` — boolean
    - `wrap_unwrap_enabled` — boolean
    - `pools_enabled` — boolean
    - `program_labels_enabled` — boolean
    - `multi_split_enabled` — boolean
    - `jit_enabled` — boolean
    - `enforce_jit` — boolean
    - `allow_jit_override` — boolean
    - `jit_allocation_denominator` — integer | null
    - `platform_fee_bps` — integer
    - `fee_account` — string | null
    - `tracking_account` — string | null
    - `enforce_platform_fee` — boolean
    - `allow_platform_fee_override` — boolean
    - `wrap_unwrap_fee_bps` — integer
    - `wrap_unwrap_fee_owner` — string | null — System-owned wallet receiving unwrap fees as SOL and wrap fees through its operator-provisioned canonical wSOL ATA
    - `max_wrap_amount_lamports` — integer | null
    - `max_unwrap_amount_lamports` — integer | null
    - `exclude_dexes[]` — string[]
    - `only_direct_routes` — boolean
    - `max_accounts` — integer | null
    - `enforce_dex_restrictions` — boolean
    - `allow_dex_override` — boolean
    - `default_slippage_bps` — integer | null
    - `max_slippage_bps` — integer | null
    - `min_slippage_bps` — integer | null
    - `enforce_slippage` — boolean
    - `allow_slippage_override` — boolean
    - `default_compute_units` — integer | null
    - `max_compute_units` — integer | null
    - `min_compute_units` — integer | null
    - `enforce_compute_units` — boolean
    - `allow_compute_units_override` — boolean
    - `default_max_hops` — integer | null
    - `max_hops` — integer | null
    - `enforce_max_hops` — boolean
    - `allow_max_hops_override` — boolean
    - `prefer_liquid_dexes` — boolean
    - `default_route_splits` — integer | null
    - `max_route_splits` — integer | null
    - `enforce_route_splits` — boolean
    - `allow_route_splits_override` — boolean
    - `force_algorithm` — string | null
    - `algorithm_mode` — string | null
    - `auction_algorithms[]` — string[] | null
    - `enforce_algorithm` — boolean
    - `allow_algorithm_override` — boolean
    - `default_auction_timeout_ms` — integer | null
    - `auction_timeout_ms` — integer | null
    - `max_auction_timeout_ms` — integer | null
    - `min_auction_timeout_ms` — integer | null
    - `enforce_auction_timeout` — boolean
    - `allow_auction_timeout_override` — boolean
    - `allowed_swap_modes[]` — string[] | null
    - `default_wrap_and_unwrap_sol` — boolean
    - `allow_wrap_and_unwrap_sol_override` — boolean
    - `ws_enabled` — boolean
    - `ws_denied_topics[]` — string[] | null
    - `allowed_tokens[]` — string[] | null
    - `blocked_tokens[]` — string[]

### `GET /v1/order-os/nodes` — List linked nodes
- Action: `read` · MCP tool: `order-os.list_nodes`
- Every self-hosted node linked to your workspace; tokens are never shown.
- Response (JSON):
  - `nodes[]` — object[]
    - `id` — string
    - `name` — string
    - `created_at` — string
    - `revoked_at` — string | null
    - `telemetry` — object | null
      - `last_seen` — string | null
      - `active` — boolean
      - `requests_24h` — number
      - `errors_24h` — number

### `GET /v1/order-os/analytics/overview` — Analytics overview (KPIs)
- Action: `read` · MCP tool: `order-os.analytics_overview`
- Quote and swap volume, conversion and success rate, average quote/swap latency, unique keys, and p50/p99 latency for the window.
- Query param `range` ("1h" | "6h" | "24h" | "7d" | "30d" | "90d") — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
- Query param `from` (string) — Window start as an ISO-8601 timestamp. Pair with `to` for an exact custom window; when set it overrides `range`.
- Query param `to` (string) — Window end as an ISO-8601 timestamp (defaults to now when only `from` is given). Overrides `range` when set.
- Query param `app_id` (string) — Scope the metrics to one policy app (app_…). Omit to aggregate across every app in the workspace.
- Query param `endpoint` (string) — Scope the metrics to one API endpoint path (e.g. /quote). Omit to include all endpoints.
- Response (JSON):
  - `total_quotes` — number
  - `total_swaps` — number
  - `conversion_rate` — number
  - `success_rate` — number
  - `avg_quote_latency_ms` — number
  - `avg_swap_latency_ms` — number
  - `unique_keys` — number
  - `p50_latency_ms` — number
  - `p99_latency_ms` — number
  - `deltas` — object | null
    - `total_quotes` — number | null
    - `total_swaps` — number | null
    - `success_rate` — number | null
    - `avg_quote_latency_ms` — number | null
    - `p50_latency_ms` — number | null
    - `p99_latency_ms` — number | null
  - `range` — "1h" | "6h" | "24h" | "7d" | "30d" | "90d" — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
  - `degraded` — boolean

### `GET /v1/order-os/analytics/timeseries` — Analytics timeseries
- Action: `read` · MCP tool: `order-os.analytics_timeseries`
- Bucketed requests/errors/avg-latency (hour buckets ≤7d, day buckets beyond).
- Query param `range` ("1h" | "6h" | "24h" | "7d" | "30d" | "90d") — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
- Query param `from` (string) — Window start as an ISO-8601 timestamp. Pair with `to` for an exact custom window; when set it overrides `range`.
- Query param `to` (string) — Window end as an ISO-8601 timestamp (defaults to now when only `from` is given). Overrides `range` when set.
- Query param `app_id` (string) — Scope the metrics to one policy app (app_…). Omit to aggregate across every app in the workspace.
- Query param `endpoint` (string) — Scope the metrics to one API endpoint path (e.g. /quote). Omit to include all endpoints.
- Response (JSON):
  - `points[]` — object[]
    - `timestamp` — string
    - `requests` — number
    - `errors` — number
    - `avg_latency_ms` — number
  - `range` — "1h" | "6h" | "24h" | "7d" | "30d" | "90d" — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
  - `degraded` — boolean

### `GET /v1/order-os/analytics/status-breakdown` — Analytics status breakdown
- Action: `read` · MCP tool: `order-os.analytics_status_breakdown`
- 2xx / 4xx / 5xx counts for the window.
- Query param `range` ("1h" | "6h" | "24h" | "7d" | "30d" | "90d") — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
- Query param `from` (string) — Window start as an ISO-8601 timestamp. Pair with `to` for an exact custom window; when set it overrides `range`.
- Query param `to` (string) — Window end as an ISO-8601 timestamp (defaults to now when only `from` is given). Overrides `range` when set.
- Query param `app_id` (string) — Scope the metrics to one policy app (app_…). Omit to aggregate across every app in the workspace.
- Query param `endpoint` (string) — Scope the metrics to one API endpoint path (e.g. /quote). Omit to include all endpoints.
- Response (JSON):
  - `total` — number
  - `success` — number
  - `client_error` — number
  - `server_error` — number
  - `range` — "1h" | "6h" | "24h" | "7d" | "30d" | "90d" — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
  - `degraded` — boolean

### `GET /v1/order-os/analytics/latency` — Analytics latency hotspots
- Action: `read` · MCP tool: `order-os.analytics_latency`
- p50/p90/p99 latency and error rate by endpoint.
- Query param `range` ("1h" | "6h" | "24h" | "7d" | "30d" | "90d") — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
- Query param `from` (string) — Window start as an ISO-8601 timestamp. Pair with `to` for an exact custom window; when set it overrides `range`.
- Query param `to` (string) — Window end as an ISO-8601 timestamp (defaults to now when only `from` is given). Overrides `range` when set.
- Query param `app_id` (string) — Scope the metrics to one policy app (app_…). Omit to aggregate across every app in the workspace.
- Query param `endpoint` (string) — Scope the metrics to one API endpoint path (e.g. /quote). Omit to include all endpoints.
- Response (JSON):
  - `endpoints[]` — object[]
    - `endpoint` — string
    - `requests` — number
    - `p50_ms` — number
    - `p90_ms` — number
    - `p99_ms` — number
    - `error_rate` — number
  - `range` — "1h" | "6h" | "24h" | "7d" | "30d" | "90d" — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
  - `degraded` — boolean

### `GET /v1/order-os/analytics/endpoints` — Analytics top endpoints
- Action: `read` · MCP tool: `order-os.analytics_endpoints`
- Top endpoints by count, with error_rate and p99 latency.
- Query param `range` ("1h" | "6h" | "24h" | "7d" | "30d" | "90d") — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
- Query param `from` (string) — Window start as an ISO-8601 timestamp. Pair with `to` for an exact custom window; when set it overrides `range`.
- Query param `to` (string) — Window end as an ISO-8601 timestamp (defaults to now when only `from` is given). Overrides `range` when set.
- Query param `app_id` (string) — Scope the metrics to one policy app (app_…). Omit to aggregate across every app in the workspace.
- Query param `endpoint` (string) — Scope the metrics to one API endpoint path (e.g. /quote). Omit to include all endpoints.
- Response (JSON):
  - `endpoints[]` — object[]
    - `endpoint` — string
    - `count` — number
    - `error_rate` — number
    - `p99_ms` — number
  - `range` — "1h" | "6h" | "24h" | "7d" | "30d" | "90d" — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
  - `degraded` — boolean

### `GET /v1/order-os/analytics/errors` — Analytics top error codes
- Action: `read` · MCP tool: `order-os.analytics_errors`
- Top error codes for the window, each with how many times it occurred and how many flows it affected.
- Query param `range` ("1h" | "6h" | "24h" | "7d" | "30d" | "90d") — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
- Query param `from` (string) — Window start as an ISO-8601 timestamp. Pair with `to` for an exact custom window; when set it overrides `range`.
- Query param `to` (string) — Window end as an ISO-8601 timestamp (defaults to now when only `from` is given). Overrides `range` when set.
- Query param `app_id` (string) — Scope the metrics to one policy app (app_…). Omit to aggregate across every app in the workspace.
- Query param `endpoint` (string) — Scope the metrics to one API endpoint path (e.g. /quote). Omit to include all endpoints.
- Response (JSON):
  - `codes[]` — object[]
    - `code` — string
    - `occurrences` — number
    - `impacted_flows` — number
  - `range` — "1h" | "6h" | "24h" | "7d" | "30d" | "90d" — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
  - `degraded` — boolean

### `GET /v1/order-os/analytics/dex` — Analytics DEX distribution
- Action: `read` · MCP tool: `order-os.analytics_dex`
- How your trades distributed across DEXes, with a pool count per DEX.
- Query param `range` ("1h" | "6h" | "24h" | "7d" | "30d" | "90d") — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
- Query param `from` (string) — Window start as an ISO-8601 timestamp. Pair with `to` for an exact custom window; when set it overrides `range`.
- Query param `to` (string) — Window end as an ISO-8601 timestamp (defaults to now when only `from` is given). Overrides `range` when set.
- Query param `app_id` (string) — Scope the metrics to one policy app (app_…). Omit to aggregate across every app in the workspace.
- Query param `endpoint` (string) — Scope the metrics to one API endpoint path (e.g. /quote). Omit to include all endpoints.
- Response (JSON):
  - `market_share[]` — object[]
    - `dex` — string
    - `count` — number
    - `pools` — number
  - `range` — "1h" | "6h" | "24h" | "7d" | "30d" | "90d" — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
  - `degraded` — boolean

### `GET /v1/order-os/analytics/routing` — Analytics routing distribution
- Action: `read` · MCP tool: `order-os.analytics_routing`
- Distribution of routing algorithms, hop counts, and route types (direct/multi/complex).
- Query param `range` ("1h" | "6h" | "24h" | "7d" | "30d" | "90d") — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
- Query param `from` (string) — Window start as an ISO-8601 timestamp. Pair with `to` for an exact custom window; when set it overrides `range`.
- Query param `to` (string) — Window end as an ISO-8601 timestamp (defaults to now when only `from` is given). Overrides `range` when set.
- Query param `app_id` (string) — Scope the metrics to one policy app (app_…). Omit to aggregate across every app in the workspace.
- Query param `endpoint` (string) — Scope the metrics to one API endpoint path (e.g. /quote). Omit to include all endpoints.
- Response (JSON):
  - `algorithms[]` — object[]
    - `algorithm` — string
    - `count` — number
  - `hops[]` — object[]
    - `hops` — number
    - `count` — number
  - `route_types[]` — object[]
    - `route_type` — string
    - `count` — number
  - `range` — "1h" | "6h" | "24h" | "7d" | "30d" | "90d" — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
  - `degraded` — boolean

### `GET /v1/order-os/analytics/slippage` — Analytics slippage / price impact
- Action: `read` · MCP tool: `order-os.analytics_slippage`
- Distribution of price impact and of requested slippage across your trades.
- Query param `range` ("1h" | "6h" | "24h" | "7d" | "30d" | "90d") — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
- Query param `from` (string) — Window start as an ISO-8601 timestamp. Pair with `to` for an exact custom window; when set it overrides `range`.
- Query param `to` (string) — Window end as an ISO-8601 timestamp (defaults to now when only `from` is given). Overrides `range` when set.
- Query param `app_id` (string) — Scope the metrics to one policy app (app_…). Omit to aggregate across every app in the workspace.
- Query param `endpoint` (string) — Scope the metrics to one API endpoint path (e.g. /quote). Omit to include all endpoints.
- Response (JSON):
  - `price_impact[]` — object[]
    - `bucket` — string
    - `count` — number
  - `requested_slippage[]` — object[]
    - `slippage_bps` — string
    - `count` — number
  - `range` — "1h" | "6h" | "24h" | "7d" | "30d" | "90d" — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
  - `degraded` — boolean

### `GET /v1/order-os/analytics/tokens` — Analytics top tokens
- Action: `read` · MCP tool: `order-os.analytics_tokens`
- Your top input and output mints, and top trading pairs.
- Query param `range` ("1h" | "6h" | "24h" | "7d" | "30d" | "90d") — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
- Query param `from` (string) — Window start as an ISO-8601 timestamp. Pair with `to` for an exact custom window; when set it overrides `range`.
- Query param `to` (string) — Window end as an ISO-8601 timestamp (defaults to now when only `from` is given). Overrides `range` when set.
- Query param `app_id` (string) — Scope the metrics to one policy app (app_…). Omit to aggregate across every app in the workspace.
- Query param `endpoint` (string) — Scope the metrics to one API endpoint path (e.g. /quote). Omit to include all endpoints.
- Response (JSON):
  - `top_input[]` — object[]
    - `mint` — string
    - `count` — number
  - `top_output[]` — object[]
    - `mint` — string
    - `count` — number
  - `top_pairs[]` — object[]
    - `input_mint` — string
    - `output_mint` — string
    - `count` — number
  - `range` — "1h" | "6h" | "24h" | "7d" | "30d" | "90d" — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
  - `degraded` — boolean

### `GET /v1/order-os/analytics/volume` — Analytics volume
- Action: `read` · MCP tool: `order-os.analytics_volume`
- Trade-size distribution and swap-mode split.
- Query param `range` ("1h" | "6h" | "24h" | "7d" | "30d" | "90d") — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
- Query param `from` (string) — Window start as an ISO-8601 timestamp. Pair with `to` for an exact custom window; when set it overrides `range`.
- Query param `to` (string) — Window end as an ISO-8601 timestamp (defaults to now when only `from` is given). Overrides `range` when set.
- Query param `app_id` (string) — Scope the metrics to one policy app (app_…). Omit to aggregate across every app in the workspace.
- Query param `endpoint` (string) — Scope the metrics to one API endpoint path (e.g. /quote). Omit to include all endpoints.
- Response (JSON):
  - `trade_sizes[]` — object[]
    - `bucket` — string
    - `count` — number
  - `swap_modes[]` — object[]
    - `swap_mode` — string
    - `count` — number
  - `range` — "1h" | "6h" | "24h" | "7d" | "30d" | "90d" — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
  - `degraded` — boolean

### `GET /v1/order-os/analytics/geo` — Analytics geo distribution
- Action: `read` · MCP tool: `order-os.analytics_geo`
- Requests by country and continent.
- Query param `range` ("1h" | "6h" | "24h" | "7d" | "30d" | "90d") — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
- Query param `from` (string) — Window start as an ISO-8601 timestamp. Pair with `to` for an exact custom window; when set it overrides `range`.
- Query param `to` (string) — Window end as an ISO-8601 timestamp (defaults to now when only `from` is given). Overrides `range` when set.
- Query param `app_id` (string) — Scope the metrics to one policy app (app_…). Omit to aggregate across every app in the workspace.
- Query param `endpoint` (string) — Scope the metrics to one API endpoint path (e.g. /quote). Omit to include all endpoints.
- Response (JSON):
  - `countries[]` — object[]
    - `country_code` — string
    - `continent_code` — string
    - `count` — number
  - `range` — "1h" | "6h" | "24h" | "7d" | "30d" | "90d" — Rolling time window for the metrics, ending now. Defaults to "24h". Ignored when explicit from/to are supplied.
  - `degraded` — boolean

### `GET /v1/order-os/requests` — Inspect API requests
- Action: `read` · MCP tool: `order-os.requests`
- Lists your recent keyed Order OS API calls from the capture sink: method, operation, latency, status, request and response JSON where the capture tier allows it, and caller geo. The inspector never captures itself.
- Query param `endpoint` (string) — Filter to one captured operation. Omit for every operation.
- Query param `cluster` (string) — Filter to calls on one cluster when the product records a cluster. Omit for every cluster.
- Query param `status` ("2xx" | "3xx" | "4xx" | "5xx" | "error") — Filter the feed and endpoint summary by response status class. `error` means status >= 400.
- Query param `tier` (integer) — Filter by capture tier: 0 = Full bodies, 1 = metadata only.
- Query param `cursor` (string) — Pagination cursor for the `items` feed — pass the `next_cursor` from the previous page.
- Query param `limit` (integer) — Rows per page for the `items` feed (1–200). Defaults to 50.
- Query param `range_days` (integer) — Compatibility window in days (1–90) for `by_endpoint`. Exact from/to filters both items and summary. Defaults to 14.
- Query param `from` (string) — Exact ISO-8601 boundary. Supply both from and to; the interval is [from, to).
- Query param `to` (string) — Exact ISO-8601 boundary. Supply both from and to; the interval is [from, to).
- Response (JSON):
  - `items[]` — object[] — Recent keyed customer API calls, newest first. Dashboard-session, service, and internal calls are never included.
    - `timestamp` — number — Unix-ms when the call was served.
    - `endpoint` — string — The captured customer-facing operation.
    - `method` — string — HTTP method.
    - `status` — number — HTTP status returned.
    - `latency_ms` — number — Server-side latency in milliseconds.
    - `cluster` — string | null — Cluster stamped on the call, or null when the product has no cluster dimension.
    - `request_body` — any — Captured request JSON, or null when the capture tier carried no body.
    - `response_body` — any — Captured response JSON, or null when the capture tier carried no body.
    - `request_size` — number — Captured request body size in bytes before truncation.
    - `response_size` — number — Captured response body size in bytes before truncation.
    - `user_agent` — string | null — Caller's User-Agent when captured.
    - `client_id` — string | null — Caller-supplied X-Client-ID when present.
    - `tier` — number — Capture tier: 0 = Full, 1 = MetadataOnly.
    - `country_code` — string | null — Caller's GeoIP country.
    - `city` — string | null — Caller's GeoIP city.
    - `region` — string | null — Caller's GeoIP region/subdivision.
    - `continent_code` — string | null — Caller's GeoIP continent code.
    - `asn` — number | null — Caller's network ASN.
    - `as_org` — string | null — Caller's network organization name.
  - `by_endpoint[]` — object[] — Per-endpoint performance over the selected window.
    - `endpoint` — string — The captured operation.
    - `calls` — number — Number of calls to this endpoint in the window.
    - `error_rate` — number — Percent of calls with status >= 400 (0–100).
    - `p50_latency_ms` — number — Median server-side latency in milliseconds.
    - `p90_latency_ms` — number — p90 server-side latency in milliseconds.
    - `p99_latency_ms` — number — p99 server-side latency in milliseconds.
  - `next_cursor` — string | null — Pass as `cursor` to fetch the next older page of items.
  - `degraded` — boolean — true when the inspection store is unavailable; items and by_endpoint are then empty.

### `GET /v1/order-os/tokens/search` — Search tokens
- Action: `read` · MCP tool: `order-os.search_tokens`
- Search the tradeable tokens by symbol, name, or address. Defaults to cluster=mainnet and every response echoes its cluster. Pass `minimal=true` for just address and decimals per hit.
- Query param `q` (string, required) — Search text — a symbol ("SOL"), name ("Circle"), or a full mint address. Best matches first.
- Query param `limit` (integer) — Max results to return.
- Query param `offset` (integer) — Result offset for paging.
- Query param `minimal` ("true" | "false") — Set "true" to return a lean token shape (address, symbol, name, decimals, logo) instead of the full metadata record — smaller payload for pickers and autocompletes.
- Query param `cluster` (string) — Solana cluster to resolve token metadata against — "mainnet" is the live network and the default. Order OS trades mainnet only.
- Response (JSON):
  - `tokens[]` — any[]
  - `total` — number
  - `processing_time_ms` — number
  - `cluster` — string

### `GET /v1/order-os/tokens/{mint}` — Get a token
- Action: `read` · MCP tool: `order-os.get_token`
- The token for a mint: always decimals, plus symbol, name, and logo when known. Pass `minimal=true` for just address and decimals. Passing a token account (not a mint) returns 400 with a `mintHint` pointing at the owning mint; an unknown address is 404. Defaults to cluster=mainnet and echoes the cluster.
- Path param `mint` (string, required) — The token's mint address (base58), e.g. So11111111111111111111111111111111111111112 (SOL).
- Query param `minimal` ("true" | "false") — Set "true" to return a lean token shape (address, symbol, name, decimals, logo) instead of the full metadata record — smaller payload for pickers and autocompletes.
- Query param `cluster` (string) — Solana cluster to resolve token metadata against — "mainnet" is the live network and the default. Order OS trades mainnet only.
- Response (JSON):
  - `address` — string
  - `decimals` — number
  - `cluster` — string
