# Clear API

Hand Clear a signed transaction and walk away — it lands durably on chain, resubmits only while the network hasn't seen it, and tells you the moment it confirms. Non-custodial: you sign, Clear relays the bytes, never your keys.

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/clear`
- OpenAPI: `https://api.k256.xyz/clear/api/spec.json`
- MCP (for agents): `https://api.k256.xyz/clear/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.

Clear lands signed Solana transactions durably and non-custodially. HOSTS — every SEND goes to https://clear-<cluster>.k256.xyz (clear-mainnet, clear-devnet, or clear-testnet); every READ, status poll, and cancel goes to https://api.k256.xyz. Two ways in, same engine: (1) Structured: POST https://clear-<cluster>.k256.xyz/v1/clear/intents/send with signed bytes (legacy or v0) — blockhash, last_valid_block_height and idempotency_key are all OPTIONAL (derived from the bytes; idempotency defaults to the tx signature). Returns an intent_id. Poll GET https://api.k256.xyz/v1/clear/intents/:id (add ?wait=true&cursor=<version> to long-poll). (2) Drop-in RPC: POST https://clear-<cluster>.k256.xyz is a Solana JSON-RPC endpoint (the hostname IS the RPC URL — no path or cluster field needed; /v1/clear/rpc/<cluster> also works). sendTransaction answers the standard {jsonrpc, result: <base58 signature>, id}; parameters, structural errors, and preflight errors match agave. With skipPreflight:true, Clear validates locally, begins delivery, durably accepts the exact bytes, and returns the standard signature without waiting for continued landing. Bytes that fail validation are never broadcast and are recorded as terminal status invalid at X-Clear-Status-Url. With preflight enabled, Clear waits for the requested simulation and returns its error before sending. Every other method keeps standard Solana JSON-RPC behavior. Migrate by changing only your RPC URL (auth via Authorization: Bearer <key> or key-in-path /k/<key>). Accepted sends can add X-Clear-Intent-Id, X-Clear-Status-Url, X-Clear-Cluster, X-Clear-Signature, X-Clear-Commitment, X-Clear-Dedup, X-Clear-Reference-Id, and X-Clear-Hint response headers. Identity & idempotency: on the drop-in, identical bytes ALWAYS collapse to one durable intent within a cluster because the transaction signature is the identity. Send X-Clear-Reference-Id (or Idempotency-Key) to tag the intent; an explicit idempotency key that deduplicates different signings is available through the intent API. Look an intent up by signature at GET https://api.k256.xyz/v1/clear/intents/<signature>?cluster=<cluster>, or by your reference at GET https://api.k256.xyz/v1/clear/feed?search=<your-reference-id>. Clear re-attempts the same signed bytes only while the transaction remains valid and the chain has not observed it — never fixed-timer spam. The intent timeline records every accepted send and every terminal outcome, including locally rejected invalidity. REFERENCE INTEGRATION — https://github.com/quiknode-labs/k256-clear-nextjs-example is the maintained plain-HTTP Next.js example for wallet signing, server-side API-key custody, reload-safe version-cursor long polling, re-signing, and cancellation. It uses no k256 SDK. CLEAR FEES — GET https://clear-<cluster>.k256.xyz/v1/clear/fees/quote needs no key and takes no query parameters. The host selects the cluster and the answer echoes it. Authenticated POST on the same URL accepts {} or optional `urgency`, `writable_accounts`, `transaction`, `cu_limit`, `max_spend_lamports`, and `sign_latency_ms`, and returns a `quote_id`. Every 200 carries `recent_blockhash` and `last_valid_block_height`; if `pay` is false, omit SetComputeUnitPrice. A send may carry `quote_id` to correlate the quote with that send. It is optional metadata and never participates in admission or landing. Re-quote after `re_quote_after_ms` if you have not sent yet. LANDING CONTROLS — landing is automatic: Clear decides the fastest safe way to deliver your transaction; you don't configure it. Your ONE control is the avoid list: GET/POST /v1/clear/avoid-list — validators, AS networks, countries, and client software families Clear will never send your transactions through. Block-only by design: there is no require-list. Changes apply on your very next send.

## Endpoints

### `POST /v1/clear/intents/send` — Send a transaction
- Action: `write` · MCP tool: `clear.intents_send`
- Base URL for THIS endpoint: `https://clear-{cluster}.k256.xyz` — Clear's send endpoint — geo-routed to the nearest location for the fastest submission; it serves the whole send path. Reads, status, and cancel stay on https://api.k256.xyz. — `{cluster}` = `mainnet` | `devnet` | `testnet` (default `mainnet`; selects the `cluster` in this base URL — the host you send to)
- Hands Clear your signed transaction bytes (legacy or v0) and durably drives them to landing at your commitment gate (default finalized). Non-custodial — Clear relays the signed bytes, never your key. Pass intent_id with freshly-signed bytes of the same action to re-sign an intent whose blockhash expired, instead of creating a new one. The acknowledgement returns the known signature and intent id immediately; poll status_url for the complete lifecycle and outcome.
- Request body (JSON, required):
  - `intent_id` — string — RE-SIGN an existing intent: pass its id with freshly-signed bytes of the SAME action (only the blockhash may differ) and Clear continues that intent — no new record. Omit to create.
  - `signed_tx_base64` — string (required) — The fully-signed transaction (v0 or legacy), base64 wire bytes. Clear never sees your key — only these signed bytes.
  - `blockhash` — string — Optional — derived from the signed bytes when omitted; cross-checked against them when supplied.
  - `last_valid_block_height` — integer — Optional expiry height from getLatestBlockhash — lets Clear declare needs_resign precisely instead of probing.
  - `cluster` — "mainnet" | "devnet" | "testnet" — Optional cross-check. The clear-<cluster>.k256.xyz hostname selects the cluster; omit this field for the simplest direct call. If supplied, it must match that host. Explorer and MCP calls use it to choose a host and default to mainnet. Ignored on re-sign because the intent already has a cluster.
  - `idempotency_key` — string — Optional dedup key (unique per workspace): a retry with the same key returns the existing intent instead of double-sending. Defaults to the transaction signature when omitted — so a plain retry of the identical signed bytes is already dedup-safe (it collapses to the same intent, never a double-send).
  - `origin` — object — Where this came from — a label for the console feed, an optional return_url for re-signing at the source, and an opaque context echoed back.
  - `client_reference_id` — string — Your own id for this action — searchable in the feed and echoed in callbacks.
  - `consumer` — string
  - `kind` — string
  - `effect` — any
  - `commitment_target` — "confirmed" | "finalized" — The landing gate — when Clear considers it LANDED and applies your effect. Default FINALIZED (irreversible, ~15s); choose confirmed for speed (~0.4-2s, supermajority-voted but theoretically reversible). processed is not offered: it can be rolled back and is never safe to act on. Clear always watches through finalized either way.
  - `not_before` — integer — Execute NO EARLIER than this unix-ms — a lower bound, not an exact time. A future value holds it as a scheduled release; a past value means 'now' and lands immediately. Beyond the blockhash life minus landing margin (~45s at today's 400ms slots) it must be signed against a durable nonce.
  - `window_until` — integer — Landing window: broadcast now and keep trying until this unix-ms passes (then canceled if it never landed). Beyond the blockhash life (~60s at today's 400ms slots) it requires a durable nonce.
  - `trigger_spec` — any — Arm on a trigger: hold durably until you POST /intents/:id/fire (or arm_expires_at passes). Requires a durable nonce. The spec is yours — Clear stores it verbatim.
  - `arm_expires_at` — integer — TTL for an armed intent (unix-ms): if never fired by then, it cancels cleanly — nothing broadcast.
  - `callback` — object — Callbacks: Clear POSTs each subscribed transition to this URL, HMAC-signed with your workspace callback secret (rotate one first), in order, retried ~24h. Verify each delivery from its X-Clear-Signature header `t=<unix_seconds>,v1=<hex>`: v1 must equal hex(hmac_sha256(secret, `<t>.<raw body>`)).
  - `urgency` — "instant" | "standard" | "flexible" — Optional — how urgently you want this landed, independent of the priority fee (the fee lives in your signed bytes). "standard" (default) and "instant" prioritize speed; "flexible" is for non-time-critical work (settlement, batch) — Clear queues these for smoother delivery instead of rejecting when you're near the rate limit (a 200 instead of a 429). On the drop-in RPC path (raw bytes, no body field) the same choice rides the `X-Clear-Urgency` header.
- Response (JSON):
  - `intent_id` — string — The durable Clear intent id. Poll status_url for the complete lifecycle and outcome.
  - `signature` — string | null — The transaction signature Clear accepted. Null only for a multisig transaction that is still collecting signatures.
  - `status` — "submitted" | "collecting" | "scheduled" | "armed" | "invalid" — The state at acknowledgement time. invalid means Clear durably recorded a rejected transaction and did not broadcast it; otherwise poll status_url for subsequent transitions.
  - `status_url` — string — The absolute GET URL for the complete lifecycle, attempts, events, and final outcome.

### `POST /v1/clear/fees/quote` — Priority-fee quote
- Action: `read` · MCP tool: `clear.fees_quote`
- Base URL for THIS endpoint: `https://clear-{cluster}.k256.xyz` — Clear's send endpoint — geo-routed to the nearest location for the fastest submission; it serves the whole send path. Reads, status, and cancel stay on https://api.k256.xyz. — `{cluster}` = `mainnet` | `devnet` | `testnet` (default `mainnet`; selects the `cluster` in this base URL — the host you send to)
- The priority fee to pay so your transaction lands at the urgency you ask for — priced to live conditions right now, not a blind percentile. The same answer also hands you a fresh blockhash to build against and a quote_id to pass when you send, so quoting and sending are one step.

Send an empty body for a quick standard quote; add your writable accounts (and cu_limit) for a tighter, account-aware price. If the response says pay is false, add no priority fee at all — anything more is overpaying.
- Request body (JSON):
  - `urgency` — "instant" | "standard" | "flexible" — Optional. Same vocabulary as Clear send. Defaults to "standard". Shapes the target percentile of the priced answer, not a guaranteed slot.
  - `writable_accounts` — string[] — Optional. Base58 pubkeys the transaction write-locks — the sharpest input. Supplying them moves `pricing_scope` to "transaction_specific"; omitting them prices network-wide and returns a `sharpen` hint. Unioned with any `transaction` writables.
  - `transaction` — string — Optional. Base64 legacy or v0/versioned transaction/message. Clear extracts static writable keys and the declared compute limit. ALT-loaded accounts are NOT resolved in v1 — pass them in `writable_accounts` to price them.
  - `cu_limit` — integer — Optional. The compute-unit limit (1..1_400_000). Enables the exact lamports estimate and `max_spend_lamports` cap math. Derived from `transaction` when it declares one.
  - `max_spend_lamports` — integer — Optional. Caps the total priority-fee estimate. Requires a resolvable `cu_limit` (explicit or declared in the transaction). When it binds, the response carries `constraint: "your_cap"`.
  - `sign_latency_ms` — integer — Optional. How long you expect to take between quote and broadcast. Defaults to 0 for "instant", 30000 for "standard"/"flexible". Programmatic senders should pass 0.
- Response (JSON):
  - `cluster` — string — The Solana cluster that was priced — mainnet | devnet | testnet. Echoed from the host so you can verify which network answered (the body never sends it).
  - `slot_context` — number — Scalar u64. The host cluster's observed chain tip when this answer was built. Not an object, not quote validity, not a promise of a future landing slot — just the tip the price was computed against. Present on every 200 (a 503 is returned rather than a guessed slot when the chain head can't be read).
  - `recent_blockhash` — string — A current recent blockhash for the same cluster, so you can build immediately without a separate getLatestBlockhash (legacy and v0/versioned). It is at CONFIRMED commitment (the freshest usable) — if you send it right away with preflight ENABLED, set preflightCommitment:"confirmed" (or skipPreflight:true), otherwise a not-yet-finalized blockhash fails preflight with -32002 BlockhashNotFound.
  - `last_valid_block_height` — number — The blockhash-validity bound paired with `recent_blockhash` (block-height expiry). This is blockhash validity, NOT fee validity.
  - `cu_price_micro_lamports` — number — The value to put in `SetComputeUnitPrice` (micro-lamports per CU). 0 means no priority fee is needed.
  - `pay` — boolean — false iff cu_price_micro_lamports == 0. When false, OMIT the SetComputeUnitPrice instruction entirely (do not set it to 0).
  - `est_priority_fee_lamports` — number | null — Exact chain spend for the priority fee: ceil(cu_price_micro_lamports * cu_limit / 1_000_000). Present only when `cu_limit` is known (passed or declared in the transaction); null otherwise.
  - `quote_id` — string — Opaque quote id ("fq_"+hex), returned by the KEYED POST only (the keyless GET omits it). Pass it into a Clear send as body.quote_id or the X-Clear-Quote-Id header to correlate the quote with that send. It is optional metadata and never participates in admission or landing; unknown, expired, or malformed ids never block a send.
  - `pricing_scope` — "transaction_specific" | "network_wide" — Whether this estimate is sized to your specific transaction's accounts ("transaction_specific", the sharpest) or to the network as a whole ("network_wide").
  - `confidence` — "high" | "medium" | "low" — Quality of this answer in customer terms. "low" means the estimate rests on limited data — either cold/missing live facts (then constraint: "degraded_data") or thin per-account history on an account-aware quote (constraint may be null). Never a silent fallback.
  - `constraint` — "your_cap" | "capped_for_safety" | "degraded_data" | null — Single-valued reason the answer was bounded, or null. your_cap = your max_spend_lamports clamped it; capped_for_safety = Clear capped it to keep you from overpaying; degraded_data = priced conservatively from limited data (paired with confidence: "low").
  - `sharpen` — object | null — At most one hint naming the input that would sharpen this answer, or null when the answer is already at its best scope.
    - `field` — string — The optional request field that would improve this exact answer (e.g. "writable_accounts").
    - `reason` — string — Why it would help (e.g. "improves_precision").
  - `re_quote_after_ms` — number — Re-quote after this many ms if you have NOT sent yet. It is a refresh cadence, not a validity window and not a landing slot.

### `POST /v1/clear/intents/{id}/sign` — Add a signature
- Action: `write` · MCP tool: `clear.intents_sign`
- Base URL for THIS endpoint: `https://clear-{cluster}.k256.xyz` — Clear's send endpoint — geo-routed to the nearest location for the fastest submission; it serves the whole send path. Reads, status, and cancel stay on https://api.k256.xyz. — `{cluster}` = `mainnet` | `devnet` | `testnet` (default `mainnet`; selects the `cluster` in this base URL — the host you send to)
- For a multisig transaction: each co-signer signs the same transaction and submits the bytes here. Clear merges each signature and, once every required signature is present, lands it. Non-custodial — Clear collects signatures, it never signs. Retrying the exact co-sign that completed release is safe: Clear returns the existing intent and continues driving it without adding another lifecycle event.
- Path param `id` (string, required)
- Request body (JSON, required):
  - `signed_tx_base64` — string (required)
  - `cluster` — "mainnet" | "devnet" | "testnet" — The intent's cluster — resolves the clear-<cluster>.k256.xyz send door this call is routed to. Defaults to mainnet.
- Response (JSON):
  - `intent_id` — string
  - `version` — number — Monotonic revision, bumped on every state change. Pass it as `?cursor=<version>` to GET …/intents/:id?wait=true to long-poll for changes AFTER the version you already hold.
  - `status` — string — The lifecycle state — the field to poll. Held before broadcast: building (momentary, at create) · collecting (multisig — awaiting the remaining signatures) · scheduled (waiting on a future not_before / window) · armed (waiting on a trigger — POST /intents/:id/fire, or arm_expires_at). Live once broadcast, in order: submitted → processed → confirmed → finalized. Your effect applies (and the landed callback fires) when it reaches your commitment_target; Clear then keeps watching through finalized. Terminal: finalized (landed), invalid (rejected before broadcast after a drop-in acknowledgement — see `error`), failed (landed but rejected on chain — see `error`), or canceled (you stopped it — see the final event's reason). needs_resign is a RECOVERABLE stop, not terminal: the signed bytes expired and the intent waits — `resign_hint` carries the exact re-sign call.
  - `consumer` — string — The app/label you set on create — the console feed groups by it.
  - `kind` — string | null — Your optional free-text action label from create (e.g. "swap", "withdraw"); null when unset.
  - `cluster` — string — The Solana cluster this intent lives on — mainnet | devnet | testnet.
  - `commitment_target` — string — The landing gate you chose — confirmed | finalized. Clear applies your effect and fires the landed callback when the transaction reaches it, then always keeps watching through finalized.
  - `client_reference_id` — string | null — Your own id from create — searchable in the feed (?search=) and echoed in callbacks; null when you sent none.
  - `idempotency_key` — string — The dedup key for this intent (your idempotency_key, else the tx signature) — a resend under it collapses to this one record instead of double-sending.
  - `bundle_id` — string | null — The bundle this intent belongs to, or null for a standalone send.
  - `shape` — "single" | "scheduled" — single = broadcast at create; scheduled = held or windowed at create (any not_before, window_until, or trigger). The exact release kind is in `release`.
  - `submitted_via` — string — How it entered Clear — api (structured /intents/send) | rpc (drop-in sendTransaction).
  - `signature` — string | null — The transaction signature from the accepted wire bytes. When the chain has observed an attempt this is that observed signature; otherwise it is the latest accepted attempt, including held, expired, invalid, or canceled-before-broadcast transactions. Null only while a multisig transaction is still collecting signatures or no attempt exists.
  - `explorer_url` — string | null — A ready-to-open block-explorer link when the signature was broadcast and may have a chain record. Null before broadcast and for transactions known not to have landed, including invalid and needs_resign intents.
  - `origin` — any — The origin object you sent on create (label, optional return_url, opaque context), echoed back verbatim; null when you sent none.
  - `origin_geo` — object | null — Where the create request came from (network + GeoIP). `ip` is visible only to the intent's owner. Null until the geo write lands.
    - `country` — string | null
    - `continent` — string | null
    - `city` — string | null
    - `region` — string | null
    - `lat` — number | null
    - `lon` — number | null
    - `timezone` — string | null
    - `asn` — number | null
    - `as_org` — string | null
    - `ip` — string | null
  - `resolution` — object | null — Where and how it landed — the slot, the commitment reached, and the validator that included it. Null until landed; `leader` is null on the pure-RPC path.
    - `landed_slot` — number | null — The slot the transaction landed in; null until landed.
    - `landed_commitment` — string | null — The commitment reached at landing (confirmed | finalized); null until landed.
    - `landed_attempt_id` — string | null — Which attempt (see `attempts[]`) actually landed; null until landed.
    - `leader` — object | null — The validator that included the transaction — its identity, client software, stake and geo (all publicly verifiable on-chain). Null on the pure-RPC path or before landing.
      - `identity` — string
      - `country` — string | null
      - `city` — string | null
      - `asn` — number | null
      - `as_org` — string | null
      - `lat` — number | null
      - `lon` — number | null
      - `client` — object | null — The validator's declared client software (agave | frankendancer | …); null when no version is known.
      - `stake` — number | null — Activated stake (lamports) of the validator that included the tx — null when not known.
  - `attempts[]` — object[] — Every signed version of this action Clear has driven — one per create / re-sign / bump, newest last. Each carries its own signature and blockhash so you can trace exactly which bytes were on the wire.
    - `attempt_no` — number — 1-based attempt index — bumped by each re-sign / bump.
    - `signature` — string — This attempt's transaction signature.
    - `blockhash` — string — The blockhash (or durable-nonce value) these bytes were signed against.
    - `last_valid_block_height` — number — The height past which this attempt's blockhash expires.
    - `status` — string — in_flight while the intent is live; a landed attempt carries its reached commitment (processed | confirmed | finalized). Once the intent terminalizes, an attempt that never landed tells the truth instead: superseded (a re-sign/bump replaced it, or another attempt landed) | invalid (Clear rejected the bytes before broadcast) | failed (the chain rejected this signature) | canceled (future re-broadcasts stopped) | expired (the bytes died — see resign_hint.reason).
  - `events[]` — object[] — The ordered transition timeline (oldest first) — every status change with its observation time and, where recorded, its reason. This is the audit trail behind the current `status`.
    - `at` — number — Unix-ms when Clear OBSERVED this transition — observation time, never the on-chain time (that lives in result.block_time). Same-second neighbors are real: e.g. a transaction accepted with an already-expired blockhash shows submitted and needs_resign within the same second.
    - `status` — string — The status this transition moved the intent INTO — the same vocabulary as the top-level `status`.
    - `reason` — string — Why this transition happened, when recorded — needs_resign: blockhash_expired | nonce_advanced | not_landing; canceled: caller_requested | arm_expired | window_closed | bundle_sealed | bundle_canceled.
  - `resign_hint` — object — Present ONLY while status is needs_resign: why it didn't land + the exact re-sign call with this intent's real id. The needs_resign callback payload embeds the same object.
    - `reason` — string — Why the signed bytes died: blockhash_expired | nonce_advanced | not_landing.
    - `action` — string — The one next action, in plain words.
    - `send` — object — A ready-to-send re-sign call, prefilled with this intent's real id.
      - `method` — string
      - `url` — string — The ABSOLUTE re-sign endpoint — the intent's own cluster send door, https://clear-<cluster>.k256.xyz/v1/clear/intents/send.
      - `body` — object
    - `retry_collapse` — string — How retries collapse onto this intent, in the ingress door's own vocabulary (API/direct: intent_id + the client_reference_id/idempotency_key body fields; drop-in RPC: the X-Clear-Reference-Id header).
  - `fee_posture` — object — How this transaction's priority fee sat against the live fee market when Clear accepted it — deliberately coarse. Snapshotted once at acceptance, so create and every later read return the SAME value. ABSENT when the fee wasn't classified at acceptance (and bundle members carry no posture) — never guessed.
    - `level` — "none" | "low" | "typical" | "high" — The create-time price band: none (no priority fee set) | low | typical | high, relative to observed network demand when Clear accepted the transaction.
    - `note` — string — A factual description of that create-time price band.
  - `decoded` — any | null — The decoded transaction message (fee payer, instructions, account keys, address-lookup-table resolution) — a read-only view of the bytes you signed. Null before decode.
  - `result` — any | null — The on-chain outcome once landed — slot, block_time, fee (lamports), compute units consumed, balance/token deltas, and program logs. Null until landed.
  - `error` — any — The exact failure detail when status is invalid (pre-broadcast validation) or failed (the chain's error plus a plain-words reading); null otherwise.
  - `not_before` — number | null — The earliest unix-ms this intent may broadcast (the not_before you set), or null for an immediate send.
  - `release` — object — The release axis — WHEN the bytes broadcast, orthogonal to `shape`.
    - `kind` — string — The release mechanism — immediate (broadcast at create) | scheduled (held for not_before) | window (broadcast now, keep trying until window_until) | triggered (armed; broadcasts on /fire).
    - `window_until` — number | null — Landing-window deadline (unix-ms) for a window release; null otherwise.
    - `arm_expires_at` — number | null — TTL (unix-ms) for a triggered release — cancels cleanly if never fired; null otherwise.
    - `armed` — boolean — True while a triggered intent is held awaiting /fire.
    - `trigger_spec` — any | null — Your own resolve condition, echoed verbatim from create (triggered release only) — Clear stores it opaquely and never interprets it. Null on every other release kind.
  - `created_at` — number — When Clear created this intent (unix-ms).
  - `updated_at` — number — When this intent last changed (unix-ms).
  - `terminal_at` — number | null — When the intent reached a terminal state (finalized | invalid | failed | canceled); null while still live or in needs_resign.

### `POST /v1/clear/intents/{id}/fire` — Fire (release now)
- Action: `write` · MCP tool: `clear.intents_fire`
- Base URL for THIS endpoint: `https://clear-{cluster}.k256.xyz` — Clear's send endpoint — geo-routed to the nearest location for the fastest submission; it serves the whole send path. Reads, status, and cancel stay on https://api.k256.xyz. — `{cluster}` = `mainnet` | `devnet` | `testnet` (default `mainnet`; selects the `cluster` in this base URL — the host you send to)
- Releases an intent you armed in advance (signed against a durable nonce, held for a trigger) — Clear broadcasts it now and drives it to landing. 409 if the intent isn't armed.
- Path param `id` (string, required)
- Request body (JSON):
  - `cluster` — "mainnet" | "devnet" | "testnet" — The intent's cluster — resolves the clear-<cluster>.k256.xyz send door this call is routed to. Defaults to mainnet.
- Response (JSON):
  - `intent_id` — string
  - `version` — number — Monotonic revision, bumped on every state change. Pass it as `?cursor=<version>` to GET …/intents/:id?wait=true to long-poll for changes AFTER the version you already hold.
  - `status` — string — The lifecycle state — the field to poll. Held before broadcast: building (momentary, at create) · collecting (multisig — awaiting the remaining signatures) · scheduled (waiting on a future not_before / window) · armed (waiting on a trigger — POST /intents/:id/fire, or arm_expires_at). Live once broadcast, in order: submitted → processed → confirmed → finalized. Your effect applies (and the landed callback fires) when it reaches your commitment_target; Clear then keeps watching through finalized. Terminal: finalized (landed), invalid (rejected before broadcast after a drop-in acknowledgement — see `error`), failed (landed but rejected on chain — see `error`), or canceled (you stopped it — see the final event's reason). needs_resign is a RECOVERABLE stop, not terminal: the signed bytes expired and the intent waits — `resign_hint` carries the exact re-sign call.
  - `consumer` — string — The app/label you set on create — the console feed groups by it.
  - `kind` — string | null — Your optional free-text action label from create (e.g. "swap", "withdraw"); null when unset.
  - `cluster` — string — The Solana cluster this intent lives on — mainnet | devnet | testnet.
  - `commitment_target` — string — The landing gate you chose — confirmed | finalized. Clear applies your effect and fires the landed callback when the transaction reaches it, then always keeps watching through finalized.
  - `client_reference_id` — string | null — Your own id from create — searchable in the feed (?search=) and echoed in callbacks; null when you sent none.
  - `idempotency_key` — string — The dedup key for this intent (your idempotency_key, else the tx signature) — a resend under it collapses to this one record instead of double-sending.
  - `bundle_id` — string | null — The bundle this intent belongs to, or null for a standalone send.
  - `shape` — "single" | "scheduled" — single = broadcast at create; scheduled = held or windowed at create (any not_before, window_until, or trigger). The exact release kind is in `release`.
  - `submitted_via` — string — How it entered Clear — api (structured /intents/send) | rpc (drop-in sendTransaction).
  - `signature` — string | null — The transaction signature from the accepted wire bytes. When the chain has observed an attempt this is that observed signature; otherwise it is the latest accepted attempt, including held, expired, invalid, or canceled-before-broadcast transactions. Null only while a multisig transaction is still collecting signatures or no attempt exists.
  - `explorer_url` — string | null — A ready-to-open block-explorer link when the signature was broadcast and may have a chain record. Null before broadcast and for transactions known not to have landed, including invalid and needs_resign intents.
  - `origin` — any — The origin object you sent on create (label, optional return_url, opaque context), echoed back verbatim; null when you sent none.
  - `origin_geo` — object | null — Where the create request came from (network + GeoIP). `ip` is visible only to the intent's owner. Null until the geo write lands.
    - `country` — string | null
    - `continent` — string | null
    - `city` — string | null
    - `region` — string | null
    - `lat` — number | null
    - `lon` — number | null
    - `timezone` — string | null
    - `asn` — number | null
    - `as_org` — string | null
    - `ip` — string | null
  - `resolution` — object | null — Where and how it landed — the slot, the commitment reached, and the validator that included it. Null until landed; `leader` is null on the pure-RPC path.
    - `landed_slot` — number | null — The slot the transaction landed in; null until landed.
    - `landed_commitment` — string | null — The commitment reached at landing (confirmed | finalized); null until landed.
    - `landed_attempt_id` — string | null — Which attempt (see `attempts[]`) actually landed; null until landed.
    - `leader` — object | null — The validator that included the transaction — its identity, client software, stake and geo (all publicly verifiable on-chain). Null on the pure-RPC path or before landing.
      - `identity` — string
      - `country` — string | null
      - `city` — string | null
      - `asn` — number | null
      - `as_org` — string | null
      - `lat` — number | null
      - `lon` — number | null
      - `client` — object | null — The validator's declared client software (agave | frankendancer | …); null when no version is known.
      - `stake` — number | null — Activated stake (lamports) of the validator that included the tx — null when not known.
  - `attempts[]` — object[] — Every signed version of this action Clear has driven — one per create / re-sign / bump, newest last. Each carries its own signature and blockhash so you can trace exactly which bytes were on the wire.
    - `attempt_no` — number — 1-based attempt index — bumped by each re-sign / bump.
    - `signature` — string — This attempt's transaction signature.
    - `blockhash` — string — The blockhash (or durable-nonce value) these bytes were signed against.
    - `last_valid_block_height` — number — The height past which this attempt's blockhash expires.
    - `status` — string — in_flight while the intent is live; a landed attempt carries its reached commitment (processed | confirmed | finalized). Once the intent terminalizes, an attempt that never landed tells the truth instead: superseded (a re-sign/bump replaced it, or another attempt landed) | invalid (Clear rejected the bytes before broadcast) | failed (the chain rejected this signature) | canceled (future re-broadcasts stopped) | expired (the bytes died — see resign_hint.reason).
  - `events[]` — object[] — The ordered transition timeline (oldest first) — every status change with its observation time and, where recorded, its reason. This is the audit trail behind the current `status`.
    - `at` — number — Unix-ms when Clear OBSERVED this transition — observation time, never the on-chain time (that lives in result.block_time). Same-second neighbors are real: e.g. a transaction accepted with an already-expired blockhash shows submitted and needs_resign within the same second.
    - `status` — string — The status this transition moved the intent INTO — the same vocabulary as the top-level `status`.
    - `reason` — string — Why this transition happened, when recorded — needs_resign: blockhash_expired | nonce_advanced | not_landing; canceled: caller_requested | arm_expired | window_closed | bundle_sealed | bundle_canceled.
  - `resign_hint` — object — Present ONLY while status is needs_resign: why it didn't land + the exact re-sign call with this intent's real id. The needs_resign callback payload embeds the same object.
    - `reason` — string — Why the signed bytes died: blockhash_expired | nonce_advanced | not_landing.
    - `action` — string — The one next action, in plain words.
    - `send` — object — A ready-to-send re-sign call, prefilled with this intent's real id.
      - `method` — string
      - `url` — string — The ABSOLUTE re-sign endpoint — the intent's own cluster send door, https://clear-<cluster>.k256.xyz/v1/clear/intents/send.
      - `body` — object
    - `retry_collapse` — string — How retries collapse onto this intent, in the ingress door's own vocabulary (API/direct: intent_id + the client_reference_id/idempotency_key body fields; drop-in RPC: the X-Clear-Reference-Id header).
  - `fee_posture` — object — How this transaction's priority fee sat against the live fee market when Clear accepted it — deliberately coarse. Snapshotted once at acceptance, so create and every later read return the SAME value. ABSENT when the fee wasn't classified at acceptance (and bundle members carry no posture) — never guessed.
    - `level` — "none" | "low" | "typical" | "high" — The create-time price band: none (no priority fee set) | low | typical | high, relative to observed network demand when Clear accepted the transaction.
    - `note` — string — A factual description of that create-time price band.
  - `decoded` — any | null — The decoded transaction message (fee payer, instructions, account keys, address-lookup-table resolution) — a read-only view of the bytes you signed. Null before decode.
  - `result` — any | null — The on-chain outcome once landed — slot, block_time, fee (lamports), compute units consumed, balance/token deltas, and program logs. Null until landed.
  - `error` — any — The exact failure detail when status is invalid (pre-broadcast validation) or failed (the chain's error plus a plain-words reading); null otherwise.
  - `not_before` — number | null — The earliest unix-ms this intent may broadcast (the not_before you set), or null for an immediate send.
  - `release` — object — The release axis — WHEN the bytes broadcast, orthogonal to `shape`.
    - `kind` — string — The release mechanism — immediate (broadcast at create) | scheduled (held for not_before) | window (broadcast now, keep trying until window_until) | triggered (armed; broadcasts on /fire).
    - `window_until` — number | null — Landing-window deadline (unix-ms) for a window release; null otherwise.
    - `arm_expires_at` — number | null — TTL (unix-ms) for a triggered release — cancels cleanly if never fired; null otherwise.
    - `armed` — boolean — True while a triggered intent is held awaiting /fire.
    - `trigger_spec` — any | null — Your own resolve condition, echoed verbatim from create (triggered release only) — Clear stores it opaquely and never interprets it. Null on every other release kind.
  - `created_at` — number — When Clear created this intent (unix-ms).
  - `updated_at` — number — When this intent last changed (unix-ms).
  - `terminal_at` — number | null — When the intent reached a terminal state (finalized | invalid | failed | canceled); null while still live or in needs_resign.

### `POST /v1/clear/intents/{id}/bump` — Fee-bump
- Action: `write` · MCP tool: `clear.intents_bump`
- Base URL for THIS endpoint: `https://clear-{cluster}.k256.xyz` — Clear's send endpoint — geo-routed to the nearest location for the fastest submission; it serves the whole send path. Reads, status, and cancel stay on https://api.k256.xyz. — `{cluster}` = `mainnet` | `devnet` | `testnet` (default `mainnet`; selects the `cluster` in this base URL — the host you send to)
- Attaches a higher-priced re-sign of an in-flight transaction so it can land faster. Safe only for a durable-nonce transaction — the shared nonce guarantees at most one version lands, never both. For a normal blockhash transaction, let it expire and re-sign instead.
- Path param `id` (string, required)
- Request body (JSON, required):
  - `signed_tx_base64` — string (required)
  - `last_valid_block_height` — integer
  - `cluster` — "mainnet" | "devnet" | "testnet" — The intent's cluster — resolves the clear-<cluster>.k256.xyz send door this call is routed to. Defaults to mainnet.
- Response (JSON):
  - `intent_id` — string
  - `version` — number — Monotonic revision, bumped on every state change. Pass it as `?cursor=<version>` to GET …/intents/:id?wait=true to long-poll for changes AFTER the version you already hold.
  - `status` — string — The lifecycle state — the field to poll. Held before broadcast: building (momentary, at create) · collecting (multisig — awaiting the remaining signatures) · scheduled (waiting on a future not_before / window) · armed (waiting on a trigger — POST /intents/:id/fire, or arm_expires_at). Live once broadcast, in order: submitted → processed → confirmed → finalized. Your effect applies (and the landed callback fires) when it reaches your commitment_target; Clear then keeps watching through finalized. Terminal: finalized (landed), invalid (rejected before broadcast after a drop-in acknowledgement — see `error`), failed (landed but rejected on chain — see `error`), or canceled (you stopped it — see the final event's reason). needs_resign is a RECOVERABLE stop, not terminal: the signed bytes expired and the intent waits — `resign_hint` carries the exact re-sign call.
  - `consumer` — string — The app/label you set on create — the console feed groups by it.
  - `kind` — string | null — Your optional free-text action label from create (e.g. "swap", "withdraw"); null when unset.
  - `cluster` — string — The Solana cluster this intent lives on — mainnet | devnet | testnet.
  - `commitment_target` — string — The landing gate you chose — confirmed | finalized. Clear applies your effect and fires the landed callback when the transaction reaches it, then always keeps watching through finalized.
  - `client_reference_id` — string | null — Your own id from create — searchable in the feed (?search=) and echoed in callbacks; null when you sent none.
  - `idempotency_key` — string — The dedup key for this intent (your idempotency_key, else the tx signature) — a resend under it collapses to this one record instead of double-sending.
  - `bundle_id` — string | null — The bundle this intent belongs to, or null for a standalone send.
  - `shape` — "single" | "scheduled" — single = broadcast at create; scheduled = held or windowed at create (any not_before, window_until, or trigger). The exact release kind is in `release`.
  - `submitted_via` — string — How it entered Clear — api (structured /intents/send) | rpc (drop-in sendTransaction).
  - `signature` — string | null — The transaction signature from the accepted wire bytes. When the chain has observed an attempt this is that observed signature; otherwise it is the latest accepted attempt, including held, expired, invalid, or canceled-before-broadcast transactions. Null only while a multisig transaction is still collecting signatures or no attempt exists.
  - `explorer_url` — string | null — A ready-to-open block-explorer link when the signature was broadcast and may have a chain record. Null before broadcast and for transactions known not to have landed, including invalid and needs_resign intents.
  - `origin` — any — The origin object you sent on create (label, optional return_url, opaque context), echoed back verbatim; null when you sent none.
  - `origin_geo` — object | null — Where the create request came from (network + GeoIP). `ip` is visible only to the intent's owner. Null until the geo write lands.
    - `country` — string | null
    - `continent` — string | null
    - `city` — string | null
    - `region` — string | null
    - `lat` — number | null
    - `lon` — number | null
    - `timezone` — string | null
    - `asn` — number | null
    - `as_org` — string | null
    - `ip` — string | null
  - `resolution` — object | null — Where and how it landed — the slot, the commitment reached, and the validator that included it. Null until landed; `leader` is null on the pure-RPC path.
    - `landed_slot` — number | null — The slot the transaction landed in; null until landed.
    - `landed_commitment` — string | null — The commitment reached at landing (confirmed | finalized); null until landed.
    - `landed_attempt_id` — string | null — Which attempt (see `attempts[]`) actually landed; null until landed.
    - `leader` — object | null — The validator that included the transaction — its identity, client software, stake and geo (all publicly verifiable on-chain). Null on the pure-RPC path or before landing.
      - `identity` — string
      - `country` — string | null
      - `city` — string | null
      - `asn` — number | null
      - `as_org` — string | null
      - `lat` — number | null
      - `lon` — number | null
      - `client` — object | null — The validator's declared client software (agave | frankendancer | …); null when no version is known.
      - `stake` — number | null — Activated stake (lamports) of the validator that included the tx — null when not known.
  - `attempts[]` — object[] — Every signed version of this action Clear has driven — one per create / re-sign / bump, newest last. Each carries its own signature and blockhash so you can trace exactly which bytes were on the wire.
    - `attempt_no` — number — 1-based attempt index — bumped by each re-sign / bump.
    - `signature` — string — This attempt's transaction signature.
    - `blockhash` — string — The blockhash (or durable-nonce value) these bytes were signed against.
    - `last_valid_block_height` — number — The height past which this attempt's blockhash expires.
    - `status` — string — in_flight while the intent is live; a landed attempt carries its reached commitment (processed | confirmed | finalized). Once the intent terminalizes, an attempt that never landed tells the truth instead: superseded (a re-sign/bump replaced it, or another attempt landed) | invalid (Clear rejected the bytes before broadcast) | failed (the chain rejected this signature) | canceled (future re-broadcasts stopped) | expired (the bytes died — see resign_hint.reason).
  - `events[]` — object[] — The ordered transition timeline (oldest first) — every status change with its observation time and, where recorded, its reason. This is the audit trail behind the current `status`.
    - `at` — number — Unix-ms when Clear OBSERVED this transition — observation time, never the on-chain time (that lives in result.block_time). Same-second neighbors are real: e.g. a transaction accepted with an already-expired blockhash shows submitted and needs_resign within the same second.
    - `status` — string — The status this transition moved the intent INTO — the same vocabulary as the top-level `status`.
    - `reason` — string — Why this transition happened, when recorded — needs_resign: blockhash_expired | nonce_advanced | not_landing; canceled: caller_requested | arm_expired | window_closed | bundle_sealed | bundle_canceled.
  - `resign_hint` — object — Present ONLY while status is needs_resign: why it didn't land + the exact re-sign call with this intent's real id. The needs_resign callback payload embeds the same object.
    - `reason` — string — Why the signed bytes died: blockhash_expired | nonce_advanced | not_landing.
    - `action` — string — The one next action, in plain words.
    - `send` — object — A ready-to-send re-sign call, prefilled with this intent's real id.
      - `method` — string
      - `url` — string — The ABSOLUTE re-sign endpoint — the intent's own cluster send door, https://clear-<cluster>.k256.xyz/v1/clear/intents/send.
      - `body` — object
    - `retry_collapse` — string — How retries collapse onto this intent, in the ingress door's own vocabulary (API/direct: intent_id + the client_reference_id/idempotency_key body fields; drop-in RPC: the X-Clear-Reference-Id header).
  - `fee_posture` — object — How this transaction's priority fee sat against the live fee market when Clear accepted it — deliberately coarse. Snapshotted once at acceptance, so create and every later read return the SAME value. ABSENT when the fee wasn't classified at acceptance (and bundle members carry no posture) — never guessed.
    - `level` — "none" | "low" | "typical" | "high" — The create-time price band: none (no priority fee set) | low | typical | high, relative to observed network demand when Clear accepted the transaction.
    - `note` — string — A factual description of that create-time price band.
  - `decoded` — any | null — The decoded transaction message (fee payer, instructions, account keys, address-lookup-table resolution) — a read-only view of the bytes you signed. Null before decode.
  - `result` — any | null — The on-chain outcome once landed — slot, block_time, fee (lamports), compute units consumed, balance/token deltas, and program logs. Null until landed.
  - `error` — any — The exact failure detail when status is invalid (pre-broadcast validation) or failed (the chain's error plus a plain-words reading); null otherwise.
  - `not_before` — number | null — The earliest unix-ms this intent may broadcast (the not_before you set), or null for an immediate send.
  - `release` — object — The release axis — WHEN the bytes broadcast, orthogonal to `shape`.
    - `kind` — string — The release mechanism — immediate (broadcast at create) | scheduled (held for not_before) | window (broadcast now, keep trying until window_until) | triggered (armed; broadcasts on /fire).
    - `window_until` — number | null — Landing-window deadline (unix-ms) for a window release; null otherwise.
    - `arm_expires_at` — number | null — TTL (unix-ms) for a triggered release — cancels cleanly if never fired; null otherwise.
    - `armed` — boolean — True while a triggered intent is held awaiting /fire.
    - `trigger_spec` — any | null — Your own resolve condition, echoed verbatim from create (triggered release only) — Clear stores it opaquely and never interprets it. Null on every other release kind.
  - `created_at` — number — When Clear created this intent (unix-ms).
  - `updated_at` — number — When this intent last changed (unix-ms).
  - `terminal_at` — number | null — When the intent reached a terminal state (finalized | invalid | failed | canceled); null while still live or in needs_resign.

### `POST /v1/clear/intents/{id}/cancel` — Cancel
- Action: `write` · MCP tool: `clear.intents_cancel`
- Stops Clear from making any further attempt on this intent. Returns an honest outcome — bytes already on the wire can still land and can't be revoked.
- Path param `id` (string, required)
- Response (JSON):
  - `intent_id` — string
  - `outcome` — string — What the cancel actually did: stopped_before_submit (nothing was ever sent) | stopped_further_attempts (it was in flight — Clear stops any further attempt; bytes already sent may still land) | dropped_after_cancel_request (a needs_resign was dropped) | landed_after_cancel_request (the chain landed it first — nothing to cancel) | already_canceled | already_invalid (rejected before broadcast, so there is nothing to stop) | already_submitted_cannot_revoke (it already ran / is past the point of no return — nothing changed).

### `POST /v1/clear/bundles` — Create a bundle
- Action: `write` · MCP tool: `clear.bundles_send`
- Base URL for THIS endpoint: `https://clear-{cluster}.k256.xyz` — Clear's send endpoint — geo-routed to the nearest location for the fastest submission; it serves the whole send path. Reads, status, and cancel stay on https://api.k256.xyz. — `{cluster}` = `mainnet` | `devnet` | `testnet` (default `mainnet`; selects the `cluster` in this base URL — the host you send to)
- Lands a set of signed transactions together — mode=sequential (each waits for the prior to land), parallel (all at once), or dag (per-step dependencies). Retry is automatic; on an on-chain failure the bundle follows on_failure (stop | continue) and reports exactly which steps landed and which didn't. Not atomic — landed steps stay on chain.
- Request body (JSON, required):
  - `mode` — "sequential" | "parallel" | "dag" (required) — sequential: each transaction is submitted only after the prior reaches the gate. parallel: all at once, independent. dag: per-step `after` dependencies.
  - `on_failure` — "stop" | "continue" — When a step fails on chain: stop halts everything after it (canceled, never broadcast); continue lands the rest. Default: stop for sequential, continue for parallel/dag.
  - `cluster` — "mainnet" | "devnet" | "testnet" — Optional cross-check. Send to https://clear-<cluster>.k256.xyz and the hostname selects the cluster for every member; if supplied, this value must match the host. Explorer and MCP calls use it to choose a host and default to mainnet. Reads and cancel stay on https://api.k256.xyz.
  - `idempotency_key` — string (required) — Required (unique per workspace): a retried create with the same key returns the existing bundle — never a double-send.
  - `commitment_target` — "confirmed" | "finalized" — The landing gate for EVERY member — and the sequential/dag advance gate (the next step waits for the prior to reach it). Default FINALIZED (irreversible; ~15s per sequential step); choose confirmed to advance faster (~0.4-2s).
  - `client_reference_id` — string
  - `origin` — object
  - `consumer` — string
  - `callback` — object
  - `release` — object
  - `transactions` — object[] (required)
- Response (JSON):
  - `bundle_id` — string
  - `version` — number — Monotonic revision, bumped on every state change — use as `?cursor=` to long-poll GET /bundles/:id?wait=true.
  - `status` — string — The bundle lifecycle — building (assembling / held before release) · running (steps executing) · completed (all steps landed) · completed_with_failures (finished, some steps did not land — see failed_count and each step in `transactions`) · stopped (halted by on_failure=stop after a step failed) · canceled (you canceled it).
  - `mode` — "sequential" | "parallel" | "dag" — Execution shape — sequential (each step after the previous lands) | parallel (all at once) | dag (per-step dependency graph; see plan_edges).
  - `on_failure` — string — What happens when a step fails to land — stop (halt the remaining steps) | continue (run the rest anyway).
  - `cluster` — string — The Solana cluster the bundle runs on — mainnet | devnet | testnet.
  - `commitment_target` — string — The landing gate applied to every step — confirmed | finalized.
  - `client_reference_id` — string | null — Your own id from create — searchable and echoed in callbacks; null when unset.
  - `origin` — any — The origin object you sent on create, echoed back; null when unset.
  - `tx_count` — number — Total steps in the bundle.
  - `landed_count` — number — How many steps have landed so far.
  - `failed_count` — number — How many steps have failed to land so far.
  - `release` — object — The release axis — WHEN the bundle sends.
    - `kind` — string — The release mechanism for the bundle — immediate | scheduled | window | triggered (see the intent `release.kind`).
    - `not_before` — number | null — Earliest broadcast time (unix-ms) for a scheduled release; null otherwise.
    - `window_until` — number | null — Landing-window deadline (unix-ms) for a window release; null otherwise.
    - `arm_expires_at` — number | null — TTL (unix-ms) for a triggered release; null otherwise.
    - `armed` — boolean — True while a triggered bundle is held awaiting /fire.
    - `trigger_spec` — any | null — Your own resolve condition, echoed verbatim from create (triggered release only). Null on every other release kind.
  - `created_at` — number — When the bundle was created (unix-ms).
  - `updated_at` — number — When the bundle last changed (unix-ms).
  - `terminal_at` — number | null — When the bundle reached a terminal state; null while still running.
  - `transactions[]` — object[] — The bundle's steps, in order — each is a full intent object (same shape as GET /intents/:id).
    - `intent_id` — string
    - `version` — number — Monotonic revision, bumped on every state change. Pass it as `?cursor=<version>` to GET …/intents/:id?wait=true to long-poll for changes AFTER the version you already hold.
    - `status` — string — The lifecycle state — the field to poll. Held before broadcast: building (momentary, at create) · collecting (multisig — awaiting the remaining signatures) · scheduled (waiting on a future not_before / window) · armed (waiting on a trigger — POST /intents/:id/fire, or arm_expires_at). Live once broadcast, in order: submitted → processed → confirmed → finalized. Your effect applies (and the landed callback fires) when it reaches your commitment_target; Clear then keeps watching through finalized. Terminal: finalized (landed), invalid (rejected before broadcast after a drop-in acknowledgement — see `error`), failed (landed but rejected on chain — see `error`), or canceled (you stopped it — see the final event's reason). needs_resign is a RECOVERABLE stop, not terminal: the signed bytes expired and the intent waits — `resign_hint` carries the exact re-sign call.
    - `consumer` — string — The app/label you set on create — the console feed groups by it.
    - `kind` — string | null — Your optional free-text action label from create (e.g. "swap", "withdraw"); null when unset.
    - `cluster` — string — The Solana cluster this intent lives on — mainnet | devnet | testnet.
    - `commitment_target` — string — The landing gate you chose — confirmed | finalized. Clear applies your effect and fires the landed callback when the transaction reaches it, then always keeps watching through finalized.
    - `client_reference_id` — string | null — Your own id from create — searchable in the feed (?search=) and echoed in callbacks; null when you sent none.
    - `idempotency_key` — string — The dedup key for this intent (your idempotency_key, else the tx signature) — a resend under it collapses to this one record instead of double-sending.
    - `bundle_id` — string | null — The bundle this intent belongs to, or null for a standalone send.
    - `shape` — "single" | "scheduled" — single = broadcast at create; scheduled = held or windowed at create (any not_before, window_until, or trigger). The exact release kind is in `release`.
    - `submitted_via` — string — How it entered Clear — api (structured /intents/send) | rpc (drop-in sendTransaction).
    - `signature` — string | null — The transaction signature from the accepted wire bytes. When the chain has observed an attempt this is that observed signature; otherwise it is the latest accepted attempt, including held, expired, invalid, or canceled-before-broadcast transactions. Null only while a multisig transaction is still collecting signatures or no attempt exists.
    - `explorer_url` — string | null — A ready-to-open block-explorer link when the signature was broadcast and may have a chain record. Null before broadcast and for transactions known not to have landed, including invalid and needs_resign intents.
    - `origin` — any — The origin object you sent on create (label, optional return_url, opaque context), echoed back verbatim; null when you sent none.
    - `origin_geo` — object | null — Where the create request came from (network + GeoIP). `ip` is visible only to the intent's owner. Null until the geo write lands.
      - `country` — string | null
      - `continent` — string | null
      - `city` — string | null
      - `region` — string | null
      - `lat` — number | null
      - `lon` — number | null
      - `timezone` — string | null
      - `asn` — number | null
      - `as_org` — string | null
      - `ip` — string | null
    - `resolution` — object | null — Where and how it landed — the slot, the commitment reached, and the validator that included it. Null until landed; `leader` is null on the pure-RPC path.
      - `landed_slot` — number | null — The slot the transaction landed in; null until landed.
      - `landed_commitment` — string | null — The commitment reached at landing (confirmed | finalized); null until landed.
      - `landed_attempt_id` — string | null — Which attempt (see `attempts[]`) actually landed; null until landed.
      - `leader` — object | null — The validator that included the transaction — its identity, client software, stake and geo (all publicly verifiable on-chain). Null on the pure-RPC path or before landing.
    - `attempts[]` — object[] — Every signed version of this action Clear has driven — one per create / re-sign / bump, newest last. Each carries its own signature and blockhash so you can trace exactly which bytes were on the wire.
      - `attempt_no` — number — 1-based attempt index — bumped by each re-sign / bump.
      - `signature` — string — This attempt's transaction signature.
      - `blockhash` — string — The blockhash (or durable-nonce value) these bytes were signed against.
      - `last_valid_block_height` — number — The height past which this attempt's blockhash expires.
      - `status` — string — in_flight while the intent is live; a landed attempt carries its reached commitment (processed | confirmed | finalized). Once the intent terminalizes, an attempt that never landed tells the truth instead: superseded (a re-sign/bump replaced it, or another attempt landed) | invalid (Clear rejected the bytes before broadcast) | failed (the chain rejected this signature) | canceled (future re-broadcasts stopped) | expired (the bytes died — see resign_hint.reason).
    - `events[]` — object[] — The ordered transition timeline (oldest first) — every status change with its observation time and, where recorded, its reason. This is the audit trail behind the current `status`.
      - `at` — number — Unix-ms when Clear OBSERVED this transition — observation time, never the on-chain time (that lives in result.block_time). Same-second neighbors are real: e.g. a transaction accepted with an already-expired blockhash shows submitted and needs_resign within the same second.
      - `status` — string — The status this transition moved the intent INTO — the same vocabulary as the top-level `status`.
      - `reason` — string — Why this transition happened, when recorded — needs_resign: blockhash_expired | nonce_advanced | not_landing; canceled: caller_requested | arm_expired | window_closed | bundle_sealed | bundle_canceled.
    - `resign_hint` — object — Present ONLY while status is needs_resign: why it didn't land + the exact re-sign call with this intent's real id. The needs_resign callback payload embeds the same object.
      - `reason` — string — Why the signed bytes died: blockhash_expired | nonce_advanced | not_landing.
      - `action` — string — The one next action, in plain words.
      - `send` — object — A ready-to-send re-sign call, prefilled with this intent's real id.
      - `retry_collapse` — string — How retries collapse onto this intent, in the ingress door's own vocabulary (API/direct: intent_id + the client_reference_id/idempotency_key body fields; drop-in RPC: the X-Clear-Reference-Id header).
    - `fee_posture` — object — How this transaction's priority fee sat against the live fee market when Clear accepted it — deliberately coarse. Snapshotted once at acceptance, so create and every later read return the SAME value. ABSENT when the fee wasn't classified at acceptance (and bundle members carry no posture) — never guessed.
      - `level` — "none" | "low" | "typical" | "high" — The create-time price band: none (no priority fee set) | low | typical | high, relative to observed network demand when Clear accepted the transaction.
      - `note` — string — A factual description of that create-time price band.
    - `decoded` — any | null — The decoded transaction message (fee payer, instructions, account keys, address-lookup-table resolution) — a read-only view of the bytes you signed. Null before decode.
    - `result` — any | null — The on-chain outcome once landed — slot, block_time, fee (lamports), compute units consumed, balance/token deltas, and program logs. Null until landed.
    - `error` — any — The exact failure detail when status is invalid (pre-broadcast validation) or failed (the chain's error plus a plain-words reading); null otherwise.
    - `not_before` — number | null — The earliest unix-ms this intent may broadcast (the not_before you set), or null for an immediate send.
    - `release` — object — The release axis — WHEN the bytes broadcast, orthogonal to `shape`.
      - `kind` — string — The release mechanism — immediate (broadcast at create) | scheduled (held for not_before) | window (broadcast now, keep trying until window_until) | triggered (armed; broadcasts on /fire).
      - `window_until` — number | null — Landing-window deadline (unix-ms) for a window release; null otherwise.
      - `arm_expires_at` — number | null — TTL (unix-ms) for a triggered release — cancels cleanly if never fired; null otherwise.
      - `armed` — boolean — True while a triggered intent is held awaiting /fire.
      - `trigger_spec` — any | null — Your own resolve condition, echoed verbatim from create (triggered release only) — Clear stores it opaquely and never interprets it. Null on every other release kind.
    - `created_at` — number — When Clear created this intent (unix-ms).
    - `updated_at` — number — When this intent last changed (unix-ms).
    - `terminal_at` — number | null — When the intent reached a terminal state (finalized | invalid | failed | canceled); null while still live or in needs_resign.
  - `plan_edges[]` — object[] — The plan's dependency edges (step index → step index): a dag's real waits_on, a sequence's implicit chain, a parallel's empty fan.
    - `from_step` — number
    - `to_step` — number

### `POST /v1/clear/bundles/{id}/fire` — Fire a bundle
- Action: `write` · MCP tool: `clear.bundles_fire`
- Base URL for THIS endpoint: `https://clear-{cluster}.k256.xyz` — Clear's send endpoint — geo-routed to the nearest location for the fastest submission; it serves the whole send path. Reads, status, and cancel stay on https://api.k256.xyz. — `{cluster}` = `mainnet` | `devnet` | `testnet` (default `mainnet`; selects the `cluster` in this base URL — the host you send to)
- Releases a bundle you armed in advance (every step signed against a durable nonce) — Clear broadcasts it now and drives each step to landing. 409 if the bundle isn't armed.
- Path param `id` (string, required)
- Request body (JSON):
  - `cluster` — "mainnet" | "devnet" | "testnet" — The intent's cluster — resolves the clear-<cluster>.k256.xyz send door this call is routed to. Defaults to mainnet.
- Response (JSON):
  - `bundle_id` — string
  - `version` — number — Monotonic revision, bumped on every state change — use as `?cursor=` to long-poll GET /bundles/:id?wait=true.
  - `status` — string — The bundle lifecycle — building (assembling / held before release) · running (steps executing) · completed (all steps landed) · completed_with_failures (finished, some steps did not land — see failed_count and each step in `transactions`) · stopped (halted by on_failure=stop after a step failed) · canceled (you canceled it).
  - `mode` — "sequential" | "parallel" | "dag" — Execution shape — sequential (each step after the previous lands) | parallel (all at once) | dag (per-step dependency graph; see plan_edges).
  - `on_failure` — string — What happens when a step fails to land — stop (halt the remaining steps) | continue (run the rest anyway).
  - `cluster` — string — The Solana cluster the bundle runs on — mainnet | devnet | testnet.
  - `commitment_target` — string — The landing gate applied to every step — confirmed | finalized.
  - `client_reference_id` — string | null — Your own id from create — searchable and echoed in callbacks; null when unset.
  - `origin` — any — The origin object you sent on create, echoed back; null when unset.
  - `tx_count` — number — Total steps in the bundle.
  - `landed_count` — number — How many steps have landed so far.
  - `failed_count` — number — How many steps have failed to land so far.
  - `release` — object — The release axis — WHEN the bundle sends.
    - `kind` — string — The release mechanism for the bundle — immediate | scheduled | window | triggered (see the intent `release.kind`).
    - `not_before` — number | null — Earliest broadcast time (unix-ms) for a scheduled release; null otherwise.
    - `window_until` — number | null — Landing-window deadline (unix-ms) for a window release; null otherwise.
    - `arm_expires_at` — number | null — TTL (unix-ms) for a triggered release; null otherwise.
    - `armed` — boolean — True while a triggered bundle is held awaiting /fire.
    - `trigger_spec` — any | null — Your own resolve condition, echoed verbatim from create (triggered release only). Null on every other release kind.
  - `created_at` — number — When the bundle was created (unix-ms).
  - `updated_at` — number — When the bundle last changed (unix-ms).
  - `terminal_at` — number | null — When the bundle reached a terminal state; null while still running.
  - `transactions[]` — object[] — The bundle's steps, in order — each is a full intent object (same shape as GET /intents/:id).
    - `intent_id` — string
    - `version` — number — Monotonic revision, bumped on every state change. Pass it as `?cursor=<version>` to GET …/intents/:id?wait=true to long-poll for changes AFTER the version you already hold.
    - `status` — string — The lifecycle state — the field to poll. Held before broadcast: building (momentary, at create) · collecting (multisig — awaiting the remaining signatures) · scheduled (waiting on a future not_before / window) · armed (waiting on a trigger — POST /intents/:id/fire, or arm_expires_at). Live once broadcast, in order: submitted → processed → confirmed → finalized. Your effect applies (and the landed callback fires) when it reaches your commitment_target; Clear then keeps watching through finalized. Terminal: finalized (landed), invalid (rejected before broadcast after a drop-in acknowledgement — see `error`), failed (landed but rejected on chain — see `error`), or canceled (you stopped it — see the final event's reason). needs_resign is a RECOVERABLE stop, not terminal: the signed bytes expired and the intent waits — `resign_hint` carries the exact re-sign call.
    - `consumer` — string — The app/label you set on create — the console feed groups by it.
    - `kind` — string | null — Your optional free-text action label from create (e.g. "swap", "withdraw"); null when unset.
    - `cluster` — string — The Solana cluster this intent lives on — mainnet | devnet | testnet.
    - `commitment_target` — string — The landing gate you chose — confirmed | finalized. Clear applies your effect and fires the landed callback when the transaction reaches it, then always keeps watching through finalized.
    - `client_reference_id` — string | null — Your own id from create — searchable in the feed (?search=) and echoed in callbacks; null when you sent none.
    - `idempotency_key` — string — The dedup key for this intent (your idempotency_key, else the tx signature) — a resend under it collapses to this one record instead of double-sending.
    - `bundle_id` — string | null — The bundle this intent belongs to, or null for a standalone send.
    - `shape` — "single" | "scheduled" — single = broadcast at create; scheduled = held or windowed at create (any not_before, window_until, or trigger). The exact release kind is in `release`.
    - `submitted_via` — string — How it entered Clear — api (structured /intents/send) | rpc (drop-in sendTransaction).
    - `signature` — string | null — The transaction signature from the accepted wire bytes. When the chain has observed an attempt this is that observed signature; otherwise it is the latest accepted attempt, including held, expired, invalid, or canceled-before-broadcast transactions. Null only while a multisig transaction is still collecting signatures or no attempt exists.
    - `explorer_url` — string | null — A ready-to-open block-explorer link when the signature was broadcast and may have a chain record. Null before broadcast and for transactions known not to have landed, including invalid and needs_resign intents.
    - `origin` — any — The origin object you sent on create (label, optional return_url, opaque context), echoed back verbatim; null when you sent none.
    - `origin_geo` — object | null — Where the create request came from (network + GeoIP). `ip` is visible only to the intent's owner. Null until the geo write lands.
      - `country` — string | null
      - `continent` — string | null
      - `city` — string | null
      - `region` — string | null
      - `lat` — number | null
      - `lon` — number | null
      - `timezone` — string | null
      - `asn` — number | null
      - `as_org` — string | null
      - `ip` — string | null
    - `resolution` — object | null — Where and how it landed — the slot, the commitment reached, and the validator that included it. Null until landed; `leader` is null on the pure-RPC path.
      - `landed_slot` — number | null — The slot the transaction landed in; null until landed.
      - `landed_commitment` — string | null — The commitment reached at landing (confirmed | finalized); null until landed.
      - `landed_attempt_id` — string | null — Which attempt (see `attempts[]`) actually landed; null until landed.
      - `leader` — object | null — The validator that included the transaction — its identity, client software, stake and geo (all publicly verifiable on-chain). Null on the pure-RPC path or before landing.
    - `attempts[]` — object[] — Every signed version of this action Clear has driven — one per create / re-sign / bump, newest last. Each carries its own signature and blockhash so you can trace exactly which bytes were on the wire.
      - `attempt_no` — number — 1-based attempt index — bumped by each re-sign / bump.
      - `signature` — string — This attempt's transaction signature.
      - `blockhash` — string — The blockhash (or durable-nonce value) these bytes were signed against.
      - `last_valid_block_height` — number — The height past which this attempt's blockhash expires.
      - `status` — string — in_flight while the intent is live; a landed attempt carries its reached commitment (processed | confirmed | finalized). Once the intent terminalizes, an attempt that never landed tells the truth instead: superseded (a re-sign/bump replaced it, or another attempt landed) | invalid (Clear rejected the bytes before broadcast) | failed (the chain rejected this signature) | canceled (future re-broadcasts stopped) | expired (the bytes died — see resign_hint.reason).
    - `events[]` — object[] — The ordered transition timeline (oldest first) — every status change with its observation time and, where recorded, its reason. This is the audit trail behind the current `status`.
      - `at` — number — Unix-ms when Clear OBSERVED this transition — observation time, never the on-chain time (that lives in result.block_time). Same-second neighbors are real: e.g. a transaction accepted with an already-expired blockhash shows submitted and needs_resign within the same second.
      - `status` — string — The status this transition moved the intent INTO — the same vocabulary as the top-level `status`.
      - `reason` — string — Why this transition happened, when recorded — needs_resign: blockhash_expired | nonce_advanced | not_landing; canceled: caller_requested | arm_expired | window_closed | bundle_sealed | bundle_canceled.
    - `resign_hint` — object — Present ONLY while status is needs_resign: why it didn't land + the exact re-sign call with this intent's real id. The needs_resign callback payload embeds the same object.
      - `reason` — string — Why the signed bytes died: blockhash_expired | nonce_advanced | not_landing.
      - `action` — string — The one next action, in plain words.
      - `send` — object — A ready-to-send re-sign call, prefilled with this intent's real id.
      - `retry_collapse` — string — How retries collapse onto this intent, in the ingress door's own vocabulary (API/direct: intent_id + the client_reference_id/idempotency_key body fields; drop-in RPC: the X-Clear-Reference-Id header).
    - `fee_posture` — object — How this transaction's priority fee sat against the live fee market when Clear accepted it — deliberately coarse. Snapshotted once at acceptance, so create and every later read return the SAME value. ABSENT when the fee wasn't classified at acceptance (and bundle members carry no posture) — never guessed.
      - `level` — "none" | "low" | "typical" | "high" — The create-time price band: none (no priority fee set) | low | typical | high, relative to observed network demand when Clear accepted the transaction.
      - `note` — string — A factual description of that create-time price band.
    - `decoded` — any | null — The decoded transaction message (fee payer, instructions, account keys, address-lookup-table resolution) — a read-only view of the bytes you signed. Null before decode.
    - `result` — any | null — The on-chain outcome once landed — slot, block_time, fee (lamports), compute units consumed, balance/token deltas, and program logs. Null until landed.
    - `error` — any — The exact failure detail when status is invalid (pre-broadcast validation) or failed (the chain's error plus a plain-words reading); null otherwise.
    - `not_before` — number | null — The earliest unix-ms this intent may broadcast (the not_before you set), or null for an immediate send.
    - `release` — object — The release axis — WHEN the bytes broadcast, orthogonal to `shape`.
      - `kind` — string — The release mechanism — immediate (broadcast at create) | scheduled (held for not_before) | window (broadcast now, keep trying until window_until) | triggered (armed; broadcasts on /fire).
      - `window_until` — number | null — Landing-window deadline (unix-ms) for a window release; null otherwise.
      - `arm_expires_at` — number | null — TTL (unix-ms) for a triggered release — cancels cleanly if never fired; null otherwise.
      - `armed` — boolean — True while a triggered intent is held awaiting /fire.
      - `trigger_spec` — any | null — Your own resolve condition, echoed verbatim from create (triggered release only) — Clear stores it opaquely and never interprets it. Null on every other release kind.
    - `created_at` — number — When Clear created this intent (unix-ms).
    - `updated_at` — number — When this intent last changed (unix-ms).
    - `terminal_at` — number | null — When the intent reached a terminal state (finalized | invalid | failed | canceled); null while still live or in needs_resign.
  - `plan_edges[]` — object[] — The plan's dependency edges (step index → step index): a dag's real waits_on, a sequence's implicit chain, a parallel's empty fan.
    - `from_step` — number
    - `to_step` — number

### `POST /v1/clear/bundles/{id}/cancel` — Cancel a bundle
- Action: `write` · MCP tool: `clear.bundles_cancel`
- Stops any step that hasn't started yet. Steps already in flight follow the single-transaction rules and steps that already landed stay on chain — nothing is reverted. Returns the honest per-step outcome and the bundle's final state.
- Path param `id` (string, required)
- Response (JSON):
  - `bundle_id` — string
  - `status` — string
  - `steps[]` — object[]
    - `intent_id` — string
    - `outcome` — string — Per-step truth: stopped_before_submit (its bytes never went on the wire — whether this call stopped it or an earlier cancel/seal already had) | stopped_further_attempts (was in flight — future re-broadcasts stop; wire bytes may still land) | landed_cannot_revoke (already on chain — stays landed) | already_canceled (canceled earlier, AFTER its bytes had been broadcast) | failed.

### `GET /v1/clear/intents/{id}` — Get an intent
- Action: `read` · MCP tool: `clear.intents_get`
- A snapshot of one intent — its status, attempts, timeline, and outcome. Add ?wait=true&cursor=<version> to long-poll until it changes past the version you already hold. Add ?include=forensics for the on-chain outcome receipt; the default poll stays light. When id is a transaction signature, add ?cluster=… if the same signed bytes were recorded on multiple clusters.
- Path param `id` (string, required)
- Query param `cluster` ("mainnet" | "devnet" | "testnet") — Optional when id is a transaction signature. Supply it to disambiguate the same signed bytes recorded on multiple clusters; lifecycle ids are already unambiguous.
- Query param `wait` (string)
- Query param `cursor` (integer)
- Query param `timeout` (integer)
- Query param `include` ("forensics") — Pass "forensics" to include chain facts plus Clear-observed delivery evidence inline as `forensics`. Omit for the light hot-poll path — no report unless asked.
- Response (JSON):
  - `intent_id` — string
  - `version` — number — Monotonic revision, bumped on every state change. Pass it as `?cursor=<version>` to GET …/intents/:id?wait=true to long-poll for changes AFTER the version you already hold.
  - `status` — string — The lifecycle state — the field to poll. Held before broadcast: building (momentary, at create) · collecting (multisig — awaiting the remaining signatures) · scheduled (waiting on a future not_before / window) · armed (waiting on a trigger — POST /intents/:id/fire, or arm_expires_at). Live once broadcast, in order: submitted → processed → confirmed → finalized. Your effect applies (and the landed callback fires) when it reaches your commitment_target; Clear then keeps watching through finalized. Terminal: finalized (landed), invalid (rejected before broadcast after a drop-in acknowledgement — see `error`), failed (landed but rejected on chain — see `error`), or canceled (you stopped it — see the final event's reason). needs_resign is a RECOVERABLE stop, not terminal: the signed bytes expired and the intent waits — `resign_hint` carries the exact re-sign call.
  - `consumer` — string — The app/label you set on create — the console feed groups by it.
  - `kind` — string | null — Your optional free-text action label from create (e.g. "swap", "withdraw"); null when unset.
  - `cluster` — string — The Solana cluster this intent lives on — mainnet | devnet | testnet.
  - `commitment_target` — string — The landing gate you chose — confirmed | finalized. Clear applies your effect and fires the landed callback when the transaction reaches it, then always keeps watching through finalized.
  - `client_reference_id` — string | null — Your own id from create — searchable in the feed (?search=) and echoed in callbacks; null when you sent none.
  - `idempotency_key` — string — The dedup key for this intent (your idempotency_key, else the tx signature) — a resend under it collapses to this one record instead of double-sending.
  - `bundle_id` — string | null — The bundle this intent belongs to, or null for a standalone send.
  - `shape` — "single" | "scheduled" — single = broadcast at create; scheduled = held or windowed at create (any not_before, window_until, or trigger). The exact release kind is in `release`.
  - `submitted_via` — string — How it entered Clear — api (structured /intents/send) | rpc (drop-in sendTransaction).
  - `signature` — string | null — The transaction signature from the accepted wire bytes. When the chain has observed an attempt this is that observed signature; otherwise it is the latest accepted attempt, including held, expired, invalid, or canceled-before-broadcast transactions. Null only while a multisig transaction is still collecting signatures or no attempt exists.
  - `explorer_url` — string | null — A ready-to-open block-explorer link when the signature was broadcast and may have a chain record. Null before broadcast and for transactions known not to have landed, including invalid and needs_resign intents.
  - `origin` — any — The origin object you sent on create (label, optional return_url, opaque context), echoed back verbatim; null when you sent none.
  - `origin_geo` — object | null — Where the create request came from (network + GeoIP). `ip` is visible only to the intent's owner. Null until the geo write lands.
    - `country` — string | null
    - `continent` — string | null
    - `city` — string | null
    - `region` — string | null
    - `lat` — number | null
    - `lon` — number | null
    - `timezone` — string | null
    - `asn` — number | null
    - `as_org` — string | null
    - `ip` — string | null
  - `resolution` — object | null — Where and how it landed — the slot, the commitment reached, and the validator that included it. Null until landed; `leader` is null on the pure-RPC path.
    - `landed_slot` — number | null — The slot the transaction landed in; null until landed.
    - `landed_commitment` — string | null — The commitment reached at landing (confirmed | finalized); null until landed.
    - `landed_attempt_id` — string | null — Which attempt (see `attempts[]`) actually landed; null until landed.
    - `leader` — object | null — The validator that included the transaction — its identity, client software, stake and geo (all publicly verifiable on-chain). Null on the pure-RPC path or before landing.
      - `identity` — string
      - `country` — string | null
      - `city` — string | null
      - `asn` — number | null
      - `as_org` — string | null
      - `lat` — number | null
      - `lon` — number | null
      - `client` — object | null — The validator's declared client software (agave | frankendancer | …); null when no version is known.
      - `stake` — number | null — Activated stake (lamports) of the validator that included the tx — null when not known.
  - `attempts[]` — object[] — Every signed version of this action Clear has driven — one per create / re-sign / bump, newest last. Each carries its own signature and blockhash so you can trace exactly which bytes were on the wire.
    - `attempt_no` — number — 1-based attempt index — bumped by each re-sign / bump.
    - `signature` — string — This attempt's transaction signature.
    - `blockhash` — string — The blockhash (or durable-nonce value) these bytes were signed against.
    - `last_valid_block_height` — number — The height past which this attempt's blockhash expires.
    - `status` — string — in_flight while the intent is live; a landed attempt carries its reached commitment (processed | confirmed | finalized). Once the intent terminalizes, an attempt that never landed tells the truth instead: superseded (a re-sign/bump replaced it, or another attempt landed) | invalid (Clear rejected the bytes before broadcast) | failed (the chain rejected this signature) | canceled (future re-broadcasts stopped) | expired (the bytes died — see resign_hint.reason).
  - `events[]` — object[] — The ordered transition timeline (oldest first) — every status change with its observation time and, where recorded, its reason. This is the audit trail behind the current `status`.
    - `at` — number — Unix-ms when Clear OBSERVED this transition — observation time, never the on-chain time (that lives in result.block_time). Same-second neighbors are real: e.g. a transaction accepted with an already-expired blockhash shows submitted and needs_resign within the same second.
    - `status` — string — The status this transition moved the intent INTO — the same vocabulary as the top-level `status`.
    - `reason` — string — Why this transition happened, when recorded — needs_resign: blockhash_expired | nonce_advanced | not_landing; canceled: caller_requested | arm_expired | window_closed | bundle_sealed | bundle_canceled.
  - `resign_hint` — object — Present ONLY while status is needs_resign: why it didn't land + the exact re-sign call with this intent's real id. The needs_resign callback payload embeds the same object.
    - `reason` — string — Why the signed bytes died: blockhash_expired | nonce_advanced | not_landing.
    - `action` — string — The one next action, in plain words.
    - `send` — object — A ready-to-send re-sign call, prefilled with this intent's real id.
      - `method` — string
      - `url` — string — The ABSOLUTE re-sign endpoint — the intent's own cluster send door, https://clear-<cluster>.k256.xyz/v1/clear/intents/send.
      - `body` — object
    - `retry_collapse` — string — How retries collapse onto this intent, in the ingress door's own vocabulary (API/direct: intent_id + the client_reference_id/idempotency_key body fields; drop-in RPC: the X-Clear-Reference-Id header).
  - `fee_posture` — object — How this transaction's priority fee sat against the live fee market when Clear accepted it — deliberately coarse. Snapshotted once at acceptance, so create and every later read return the SAME value. ABSENT when the fee wasn't classified at acceptance (and bundle members carry no posture) — never guessed.
    - `level` — "none" | "low" | "typical" | "high" — The create-time price band: none (no priority fee set) | low | typical | high, relative to observed network demand when Clear accepted the transaction.
    - `note` — string — A factual description of that create-time price band.
  - `decoded` — any | null — The decoded transaction message (fee payer, instructions, account keys, address-lookup-table resolution) — a read-only view of the bytes you signed. Null before decode.
  - `result` — any | null — The on-chain outcome once landed — slot, block_time, fee (lamports), compute units consumed, balance/token deltas, and program logs. Null until landed.
  - `error` — any — The exact failure detail when status is invalid (pre-broadcast validation) or failed (the chain's error plus a plain-words reading); null otherwise.
  - `not_before` — number | null — The earliest unix-ms this intent may broadcast (the not_before you set), or null for an immediate send.
  - `release` — object — The release axis — WHEN the bytes broadcast, orthogonal to `shape`.
    - `kind` — string — The release mechanism — immediate (broadcast at create) | scheduled (held for not_before) | window (broadcast now, keep trying until window_until) | triggered (armed; broadcasts on /fire).
    - `window_until` — number | null — Landing-window deadline (unix-ms) for a window release; null otherwise.
    - `arm_expires_at` — number | null — TTL (unix-ms) for a triggered release — cancels cleanly if never fired; null otherwise.
    - `armed` — boolean — True while a triggered intent is held awaiting /fire.
    - `trigger_spec` — any | null — Your own resolve condition, echoed verbatim from create (triggered release only) — Clear stores it opaquely and never interprets it. Null on every other release kind.
  - `created_at` — number — When Clear created this intent (unix-ms).
  - `updated_at` — number — When this intent last changed (unix-ms).
  - `terminal_at` — number | null — When the intent reached a terminal state (finalized | invalid | failed | canceled); null while still live or in needs_resign.
  - `forensics` — object — The opt-in outcome receipt: exact landed-attempt, finalized block, runtime-reported compute, charged fee, signed declaration, message-declared writable, and observed-effect evidence. Every potentially unsafe integer is a decimal string and every partial comparison carries coverage.
    - `intent_id` — string
    - `signature` — string | null
    - `cluster` — string
    - `status` — string
    - `commitment_target` — string
    - `explorer_url` — string | null
    - `landed` — boolean
    - `pending_reason` — string | null
    - `evidence` — object
      - `state` — "available" | "partial" | "unavailable"
      - `reason` — "pending_chain_outcome" | "landed_attempt_unavailable" | "landed_attempt_mismatch" | "unsupported_transaction_version" | "malformed_transaction" | "finalized_transaction_pending" | "transaction_read_unavailable" | "transaction_metadata_unavailable" | "block_read_unavailable" | "scheduled_leader_unavailable" | "target_block_mismatch" | "target_signature_ambiguous" | "block_coverage_partial" | null
      - `retryable` — boolean
    - `block` — object | null
      - `slot` — integer
      - `block_time` — integer | null
      - `blockhash` — string | null
      - `scheduled_leader` — string | null
      - `clear_observed_commitment_ms` — number | null — Clear-observed submission-to-commitment elapsed time; not an on-chain latency claim.
      - `transaction_index_zero_based` — integer | null
      - `transaction_count` — integer | null
    - `execution` — object | null
      - `state` — "succeeded" | "executed_reverted" | "rejected_fee_charged" | "rejected_no_fee" | "unavailable"
      - `error` — any | null
      - `error_readable` — string | null
    - `compute` — object | null
      - `runtime_reported_compute_units_exact` — string | null
      - `signed_limit_exact` — string | null
      - `signed_limit_source` — "explicit" | "implicit" | "v1_explicit" | "v1_default_zero" | "unavailable"
    - `fee` — object | null
      - `charged_total_lamports_exact` — string
      - `charged_priority_lamports_exact` — string | null
      - `transaction_signatures` — integer
      - `fee_counted_precompile_signatures` — integer
      - `signed_compute_unit_price` — object
      - `signed_compute_unit_limit_exact` — string | null
      - `signed_v1_priority_lamports_exact` — string | null
    - `block_context` — object | null
      - `state` — "available" | "partial"
      - `shared_writable_position` — object
      - `resources` — object
      - `writable_overlap` — object
      - `fee_position` — object
    - `effect` — object | null
      - `declared_label` — string | null
      - `balance_changes[]` — object[]
      - `balance_changes_complete` — boolean
      - `token_changes[]` — object[]
      - `token_changes_complete` — boolean
      - `message_declared_writable_accounts[]` — string[]
      - `inner_program_counts_by_instruction[]` — object[]
      - `inner_program_counts_complete` — boolean
      - `logs[]` — string[] | null
    - `identifiers` — object
      - `intent_id` — string
      - `signature` — string | null
      - `client_reference_id` — string | null
      - `kind` — string | null
      - `commitment_target` — string
      - `transaction_version` — "legacy" | "v0" | "v1" | "unknown"
      - `lifetime` — "recent_blockhash" | "durable_nonce" | "unknown"
      - `attempt_count` — integer

### `GET /v1/clear/bundles/{id}` — Get a bundle
- Action: `read` · MCP tool: `clear.bundles_get`
- The bundle's aggregate status and every child transaction. Add ?wait=true&cursor=<version> to long-poll for the next change, or ?include=forensics for the aggregate forensic report; the default poll stays light.
- Path param `id` (string, required)
- Query param `wait` (string)
- Query param `cursor` (integer)
- Query param `timeout` (integer)
- Query param `include` ("forensics") — Pass "forensics" to include the aggregate forensic report (whole and parts) inline as `forensics`. Omit for the light poll path — no forensics unless asked.
- Response (JSON):
  - `bundle_id` — string
  - `version` — number — Monotonic revision, bumped on every state change — use as `?cursor=` to long-poll GET /bundles/:id?wait=true.
  - `status` — string — The bundle lifecycle — building (assembling / held before release) · running (steps executing) · completed (all steps landed) · completed_with_failures (finished, some steps did not land — see failed_count and each step in `transactions`) · stopped (halted by on_failure=stop after a step failed) · canceled (you canceled it).
  - `mode` — "sequential" | "parallel" | "dag" — Execution shape — sequential (each step after the previous lands) | parallel (all at once) | dag (per-step dependency graph; see plan_edges).
  - `on_failure` — string — What happens when a step fails to land — stop (halt the remaining steps) | continue (run the rest anyway).
  - `cluster` — string — The Solana cluster the bundle runs on — mainnet | devnet | testnet.
  - `commitment_target` — string — The landing gate applied to every step — confirmed | finalized.
  - `client_reference_id` — string | null — Your own id from create — searchable and echoed in callbacks; null when unset.
  - `origin` — any — The origin object you sent on create, echoed back; null when unset.
  - `tx_count` — number — Total steps in the bundle.
  - `landed_count` — number — How many steps have landed so far.
  - `failed_count` — number — How many steps have failed to land so far.
  - `release` — object — The release axis — WHEN the bundle sends.
    - `kind` — string — The release mechanism for the bundle — immediate | scheduled | window | triggered (see the intent `release.kind`).
    - `not_before` — number | null — Earliest broadcast time (unix-ms) for a scheduled release; null otherwise.
    - `window_until` — number | null — Landing-window deadline (unix-ms) for a window release; null otherwise.
    - `arm_expires_at` — number | null — TTL (unix-ms) for a triggered release; null otherwise.
    - `armed` — boolean — True while a triggered bundle is held awaiting /fire.
    - `trigger_spec` — any | null — Your own resolve condition, echoed verbatim from create (triggered release only). Null on every other release kind.
  - `created_at` — number — When the bundle was created (unix-ms).
  - `updated_at` — number — When the bundle last changed (unix-ms).
  - `terminal_at` — number | null — When the bundle reached a terminal state; null while still running.
  - `transactions[]` — object[] — The bundle's steps, in order — each is a full intent object (same shape as GET /intents/:id).
    - `intent_id` — string
    - `version` — number — Monotonic revision, bumped on every state change. Pass it as `?cursor=<version>` to GET …/intents/:id?wait=true to long-poll for changes AFTER the version you already hold.
    - `status` — string — The lifecycle state — the field to poll. Held before broadcast: building (momentary, at create) · collecting (multisig — awaiting the remaining signatures) · scheduled (waiting on a future not_before / window) · armed (waiting on a trigger — POST /intents/:id/fire, or arm_expires_at). Live once broadcast, in order: submitted → processed → confirmed → finalized. Your effect applies (and the landed callback fires) when it reaches your commitment_target; Clear then keeps watching through finalized. Terminal: finalized (landed), invalid (rejected before broadcast after a drop-in acknowledgement — see `error`), failed (landed but rejected on chain — see `error`), or canceled (you stopped it — see the final event's reason). needs_resign is a RECOVERABLE stop, not terminal: the signed bytes expired and the intent waits — `resign_hint` carries the exact re-sign call.
    - `consumer` — string — The app/label you set on create — the console feed groups by it.
    - `kind` — string | null — Your optional free-text action label from create (e.g. "swap", "withdraw"); null when unset.
    - `cluster` — string — The Solana cluster this intent lives on — mainnet | devnet | testnet.
    - `commitment_target` — string — The landing gate you chose — confirmed | finalized. Clear applies your effect and fires the landed callback when the transaction reaches it, then always keeps watching through finalized.
    - `client_reference_id` — string | null — Your own id from create — searchable in the feed (?search=) and echoed in callbacks; null when you sent none.
    - `idempotency_key` — string — The dedup key for this intent (your idempotency_key, else the tx signature) — a resend under it collapses to this one record instead of double-sending.
    - `bundle_id` — string | null — The bundle this intent belongs to, or null for a standalone send.
    - `shape` — "single" | "scheduled" — single = broadcast at create; scheduled = held or windowed at create (any not_before, window_until, or trigger). The exact release kind is in `release`.
    - `submitted_via` — string — How it entered Clear — api (structured /intents/send) | rpc (drop-in sendTransaction).
    - `signature` — string | null — The transaction signature from the accepted wire bytes. When the chain has observed an attempt this is that observed signature; otherwise it is the latest accepted attempt, including held, expired, invalid, or canceled-before-broadcast transactions. Null only while a multisig transaction is still collecting signatures or no attempt exists.
    - `explorer_url` — string | null — A ready-to-open block-explorer link when the signature was broadcast and may have a chain record. Null before broadcast and for transactions known not to have landed, including invalid and needs_resign intents.
    - `origin` — any — The origin object you sent on create (label, optional return_url, opaque context), echoed back verbatim; null when you sent none.
    - `origin_geo` — object | null — Where the create request came from (network + GeoIP). `ip` is visible only to the intent's owner. Null until the geo write lands.
      - `country` — string | null
      - `continent` — string | null
      - `city` — string | null
      - `region` — string | null
      - `lat` — number | null
      - `lon` — number | null
      - `timezone` — string | null
      - `asn` — number | null
      - `as_org` — string | null
      - `ip` — string | null
    - `resolution` — object | null — Where and how it landed — the slot, the commitment reached, and the validator that included it. Null until landed; `leader` is null on the pure-RPC path.
      - `landed_slot` — number | null — The slot the transaction landed in; null until landed.
      - `landed_commitment` — string | null — The commitment reached at landing (confirmed | finalized); null until landed.
      - `landed_attempt_id` — string | null — Which attempt (see `attempts[]`) actually landed; null until landed.
      - `leader` — object | null — The validator that included the transaction — its identity, client software, stake and geo (all publicly verifiable on-chain). Null on the pure-RPC path or before landing.
    - `attempts[]` — object[] — Every signed version of this action Clear has driven — one per create / re-sign / bump, newest last. Each carries its own signature and blockhash so you can trace exactly which bytes were on the wire.
      - `attempt_no` — number — 1-based attempt index — bumped by each re-sign / bump.
      - `signature` — string — This attempt's transaction signature.
      - `blockhash` — string — The blockhash (or durable-nonce value) these bytes were signed against.
      - `last_valid_block_height` — number — The height past which this attempt's blockhash expires.
      - `status` — string — in_flight while the intent is live; a landed attempt carries its reached commitment (processed | confirmed | finalized). Once the intent terminalizes, an attempt that never landed tells the truth instead: superseded (a re-sign/bump replaced it, or another attempt landed) | invalid (Clear rejected the bytes before broadcast) | failed (the chain rejected this signature) | canceled (future re-broadcasts stopped) | expired (the bytes died — see resign_hint.reason).
    - `events[]` — object[] — The ordered transition timeline (oldest first) — every status change with its observation time and, where recorded, its reason. This is the audit trail behind the current `status`.
      - `at` — number — Unix-ms when Clear OBSERVED this transition — observation time, never the on-chain time (that lives in result.block_time). Same-second neighbors are real: e.g. a transaction accepted with an already-expired blockhash shows submitted and needs_resign within the same second.
      - `status` — string — The status this transition moved the intent INTO — the same vocabulary as the top-level `status`.
      - `reason` — string — Why this transition happened, when recorded — needs_resign: blockhash_expired | nonce_advanced | not_landing; canceled: caller_requested | arm_expired | window_closed | bundle_sealed | bundle_canceled.
    - `resign_hint` — object — Present ONLY while status is needs_resign: why it didn't land + the exact re-sign call with this intent's real id. The needs_resign callback payload embeds the same object.
      - `reason` — string — Why the signed bytes died: blockhash_expired | nonce_advanced | not_landing.
      - `action` — string — The one next action, in plain words.
      - `send` — object — A ready-to-send re-sign call, prefilled with this intent's real id.
      - `retry_collapse` — string — How retries collapse onto this intent, in the ingress door's own vocabulary (API/direct: intent_id + the client_reference_id/idempotency_key body fields; drop-in RPC: the X-Clear-Reference-Id header).
    - `fee_posture` — object — How this transaction's priority fee sat against the live fee market when Clear accepted it — deliberately coarse. Snapshotted once at acceptance, so create and every later read return the SAME value. ABSENT when the fee wasn't classified at acceptance (and bundle members carry no posture) — never guessed.
      - `level` — "none" | "low" | "typical" | "high" — The create-time price band: none (no priority fee set) | low | typical | high, relative to observed network demand when Clear accepted the transaction.
      - `note` — string — A factual description of that create-time price band.
    - `decoded` — any | null — The decoded transaction message (fee payer, instructions, account keys, address-lookup-table resolution) — a read-only view of the bytes you signed. Null before decode.
    - `result` — any | null — The on-chain outcome once landed — slot, block_time, fee (lamports), compute units consumed, balance/token deltas, and program logs. Null until landed.
    - `error` — any — The exact failure detail when status is invalid (pre-broadcast validation) or failed (the chain's error plus a plain-words reading); null otherwise.
    - `not_before` — number | null — The earliest unix-ms this intent may broadcast (the not_before you set), or null for an immediate send.
    - `release` — object — The release axis — WHEN the bytes broadcast, orthogonal to `shape`.
      - `kind` — string — The release mechanism — immediate (broadcast at create) | scheduled (held for not_before) | window (broadcast now, keep trying until window_until) | triggered (armed; broadcasts on /fire).
      - `window_until` — number | null — Landing-window deadline (unix-ms) for a window release; null otherwise.
      - `arm_expires_at` — number | null — TTL (unix-ms) for a triggered release — cancels cleanly if never fired; null otherwise.
      - `armed` — boolean — True while a triggered intent is held awaiting /fire.
      - `trigger_spec` — any | null — Your own resolve condition, echoed verbatim from create (triggered release only) — Clear stores it opaquely and never interprets it. Null on every other release kind.
    - `created_at` — number — When Clear created this intent (unix-ms).
    - `updated_at` — number — When this intent last changed (unix-ms).
    - `terminal_at` — number | null — When the intent reached a terminal state (finalized | invalid | failed | canceled); null while still live or in needs_resign.
  - `plan_edges[]` — object[] — The plan's dependency edges (step index → step index): a dag's real waits_on, a sequence's implicit chain, a parallel's empty fan.
    - `from_step` — number
    - `to_step` — number
  - `forensics` — object — The bounded opt-in bundle receipt with lifecycle facts, member receipt evidence, and covered/expected counts.
    - `bundle_id` — string
    - `shape` — "sequential" | "parallel" | "dag"
    - `status` — string
    - `cluster` — string
    - `on_failure` — string
    - `commitment_target` — string
    - `plan_edges[]` — object[] — The real dependency edges for a DAG, the implicit chain for a sequence, or an empty array for a parallel bundle.
      - `from_step` — integer
      - `to_step` — integer
    - `aggregate` — object
      - `members_total` — integer
      - `members_landed` — integer
      - `members_failed` — integer
      - `members_not_started` — integer
      - `total_fee` — object
      - `total_runtime_reported_compute` — object
      - `wall_clock_ms` — number | null
      - `slot_span` — object
      - `co_landing` — object
      - `scheduled_leaders` — object
      - `inter_step_latency[]` — object[]
      - `sibling_writable_overlap` — object
      - `stopped_at_step` — integer | null
    - `gantt[]` — object[]
      - `intent_id` — string
      - `step_index` — integer
      - `label` — string
      - `submitted_at` — number | null
      - `landed_at` — number | null
      - `slot` — integer | null
      - `scheduled_leader` — string | null
      - `status` — string
    - `members[]` — object[]
      - `intent_id` — string
      - `step_index` — integer
      - `lifecycle_status` — string
      - `report` — object | null

### `GET /v1/clear/feed` — List executions
- Action: `read` · MCP tool: `clear.feed`
- One row per execution — standalone intents and bundles alike. A bundle is a single row; drill into it for its steps. Filter by type and by outcome (comma-separated: in_flight, needs_you, scheduled, landed), and supply exact from/to boundaries to scope every outcome to the same creation-time window. Cursor-paginated newest first.
- Query param `type` ("single" | "release" | "bundle") — Filter by record shape: single (one immediate tx) · release (scheduled/triggered/window) · bundle. Omit for every shape.
- Query param `outcome` (string)
- Query param `cluster` ("mainnet" | "devnet" | "testnet") — Filter to one cluster. Omit for every cluster (the feed spans mainnet/devnet/testnet).
- Query param `source` ("api" | "rpc" | "direct") — Filter by how it was submitted: api (structured /intents·/bundles) · rpc (drop-in sendTransaction) · direct (submitted straight to Clear's send endpoint). Omit for every lane.
- Query param `search` (string) — Free-text match on your client_reference_id (the id you set on send). Omit for no search.
- Query param `cursor` (string) — Pagination cursor — pass the `next_cursor` from the previous page. Omit for the first (newest) page.
- Query param `limit` (integer) — Rows per page (1–200). Defaults to 50.
- 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[]
    - `kind` — "intent" | "bundle"
    - `id` — string
    - `type` — "single" | "release" | "bundle"
    - `variant` — string | null
    - `label` — string | null
    - `status` — string
    - `cluster` — string
    - `commitment_target` — string
    - `client_reference_id` — string | null — The caller's own reference id, or null. The feed's `search` matches this column, so a hit can show why the row matched.
    - `signature` — string | null — Accepted transaction signature for an intent; null for bundles or while a multisig transaction is still collecting signatures.
    - `explorer_url` — string | null — Explorer link only when the signature was broadcast and may have a chain record.
    - `not_before` — number | null
    - `tx_count` — number | null
    - `landed_count` — number | null
    - `child_statuses[]` — string[] | null
    - `submitted_via` — string
    - `landed_leader_identity` — string | null — Landed validator identity (intent only; null for bundles). Present on every cluster once landed.
    - `landed_leader_name` — string | null — Always null — no display-name source; the identity is the label on every cluster.
    - `landed_leader_client_family` — string | null — The client software of the validator that included the tx (e.g. agave, firedancer) — present once landed; null when no version is known.
    - `landed_leader_client_version` — string | null — The client version of the validator that included the tx (e.g. 2.1.11) — present once landed.
    - `created_at` — number
    - `updated_at` — number
    - `terminal_at` — number | null
  - `next_cursor` — string | null

### `GET /v1/clear/requests` — Inspect your API calls
- Action: `read` · MCP tool: `clear.requests`
- See exactly what you sent and what Clear answered on each of your recent API calls (`items`, newest first — the quote, the accept / needs_resign outcome, or the error), plus a per-endpoint performance summary — calls, error rate, and p50/p90/p99 latency. Exact from/to boundaries scope both rows and summary; range_days remains a compatibility summary window. Debug a quote or a send without adding your own logging. Filter by `endpoint` and `cluster`; the raw signed transaction is never captured, and secret-bearing calls record metadata only.
- 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/clear/callback-secret` — Callback secret status
- Action: `read` · MCP tool: `clear.callback_secret_status`
- Reports whether this workspace has a callback signing secret and when it was created or last rotated — never the secret itself. Check it before setting a `callback`: a secret must exist first.
- Response (JSON):
  - `exists` — boolean — Whether a callback signing secret is set for this workspace. It must be true before any intent may set a `callback` — mint one with POST /callback-secret.
  - `created_at` — number — Unix-ms the secret was first created; absent when none is set.
  - `rotated_at` — number | null — Unix-ms of the most recent rotation, or null if it has never been rotated; absent when no secret is set.

### `POST /v1/clear/callback-secret` — Create/rotate callback secret
- Action: `write` · MCP tool: `clear.callback_secret_rotate`
- Mints the HMAC secret Clear uses to sign your callbacks and returns it once — store it now, it's never re-readable. Required before any intent can set a `callback`.
- Response (JSON):
  - `secret` — string — The HMAC signing secret, returned ONCE and never re-readable — store it now. Clear signs every outbound callback with it (verify via the X-Clear-Signature header).
  - `rotated` — boolean — true if this replaced an existing secret (any previously-issued secret is now invalid); false on first creation.

### `GET /v1/clear/callbacks/health` — Callback delivery health
- Action: `read` · MCP tool: `clear.callbacks_health`
- Workspace-wide callback health across intents and bundles: work waiting, automatic retries, receiver capacity delays, and dead-lettered deliveries that exhausted Clear's automatic retry window. Use this as the callback outage signal.
- Response (JSON):
  - `state` — "healthy" | "retrying" | "action_required" — healthy (nothing outstanding) | retrying (deliveries are being re-attempted) | action_required (something dead-lettered — see dead_lettered).
  - `configured` — boolean
  - `open` — number
  - `queued` — number — Deliveries enqueued but not yet attempted. ALWAYS 0 today: box-owned delivery emits no enqueue signal, so this cannot be distinguished from `open` — do not alert on it.
  - `retrying` — number
  - `backpressured` — number — Deliveries deferred by a destination permit. ALWAYS 0 today: no signal is recorded for the deferral — do not alert on it.
  - `dead_lettered` — number
  - `oldest_open_at` — number | null
  - `next_retry_at` — number | null
  - `checked_at` — number

### `GET /v1/clear/intents/{id}/callbacks` — Intent callback log
- Action: `read` · MCP tool: `clear.intents_callbacks`
- Every callback Clear delivered for this intent — the destination url, the exact signed envelope, each attempt's status, response and latency, and the retry / dead-letter state. Your own delivery records.
- Path param `id` (string, required)
- Response (JSON):
  - `configured` — boolean
  - `deliveries[]` — object[]
    - `id` — string
    - `event` — string
    - `url` — string
    - `payload` — string | null
    - `request_headers` — object
    - `attempt_no` — number — Monotonic attempt count across Clear's automatic retries.
    - `last_status` — string | null
    - `response_body` — string | null
    - `response_time_ms` — number | null
    - `attempts[]` — object[]
      - `attempt_no` — number — Monotonic sequence number for this delivery attempt.
      - `at` — number
      - `status` — string
      - `response_body` — string | null
      - `response_time_ms` — number | null
      - `ok` — boolean
    - `delivered_at` — number | null
    - `dead_lettered` — boolean
    - `next_retry_at` — number | null
    - `backpressured_at` — number | null — When delivery was most recently delayed by receiver-capacity pressure without consuming an attempt.
    - `created_at` — number

### `GET /v1/clear/bundles/{id}/callbacks` — Bundle callback log
- Action: `read` · MCP tool: `clear.bundles_callbacks`
- Every bundle-level callback Clear delivered for this bundle — the bundle/step event, the step it was about, the destination url, the exact signed envelope, each attempt's status, response and latency, and the retry / dead-letter state. Your own delivery records.
- Path param `id` (string, required)
- Response (JSON):
  - `configured` — boolean
  - `deliveries[]` — object[]
    - `id` — string
    - `event` — string
    - `step_intent_id` — string | null
    - `url` — string
    - `payload` — string | null
    - `request_headers` — object
    - `attempt_no` — number — Monotonic attempt count across Clear's automatic retries.
    - `last_status` — string | null
    - `response_body` — string | null
    - `response_time_ms` — number | null
    - `attempts[]` — object[]
      - `attempt_no` — number — Monotonic sequence number for this delivery attempt.
      - `at` — number
      - `status` — string
      - `response_body` — string | null
      - `response_time_ms` — number | null
      - `ok` — boolean
    - `delivered_at` — number | null
    - `dead_lettered` — boolean
    - `next_retry_at` — number | null
    - `backpressured_at` — number | null — When delivery was most recently delayed by receiver-capacity pressure without consuming an attempt.
    - `created_at` — number

### `GET /v1/clear/avoid-list` — Get your avoid list
- Action: `read` · MCP tool: `clear.avoid_list`
- The one delivery control you set, per network (?cluster=mainnet|devnet|testnet): the validators, networks (AS), countries, and client software Clear will never send your transactions through on that cluster. Everything else about delivery, Clear decides for you.
- Query param `cluster` ("mainnet" | "devnet" | "testnet", required) — Which network's avoid list to read.
- Response (JSON):
  - `avoid` — object
    - `identities[]` — string[]
    - `asns[]` — number[]
    - `countries[]` — string[]
    - `clients[]` — string[]
  - `updated_at` — number | null — Unix-ms of the last change — null if never set. Changes apply on the very next send.

### `POST /v1/clear/avoid-list` — Update your avoid list
- Action: `write` · MCP tool: `clear.avoid_list_set`
- Replaces the avoid list for the given cluster. It takes effect on your very next send — an avoided validator is never routed through and shows in that send's result as excluded, with the reason. Requires write access.
- Request body (JSON, required):
  - `cluster` — "mainnet" | "devnet" | "testnet" (required) — Which network's avoid list to replace.
  - `avoid` — object (required) — The full avoid list — this REPLACES the stored list (read-modify-write).
- Response (JSON):
  - `avoid` — object
    - `identities[]` — string[]
    - `asns[]` — number[]
    - `countries[]` — string[]
    - `clients[]` — string[]
  - `updated_at` — number | null — Unix-ms of the last change — null if never set. Changes apply on the very next send.

### `GET /v1/clear/endpoints` — Send endpoints
- Action: `read` · MCP tool: `clear.endpoints`
- The send base URL per cluster — https://clear-<cluster>.k256.xyz. SDKs cache this list and send transactions there directly. Reads, status, and cancel stay on https://api.k256.xyz.
- Response (JSON):
  - `direct_endpoints[]` — object[]
    - `cluster` — string
    - `url` — string — The single geo send base for the cluster, e.g. https://clear-devnet.k256.xyz.

### `GET /v1/clear/analytics` — Execution analytics
- Action: `read` · MCP tool: `clear.analytics`
- Your selected-window execution analytics: standing (total, landed, failed, in-flight, success rate), dynamically bucketed volume and landing latency, equal-duration KPI comparisons, most-invoked programs, priority fees, and shape mix. Exact from/to boundaries scope every selected-window field; compatibility 24h/daily fields remain available. All computed over your own executions.
- Query param `range_days` (integer) — Compatibility trailing window in days (1–90). Exact from/to takes precedence. Defaults to 14.
- Query param `cluster` ("mainnet" | "devnet" | "testnet") — The cluster to report on. Omit for the workspace total across all clusters.
- 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):
  - `range_days` — number
  - `window` — object — Exact [from,to) unix-ms window and chart bucket used for every selected-window aggregate.
    - `from` — number
    - `to` — number
    - `bucket_ms` — number
  - `status` — object — Landing standing for executions created in the selected window — the at-a-glance totals and attention buckets that filter the Console feed over the same exact rows.
    - `total_executions` — number — Standalone intents accepted for execution plus bundles in the selected window; pre-broadcast invalid acknowledgements are reported separately.
    - `landed` — number — How many landed — intents (confirmed/finalized) + bundles (completed / completed_with_failures).
    - `invalid` — number — Drop-in sends rejected before broadcast after their signature acknowledgement; excluded from landing-rate and fee metrics.
    - `failed` — number — Standalone intents that landed but were rejected on chain.
    - `in_flight` — number — Intents + bundles created in the selected window that are still actively landing.
    - `success_rate` — number | null — landed / (landed + failed + bundles_halted) — a halted bundle counts as failed-to-land; null when nothing has settled yet.
    - `needs_resign` — number — Intents waiting on your re-signature (recoverable stop — the bytes expired).
    - `collecting` — number — Intents still gathering their remaining transaction signatures.
    - `held` — number — Scheduled/armed intents + bundles — waiting on a time or trigger, not failed.
    - `bundles_halted` — number — Bundles stopped by on_failure=stop after a step failed — need attention.
  - `kpis` — object
    - `executions` — object — Executions in the selected window, compared with the immediately preceding equal-duration window.
      - `value` — number | null
      - `delta` — number | null
    - `executions_24h` — object
      - `value` — number | null
      - `delta` — number | null
    - `landing_rate_window` — object
      - `value` — number | null
      - `delta` — number | null
    - `landing_rate` — object
      - `value` — number | null
      - `delta` — number | null
    - `avg_land_ms_window` — object
      - `value` — number | null
      - `delta` — number | null
    - `avg_land_ms` — object
      - `value` — number | null
      - `delta` — number | null
    - `in_flight` — number
    - `p50_land_ms_window` — number | null
    - `p50_land_ms` — number | null
  - `timeseries[]` — object[] — Compatibility UTC daily series.
    - `ts` — number
    - `total` — number
    - `landed` — number
    - `failed` — number
    - `p50_ms` — number | null
  - `series[]` — object[] — Dynamically bucketed selected-window series; bucket_ms is declared in window.
    - `ts` — number
    - `total` — number
    - `landed` — number
    - `failed` — number
    - `p50_ms` — number | null
  - `top_programs[]` — object[]
    - `label` — string
    - `value` — number
  - `by_shape` — object
    - `single` — number
    - `scheduled` — number
    - `bundle` — number
  - `fees` — object — Priority-fee efficiency over your OWN landed sends (from the create-time economics snapshot) — the OUTCOME 'are you paying efficiently / how did your fee sit vs the market', not quote-door usage. Same exact selected window + cluster as the op.
    - `sends` — number — Landed sends in the range that carry a known compute-unit price — the denominator for the shares and median below. 0 when you have no priced landed sends (the whole block is then an honest empty: null shares/median, 0 total).
    - `paid_fee_share` — number | null — Fraction of those landed sends that carried a priority fee (cu_price > 0). Null when sends = 0.
    - `zero_fee_share` — number | null — Fraction that carried NO priority fee (cu_price = 0). paid_fee_share + zero_fee_share = 1. Null when sends = 0.
    - `median_priority_fee_micro_lamports` — number | null — Median compute-unit price (micro-lamports per CU) carried by landed sends. Null when sends = 0. This is a factual price position, not proof that a higher or lower fee was necessary.
    - `total_priority_fee_lamports` — number — Budgeted priority fee across landed sends: Σ ceil(cu_price × cu_limit / 1_000_000). This is the ceiling you authorized (cu_limit), NOT the CU-consumed actual spend — see per-intent forensics for the exact split. 0 when no landed send carried a priced cu_limit.
    - `fee_posture_mix` — object — How each landed send's fee sat vs the live market at acceptance — the same coarse posture (none/low/typical/high) the intent DTO's fee_posture carries, counted across the range. Outcome, not fee-market machinery.
      - `none` — number — No priority fee set.
      - `low` — number — In the low band for network demand when Clear accepted it.
      - `typical` — number — In line with network demand.
      - `high` — number — In the high band for network demand when Clear accepted it.
      - `unclassified` — number — Landed with an economics row but no classification (the fee oracle was cold at create) — honest, never bucketed into a posture.
    - `daily[]` — object[] — Daily paid-share + median-fee trend, gap-filled to match `timeseries` — is your fee efficiency drifting over the range?
      - `ts` — number — Day bucket (unix-ms, UTC midnight) — aligned to the main `timeseries` days.
      - `paid_fee_share` — number | null — Paid-fee share among that day's priced landed sends; null on a day with none.
      - `median_priority_fee_micro_lamports` — number | null — Median cu_price that day; null on a day with none.
    - `series[]` — object[] — Dynamically bucketed fee trend for interactive clients.
      - `ts` — number — Bucket start (unix-ms); width is window.bucket_ms.
      - `paid_fee_share` — number | null
      - `median_priority_fee_micro_lamports` — number | null
  - `programs_scanned` — number

### `GET /v1/clear/senders/reputation` — Your landing standing
- Action: `read` · MCP tool: `clear.sender_reputation`
- Your workspace's landing standing on the cluster over the exact selected window — how many of your sends landed, your priority-fee share (paid vs zero-fee), and one recommended action (e.g. raise your fee to land better when the network is busy). Informational only — nothing is throttled without your action. Includes a dynamically bucketed landings trend. Self-scoped; no activity returns an explicit empty, never a fabricated number.
- Query param `cluster` ("mainnet" | "devnet" | "testnet") — The cluster to read your sender standing for. Defaults to mainnet — standing is per-cluster.
- Query param `range` ("24h" | "7d" | "30d" | "90d" | "365d") — Compatibility trend window. Exact from/to takes precedence.
- 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):
  - `cluster` — string
  - `range` — string — Compatibility label for the selected window.
  - `window` — object
    - `from` — number
    - `to` — number
    - `bucket_ms` — number
  - `standing` — object | null — Compatibility rolling-1h standing, or null when there was no activity / data is unavailable.
    - `total` — number
    - `paid_fee_share` — number — Share of those landings that carried a real priority fee (0..1).
    - `zero_fee_share` — number — Share that carried no priority fee (0..1). paid_fee_share + zero_fee_share = 1.
    - `first_seen` — number | null — Unix-ms of the earliest landing in the window.
    - `last_seen` — number | null — Unix-ms of the most recent landing in the window.
    - `recommended_action` — object — Your one recommended action for this cluster — informational only; nothing is throttled without your action.
      - `action` — "none" | "add_priority_fee" — What to do, if anything — none (no action needed) | add_priority_fee (raise your compute-unit price to improve landing when the network is busy).
      - `note` — string — The recommendation in plain words.
  - `window_standing` — object | null — Standing computed over the exact selected window, or null when there was no activity / data is unavailable.
    - `total` — number
    - `paid_fee_share` — number — Share of those landings that carried a real priority fee (0..1).
    - `zero_fee_share` — number — Share that carried no priority fee (0..1). paid_fee_share + zero_fee_share = 1.
    - `first_seen` — number | null — Unix-ms of the earliest landing in the window.
    - `last_seen` — number | null — Unix-ms of the most recent landing in the window.
    - `recommended_action` — object — Your one recommended action for this cluster — informational only; nothing is throttled without your action.
      - `action` — "none" | "add_priority_fee" — What to do, if anything — none (no action needed) | add_priority_fee (raise your compute-unit price to improve landing when the network is busy).
      - `note` — string — The recommendation in plain words.
  - `series[]` — object[] — Landings trend for the cluster over the selected range. Empty when no activity / data is unavailable.
    - `t` — number — Bucket start (unix-ms).
    - `landings` — number — Your landings in the bucket.
