# 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.
- 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, the signature returns immediately. Clear then verifies before broadcast and records terminal status invalid at X-Clear-Status-Url if verification fails. 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>). Clear adds X-Clear-Intent-Id, X-Clear-Status-Url, X-Clear-Cluster, X-Clear-Signature, X-Clear-Dedup, and X-Clear-Hint response headers. Identity & idempotency: on the drop-in, identical bytes ALWAYS collapse to one durable intent 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>, 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 post-ack invalidity. 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` for best-effort attribution; it is optional and never blocks a send. 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. GET /v1/clear/landing/clients is the live census of what the network runs right now (client ids per the canonical solana-validator-client-ids registry: agave, jito_agave, agave_bam, rakurai, harmonic_agave, harmonic_frankendancer, frankendancer, firedancer, raiku, … plus client_<n> for ids not yet named) with stake shares — avoid.clients takes those family tokens. 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` — string — The state at acknowledgement time: submitted, collecting, scheduled, or armed. 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 for best-effort quote→send attribution. Never required to send, never validated on admission, fail-open (unknown/expired/malformed never blocks 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.
- 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 Clear is driving (or drove). Null only while nothing was ever broadcast — a canceled-after-broadcast intent KEEPS its signature, so you can check the chain yourself during the post-cancel watch window.
  - `explorer_url` — string | null — A ready-to-open block-explorer link for the signature; null until a signature exists.
  - `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 coarse posture: none (no priority fee set — paying transactions land first under load) | low (below current demand — landing may be slower) | typical (in line with demand) | high (above demand — positioned to land fast).
    - `note` — string — The signal in plain words, with the next step when one helps (set or raise the compute-unit price; /bump on a durable-nonce transaction).
  - `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 Clear is driving (or drove). Null only while nothing was ever broadcast — a canceled-after-broadcast intent KEEPS its signature, so you can check the chain yourself during the post-cancel watch window.
  - `explorer_url` — string | null — A ready-to-open block-explorer link for the signature; null until a signature exists.
  - `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 coarse posture: none (no priority fee set — paying transactions land first under load) | low (below current demand — landing may be slower) | typical (in line with demand) | high (above demand — positioned to land fast).
    - `note` — string — The signal in plain words, with the next step when one helps (set or raise the compute-unit price; /bump on a durable-nonce transaction).
  - `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 Clear is driving (or drove). Null only while nothing was ever broadcast — a canceled-after-broadcast intent KEEPS its signature, so you can check the chain yourself during the post-cancel watch window.
  - `explorer_url` — string | null — A ready-to-open block-explorer link for the signature; null until a signature exists.
  - `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 coarse posture: none (no priority fee set — paying transactions land first under load) | low (below current demand — landing may be slower) | typical (in line with demand) | high (above demand — positioned to land fast).
    - `note` — string — The signal in plain words, with the next step when one helps (set or raise the compute-unit price; /bump on a durable-nonce transaction).
  - `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` — string — 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 Clear is driving (or drove). Null only while nothing was ever broadcast — a canceled-after-broadcast intent KEEPS its signature, so you can check the chain yourself during the post-cancel watch window.
    - `explorer_url` — string | null — A ready-to-open block-explorer link for the signature; null until a signature exists.
    - `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 coarse posture: none (no priority fee set — paying transactions land first under load) | low (below current demand — landing may be slower) | typical (in line with demand) | high (above demand — positioned to land fast).
      - `note` — string — The signal in plain words, with the next step when one helps (set or raise the compute-unit price; /bump on a durable-nonce transaction).
    - `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` — string — 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 Clear is driving (or drove). Null only while nothing was ever broadcast — a canceled-after-broadcast intent KEEPS its signature, so you can check the chain yourself during the post-cancel watch window.
    - `explorer_url` — string | null — A ready-to-open block-explorer link for the signature; null until a signature exists.
    - `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 coarse posture: none (no priority fee set — paying transactions land first under load) | low (below current demand — landing may be slower) | typical (in line with demand) | high (above demand — positioned to land fast).
      - `note` — string — The signal in plain words, with the next step when one helps (set or raise the compute-unit price; /bump on a durable-nonce transaction).
    - `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 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 empirical forensic report (chain truth only) inline as `forensics`. Omit for the light hot-poll path — no forensics 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 Clear is driving (or drove). Null only while nothing was ever broadcast — a canceled-after-broadcast intent KEEPS its signature, so you can check the chain yourself during the post-cancel watch window.
  - `explorer_url` — string | null — A ready-to-open block-explorer link for the signature; null until a signature exists.
  - `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 coarse posture: none (no priority fee set — paying transactions land first under load) | low (below current demand — landing may be slower) | typical (in line with demand) | high (above demand — positioned to land fast).
    - `note` — string — The signal in plain words, with the next step when one helps (set or raise the compute-unit price; /bump on a durable-nonce transaction).
  - `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 empirical forensic report (chain truth only) — present ONLY when you pass ?include=forensics. Block landing (slot, the validator that produced it, position, compute), the exact base/priority fee split, the in-block fee percentile, the fee market around the landing, and the observed effect (balance/token deltas + CPI tree). Pending (never zeroed) until the tx lands.
    - `intent_id` — string
    - `signature` — string | null
    - `cluster` — string
    - `status` — string
    - `commitment_target` — string
    - `explorer_url` — string | null
    - `landed` — boolean
    - `pending_reason` — string | null
    - `block` — any | null
    - `compute` — any | null
    - `fee` — any | null
    - `fee_context` — any | null
    - `fee_market` — any | null
    - `effect` — any | null
    - `identifiers` — any

### `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` — string — 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 Clear is driving (or drove). Null only while nothing was ever broadcast — a canceled-after-broadcast intent KEEPS its signature, so you can check the chain yourself during the post-cancel watch window.
    - `explorer_url` — string | null — A ready-to-open block-explorer link for the signature; null until a signature exists.
    - `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 coarse posture: none (no priority fee set — paying transactions land first under load) | low (below current demand — landing may be slower) | typical (in line with demand) | high (above demand — positioned to land fast).
      - `note` — string — The signal in plain words, with the next step when one helps (set or raise the compute-unit price; /bump on a durable-nonce transaction).
    - `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 aggregate forensic report (whole and parts) — present ONLY when you pass ?include=forensics. Totals, wall-clock and slot spans, co-landing detection, inter-step latency, and sibling write-lock contention, plus every step's full single-transaction report.
    - `bundle_id` — string
    - `shape` — string
    - `status` — string
    - `cluster` — string
    - `on_failure` — string
    - `commitment_target` — string
    - `plan_edges[]` — object[] — For a dag bundle, the per-step dependency edges (from_step → to_step); empty for sequential/parallel.
      - `from_step` — number
      - `to_step` — number
    - `aggregate` — any
    - `gantt[]` — any[]
    - `steps[]` — object[]
      - `intent_id` — string
      - `signature` — string | null
      - `cluster` — string
      - `status` — string
      - `commitment_target` — string
      - `explorer_url` — string | null
      - `landed` — boolean
      - `pending_reason` — string | null
      - `block` — any | null
      - `compute` — any | null
      - `fee` — any | null
      - `fee_context` — any | null
      - `fee_market` — any | null
      - `effect` — any | null
      - `identifiers` — any

### `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), 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` (integer) — 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.
- 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
    - `explorer_url` — string | null
    - `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 over the last `range_days` (`by_endpoint`, default 14). Debug a quote or a send without adding your own logging. Filter `items` 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) — Window (in days, 1–90) for the `by_endpoint` performance summary. Defaults to 14.
- 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 deliveries that need a manual resend. Use this as the callback outage signal.
- Response (JSON):
  - `state` — "healthy" | "delivering" | "retrying" | "action_required"
  - `configured` — boolean
  - `open` — number
  - `queued` — number
  - `retrying` — number
  - `backpressured` — number
  - `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 automatic retries and manual resends.
    - `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
    - `created_at` — number

### `POST /v1/clear/intents/{id}/callbacks/{delivery_id}/resend` — Resend a callback
- Action: `write` · MCP tool: `clear.intents_callbacks_resend`
- Re-sends one delivery to your endpoint immediately and returns the refreshed log with the new attempt's status, latency, and response. Use it after fixing your receiver; the bytes are unchanged, so the receiver can de-dupe on the delivery id.
- Path param `id` (string, required)
- Path param `delivery_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 automatic retries and manual resends.
    - `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
    - `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 automatic retries and manual resends.
    - `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
    - `created_at` — number

### `POST /v1/clear/bundles/{id}/callbacks/{delivery_id}/resend` — Resend a bundle callback
- Action: `write` · MCP tool: `clear.bundles_callbacks_resend`
- Re-sends one bundle delivery to your endpoint immediately and returns the refreshed log with the new attempt's status, latency, and response. Use it after fixing your receiver; the bytes are unchanged.
- Path param `id` (string, required)
- Path param `delivery_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 automatic retries and manual resends.
    - `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
    - `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 execution analytics: current standing (total, landed, failed, in-flight, success rate), a daily volume and landing-latency series over range_days, 24h KPIs with deltas, your most-invoked programs, and the mix by shape. All computed over your own executions.
- Query param `range_days` (integer) — Trailing window in days (1–90). Defaults to 14.
- Query param `cluster` ("mainnet" | "devnet" | "testnet") — The cluster to report on. Defaults to mainnet.
- Response (JSON):
  - `range_days` — number
  - `status` — object — The current landing-standing snapshot for the workspace — the at-a-glance totals (total / landed / invalid / failed / in-flight) and success rate, plus the attention buckets (needs-you / collecting / held / halted) the console surfaces so you see what needs action without filtering the feed.
    - `total_executions` — number — Standalone intents accepted for execution plus bundles in the trailing 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 — Actively landing right now — intents + bundles.
    - `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 — Bundles still gathering their remaining member 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_24h` — object
      - `value` — number | null
      - `delta` — number | null
    - `landing_rate` — object
      - `value` — number | null
      - `delta` — number | null
    - `avg_land_ms` — object
      - `value` — number | null
      - `delta` — number | null
    - `in_flight` — number
    - `p50_land_ms` — number | null
    - `rebroadcasts` — number
  - `timeseries[]` — object[]
    - `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 range_days + 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) you actually carried on landed sends. Null when sends = 0. A low median while you're still landing is the signal you may be overpaying-free; a high one under contention is what buys speed.
    - `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 — Below network demand when Clear accepted it — landing can be slower.
      - `typical` — number — In line with network demand.
      - `high` — number — Above network demand — positioned to land fast.
      - `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.
  - `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 last hour — 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 an hourly 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") — The window for your landings trend (canonical D/W/M/Q/Y). Defaults to 24h. Your standing summary is always the rolling 1h; only the landings trend honors this range.
- Response (JSON):
  - `cluster` — string
  - `range` — string — The window the landings trend covers (24h | 7d | 30d | 90d | 365d).
  - `standing` — object | null — Your workspace's landing standing for the cluster (rolling 1h), or null when you have no send activity in the window / data is unavailable (explicit empty — never fabricated).
    - `total` — number — Your landings accepted in the rolling 1h window.
    - `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[] — Hourly landings trend for the cluster over the selected range. Empty when no activity / data is unavailable.
    - `t` — number — Bucket start (unix-ms, hourly).
    - `landings` — number — Your landings in the hour.
