@botanary/agent 0.1.0-alpha.1 → 0.1.0-alpha.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +43 -5
  3. package/dist/errors.d.ts +1 -38
  4. package/dist/exact-action.d.ts +61 -8
  5. package/dist/fingerprint.d.ts +0 -15
  6. package/dist/generated/routes.d.ts +0 -1
  7. package/dist/generated/schema.d.ts +8 -1092
  8. package/dist/http-path.d.ts +0 -81
  9. package/dist/index.d.ts +1 -2
  10. package/dist/index.js +2 -7
  11. package/dist/pairing-code.d.ts +0 -23
  12. package/dist/registration.d.ts +0 -3
  13. package/dist/runtime.d.ts +3 -128
  14. package/dist/signer.d.ts +0 -7
  15. package/dist/transport.d.ts +0 -3
  16. package/dist/validation.d.ts +4 -3
  17. package/dist/views.d.ts +0 -54
  18. package/package.json +6 -2
  19. package/dist/errors.d.ts.map +0 -1
  20. package/dist/errors.js +0 -40
  21. package/dist/errors.js.map +0 -1
  22. package/dist/exact-action.d.ts.map +0 -1
  23. package/dist/exact-action.js +0 -178
  24. package/dist/exact-action.js.map +0 -1
  25. package/dist/fingerprint.d.ts.map +0 -1
  26. package/dist/fingerprint.js +0 -47
  27. package/dist/fingerprint.js.map +0 -1
  28. package/dist/generated/routes.d.ts.map +0 -1
  29. package/dist/generated/routes.js +0 -92
  30. package/dist/generated/routes.js.map +0 -1
  31. package/dist/generated/schema.d.ts.map +0 -1
  32. package/dist/generated/schema.js +0 -2
  33. package/dist/generated/schema.js.map +0 -1
  34. package/dist/http-path.d.ts.map +0 -1
  35. package/dist/http-path.js +0 -201
  36. package/dist/http-path.js.map +0 -1
  37. package/dist/index.d.ts.map +0 -1
  38. package/dist/index.js.map +0 -1
  39. package/dist/pairing-code.d.ts.map +0 -1
  40. package/dist/pairing-code.js +0 -60
  41. package/dist/pairing-code.js.map +0 -1
  42. package/dist/registration.d.ts.map +0 -1
  43. package/dist/registration.js +0 -62
  44. package/dist/registration.js.map +0 -1
  45. package/dist/runtime.d.ts.map +0 -1
  46. package/dist/runtime.js +0 -559
  47. package/dist/runtime.js.map +0 -1
  48. package/dist/signer.d.ts.map +0 -1
  49. package/dist/signer.js +0 -13
  50. package/dist/signer.js.map +0 -1
  51. package/dist/transport.d.ts.map +0 -1
  52. package/dist/transport.js +0 -135
  53. package/dist/transport.js.map +0 -1
  54. package/dist/validation.d.ts.map +0 -1
  55. package/dist/validation.js +0 -108
  56. package/dist/validation.js.map +0 -1
  57. package/dist/views.d.ts.map +0 -1
  58. package/dist/views.js +0 -2
  59. package/dist/views.js.map +0 -1
@@ -8,13 +8,6 @@ export interface paths {
8
8
  };
9
9
  get?: never;
10
10
  put?: never;
11
- /**
12
- * Begin an agent pairing - the agent signs to prove it holds the key
13
- * @description Public endpoint (no session required). The agent signs over `(code || timestamp)`, proving it holds the private key for the claimed public key. We verify the signature recovers to that key and hold the proof until the account owner claims it via `POST /agents/{code}/claim`.
14
- * The signature is the load-bearing check: a pairing code seen over someone's shoulder is worthless on its own. **Claiming binds THE AGENT THAT SIGNED, never the person who typed the code.** That is what makes agent pairing password-free and rotation-free (design §5-41): there is no secret to write down, type into the wrong window, or rotate later.
15
- * Codes are single-use and expire in minutes; the timestamp window is ±5 minutes so a captured proof cannot be replayed later. Pending pairings are in-memory coordination state (not persisted) - a backend restart loses pending pairings, which simply means the agent regenerates a code and signs again.
16
- * Refused with 400 when: - The timestamp is outside the ±5-minute window (too old or too far in the future). - The signature does not recover to the claimed public key (the proof belongs to a different agent). - The signature is over a different code than the one claimed (a proof from elsewhere).
17
- */
18
11
  post: operations["pairAgent"];
19
12
  delete?: never;
20
13
  options?: never;
@@ -31,10 +24,6 @@ export interface paths {
31
24
  };
32
25
  get?: never;
33
26
  put?: never;
34
- /**
35
- * Issue a nonce for an agent to sign, to mint a session
36
- * @description Public endpoint (no session required). Returns a fresh, single-use, server-issued nonce for the named agent address. The agent signs this exact nonce with its private key and exchanges the signature for a session token via `POST /agents/session`. The nonce expires after a few minutes if unused. Challenges are shared across API replicas and bind the connected agent and its authentication generation. A newer challenge for the address replaces the prior challenge.
37
- */
38
27
  post: operations["issueAgentSessionNonce"];
39
28
  delete?: never;
40
29
  options?: never;
@@ -51,10 +40,6 @@ export interface paths {
51
40
  };
52
41
  get?: never;
53
42
  put?: never;
54
- /**
55
- * Mint an agent session by signing a server-issued nonce
56
- * @description Public endpoint (no session required). Exchanges a signature over the nonce from `POST /agents/session/nonce` for a short-lived bearer token (`ags_...`) that grants access to every `@AgentAllowed()` route, scoped to whichever account this agent is connected to (`POST /agents/{code}/claim`). Refused with 401 when the nonce is missing/expired, the signature does not recover to this agent's key, or the address names no LIVE connected agent (never connected, or disconnected). Key verification precedes atomic challenge consumption and hash-only session creation. Concurrent replay has one winner. Disablement invalidates sessions and earlier authentication challenges across replicas and process restarts.
57
- */
58
43
  post: operations["mintAgentSession"];
59
44
  delete?: never;
60
45
  options?: never;
@@ -69,12 +54,6 @@ export interface paths {
69
54
  path?: never;
70
55
  cookie?: never;
71
56
  };
72
- /**
73
- * An agent's own question - who am I, what account, and what may I do
74
- * @description Requires an agent session (`@AgentAllowed()`) - an owner session gets 404, since the question ("what can THIS agent do") has no owner-side referent. Answers three things at once: this agent's own identity (id/name/address/fingerprint/connectedAt, mirroring `ConnectedAgent`), the account it is bound to, and its live grant if one exists - including the `permissionId` a delegated spend needs, the grant's bounds (`policySet`) and plain-language sentence (`humanSummary`), and its current `status`.
75
- * When the owner has granted this agent nothing yet, `grant` is `null` - an honest, explicit answer (not an error, not an empty object): the agent can still read and draft under every `@AgentAllowed()` route, and every attempt to spend is refused for lack of authority, never silently.
76
- * This is a convenience read, never the check - the only boundary that counts is on-chain. An agent (or whoever built it) can use this to learn its bounds WITHOUT hitting them first, but a bug or a lie in this response changes nothing about what the agent can actually get away with.
77
- */
78
57
  get: operations["getAgentSelf"];
79
58
  put?: never;
80
59
  post?: never;
@@ -91,17 +70,8 @@ export interface paths {
91
70
  path?: never;
92
71
  cookie?: never;
93
72
  };
94
- /**
95
- * List agent requests for this account or agent
96
- * @description The owner sees all requests for their account. An agent session sees only its own requests. Requests expire in minutes; an expired request stays in the list marked `expired` rather than vanishing.
97
- */
98
73
  get: operations["listAgentRequests"];
99
74
  put?: never;
100
- /**
101
- * Raise a request when hitting a delegation bound
102
- * @description The agent has attempted an action that exceeds its delegated grant. Instead of a bare decline, it raises a request carrying WHICH bound was crossed (§6-40) - derived from the agent's live grant and the proposed calls, never a generic reason. An agent with no grant at all gets `no_policies_set`, never a guessed cap; calls this cannot decode into a token/amount/recipient get `malformed_call`, never a plausible guess. A revoked agent cannot raise requests - its session is already gone (§6-38).
103
- * Refused with 400 if the proposed calls are already inside the grant - there is nothing to request, since the action can be performed directly under the delegation.
104
- */
105
75
  post: operations["raiseAgentRequest"];
106
76
  delete?: never;
107
77
  options?: never;
@@ -116,10 +86,6 @@ export interface paths {
116
86
  path?: never;
117
87
  cookie?: never;
118
88
  };
119
- /**
120
- * Get the unified multi-stablecoin balance (presentation-only)
121
- * @description A single unified balance over the owner's own per-token holdings, with each token carrying its live peg status. **Presentation + spendability only - never pooled or custodial** (FR-S1).
122
- */
123
89
  get: operations["getUnifiedBalance"];
124
90
  put?: never;
125
91
  post?: never;
@@ -136,7 +102,6 @@ export interface paths {
136
102
  path?: never;
137
103
  cookie?: never;
138
104
  };
139
- /** List supported chains */
140
105
  get: operations["listChains"];
141
106
  put?: never;
142
107
  post?: never;
@@ -153,10 +118,6 @@ export interface paths {
153
118
  path?: never;
154
119
  cookie?: never;
155
120
  };
156
- /**
157
- * List gas methods with per-method balances (FR-8)
158
- * @description Available gas methods for a chain. At least one of `chainId` (EVM) or `key` (Solana/Stellar) is required - gas availability is per-chain (USDC gas exists only on Base and Arbitrum), so a request with neither is rejected rather than answered about some default chain. If both are supplied, `key` takes priority. Every action MUST remain executable at native balance = 0 via sponsored / USDC / USDT.
159
- */
160
121
  get: operations["listGasMethods"];
161
122
  put?: never;
162
123
  post?: never;
@@ -173,7 +134,6 @@ export interface paths {
173
134
  path?: never;
174
135
  cookie?: never;
175
136
  };
176
- /** Get the owner's smart account */
177
137
  get: operations["getAccount"];
178
138
  put?: never;
179
139
  post?: never;
@@ -188,18 +148,12 @@ export interface paths {
188
148
  query?: never;
189
149
  header?: never;
190
150
  path: {
191
- /** @example d1 */
192
151
  delegationId: components["parameters"]["DelegationId"];
193
152
  };
194
153
  cookie?: never;
195
154
  };
196
155
  get?: never;
197
156
  put?: never;
198
- /**
199
- * Build a bounded delegated action (the binding-boundary demonstration)
200
- * @description Builds an UNSIGNED Smart Sessions op - a bounded transfer performed with this delegation's **session key** (not the owner). The op runs raw Kernel `execute` under the SS validator lane; Smart Sessions re-checks it against the granted policies in its validation phase. In-scope executes; out-of-scope (wrong recipient / over the per-action or cumulative cap) is rejected pre-inclusion. The client signs the returned hash with the session key it holds and relays via `POST /userops`. The API never signs.
201
- * **`@AgentAllowed()`** - this is the connected agent's own build lane (Flow 7c: an outside agent proposing a payment under its grant), the ONLY lane that builds in the session nonce key with fixed native gas a session-key signature can actually validate. An agent session may only build against the delegation that names ITS OWN address as `delegateeAddress` - naming a *different* agent's delegation id is refused with 403, not merely refused on-chain later (§6-34: "A grant names one agent, and no other can draw on it"). An owner session is unaffected: it may still build against any delegation on its own account, exactly as before.
202
- */
203
157
  post: operations["buildDelegatedAction"];
204
158
  delete?: never;
205
159
  options?: never;
@@ -216,10 +170,6 @@ export interface paths {
216
170
  };
217
171
  get?: never;
218
172
  put?: never;
219
- /**
220
- * Build an agent action using exact base units
221
- * @description Requires the grant-bound agent session. The account ID, account address, chain and asset are explicit and must match the stored delegation. Native gas only. App keys and console/owner sessions are refused. On-chain capabilities remain testnet-only; this endpoint does not create a grant.
222
- */
223
173
  post: operations["buildExactDelegatedAction"];
224
174
  delete?: never;
225
175
  options?: never;
@@ -236,11 +186,6 @@ export interface paths {
236
186
  };
237
187
  get?: never;
238
188
  put?: never;
239
- /**
240
- * Relay a client-signed UserOp to the bundler
241
- * @description The single relay boundary. Accepts a `SignedUserOp` (the client attached the owner's, or a connected agent's own session key's, signature to a previously built op) and submits it to the bundler/paymaster. Returns a receipt to poll. **This is availability, never authority** - the server cannot alter the signed op's effect, and the on-chain policy bounds it regardless.
242
- * **`@AgentAllowed()`** - a connected agent relays here too, signing with its own session key (e.g. after `POST /delegations/{id}/actions`). This route never interprets or authorizes what the op DOES; it only forwards a signed payload, so opening it to an agent adds no new authority - a signature over the wrong session key fails Smart Sessions' own on-chain check exactly as an owner op signed by the wrong EOA already does.
243
- */
244
189
  post: operations["submitUserOp"];
245
190
  delete?: never;
246
191
  options?: never;
@@ -257,7 +202,6 @@ export interface paths {
257
202
  };
258
203
  cookie?: never;
259
204
  };
260
- /** Track a submitted UserOp */
261
205
  get: operations["getUserOp"];
262
206
  put?: never;
263
207
  post?: never;
@@ -274,10 +218,6 @@ export interface paths {
274
218
  path?: never;
275
219
  cookie?: never;
276
220
  };
277
- /**
278
- * Reconcile an agent operation by its original hash
279
- * @description Requires the agent session that submitted the operation. A missing record does not prove that the network rejected a timed-out submission. Do not build a replacement based on a 404.
280
- */
281
221
  get: operations["getAgentUserOpByHash"];
282
222
  put?: never;
283
223
  post?: never;
@@ -294,10 +234,6 @@ export interface paths {
294
234
  path?: never;
295
235
  cookie?: never;
296
236
  };
297
- /**
298
- * Ranked, searchable, paged catalog of API providers
299
- * @description Ranked, searchable, paged catalog of API providers. Ranking is by `rankScore`, the provider's busiest endpoint measured in 30-day unique payers. Every discovered provider is listed; each endpoint carries a `verification` state saying whether we measured its 402, measured that it is free, have not probed it yet, found it quoting another chain, or found it unreachable. Endpoints are NOT inlined here - fetch `/apis/providers/{providerId}` for those. `total` counts what matched before paging; `hidden` counts providers a chain or asset filter left with nothing to show, and `reasons` explains at most 50 of them (`reasonsTruncated` says when it is not all of them). Spec 2026-08-13 §9.
300
- */
301
237
  get: operations["listApiProviders"];
302
238
  put?: never;
303
239
  post?: never;
@@ -314,10 +250,6 @@ export interface paths {
314
250
  path?: never;
315
251
  cookie?: never;
316
252
  };
317
- /**
318
- * One provider with a page of its endpoints
319
- * @description Detailed view of one provider: the same fields the list carries, plus a searchable, paged `endpoints` array and the `endpointTotal` it is a page of. One provider carries up to 965 endpoints, so this route pages as well. Each endpoint states its `verification`, its price as measured or as declared, and whether it is `payable` on that chain. Spec 2026-08-13 §9.
320
- */
321
253
  get: operations["getApiProvider"];
322
254
  put?: never;
323
255
  post?: never;
@@ -334,10 +266,6 @@ export interface paths {
334
266
  path?: never;
335
267
  cookie?: never;
336
268
  };
337
- /**
338
- * Read the current API budget and its state
339
- * @description Returns remaining count, per-call max, expiry, epoch, token, max exposure, and amount spent. Spec 2026-08-13 §9.
340
- */
341
269
  get: operations["getApiBudget"];
342
270
  put?: never;
343
271
  post?: never;
@@ -356,11 +284,6 @@ export interface paths {
356
284
  };
357
285
  get?: never;
358
286
  put?: never;
359
- /**
360
- * Check the gate and allocate a budget index for an API call
361
- * @description Runs the gate, fetches the provider's 402, allocates an index, and returns the EIP-3009 payload the agent must sign, plus everything else needed to build the ERC-1271 envelope around the signature (`authorization`, `index`, `validator` - Task 13). Returns no signature - the agent signs and passes the sig to relay. Spec 2026-08-13 §9.
362
- * Task 11: a call above the agent's mandate `confirmAbove` threshold does NOT build ready to sign. `status: 'pending_approval'` is returned instead - `payload`/`requirements`/ `authorization`/`index`/`validator` are all absent, structurally, not merely empty. Poll `GET /apis/calls/requirements/{id}` for the owner's decision; once `POST /apis/calls/requirements/{id}/approve` has run, that same poll route starts returning `payload`/`authorization`/`index`/`validator` together (Task 14) - a client that only ever sees `pending_approval` here still gets everything it needs to build the signature once approved.
363
- */
364
287
  post: operations["buildApiCallRequirements"];
365
288
  delete?: never;
366
289
  options?: never;
@@ -375,11 +298,6 @@ export interface paths {
375
298
  path?: never;
376
299
  cookie?: never;
377
300
  };
378
- /**
379
- * Poll a call raised above the agent's confirmAbove threshold
380
- * @description Task 11. What the owner decided, if anything, about a `pending_approval` call from `buildApiCallRequirements`. `@AgentAllowed` - this is what the agent polls, since the digest was withheld at build time.
381
- * THE SECURITY PROPERTY: `payload`, `authorization`, `index` and `validator` (Task 14) are present ONLY when `status: 'approved'`. `X402PaymentValidator`'s nonce is a `pure` function of public inputs and `validBefore` is the agent's own to choose, so an agent holding all four before the owner has actually approved could sign and relay to any facilitator without ever calling Botanary again - returning them any earlier would make the threshold decorative. `validator` itself is not secret - it is a public contract address - but it is withheld alongside the other three so a client never has a reason to reach for it before it also has something to sign.
382
- */
383
301
  get: operations["getApiCallRequirementStatus"];
384
302
  put?: never;
385
303
  post?: never;
@@ -398,10 +316,6 @@ export interface paths {
398
316
  };
399
317
  get?: never;
400
318
  put?: never;
401
- /**
402
- * Relay an authorized API call with payment
403
- * @description Claims the requirement durably before forwarding payment once. Returns the provider response when available, with payment status based on finalized chain evidence. A timeout or provider success does not prove settlement. Repeating the same requirement returns its stored status without forwarding again; recover with GET /apis/calls/relay/{id}. The authenticated account must own the requirement. An agent session may relay only its own requirement on that account; another agent on the same account cannot relay it. Unknown, unsubmitted expired and out-of-scope requirement IDs return the same requirement_expired decline without forwarding payment or changing another caller's state.
404
- */
405
319
  post: operations["relayApiCall"];
406
320
  delete?: never;
407
321
  options?: never;
@@ -416,10 +330,6 @@ export interface paths {
416
330
  path?: never;
417
331
  cookie?: never;
418
332
  };
419
- /**
420
- * Recover the same API payment without submitting again
421
- * @description Reads the durable requirement, provider observation and finalized payment status. The same account and agent scope as relay applies. Submitted calls remain recoverable after their authorization expires. No provider request or signature is sent by this endpoint.
422
- */
423
333
  get: operations["getApiCallStatus"];
424
334
  put?: never;
425
335
  post?: never;
@@ -433,46 +343,17 @@ export interface paths {
433
343
  export type webhooks = Record<string, never>;
434
344
  export interface components {
435
345
  schemas: {
436
- /** @description Request to pair a new agent. The agent signs over `(code || timestamp)` with its secp256k1 private key, proving it holds the key for the claimed public key. The signature is verified to recover to that key before the pairing proof is held (in-memory, expiring in minutes). */
437
346
  AgentPairInput: {
438
- /**
439
- * @description The pairing code (format XXXXXX-XXXXXX). Identifies the agent by its signature.
440
- * @example a1b2c3-d4e5f6
441
- */
442
347
  code: string;
443
- /**
444
- * @description The agent's secp256k1 public key (hex, with 0x prefix).
445
- * @example 0x...
446
- */
447
348
  publicKey: string;
448
- /**
449
- * @description The agent's secp256k1 signature over keccak256(code || timestamp) (hex, with 0x prefix).
450
- * @example 0x...
451
- */
452
349
  signature: string;
453
- /** @description Unix seconds at the time the agent signed. Used for replay protection (±5 minutes). */
454
350
  timestamp: number;
455
- /**
456
- * @description OPTIONAL. The coding tool the connector reports itself to be, slugified from the MCP `clientInfo.name` it received at initialize. Travels with the signed proof, so the tool a pairing claims to be is fixed by the connector that holds the key, not by whoever claims the code.
457
- * Unverified by construction - `clientInfo` is self-reported and the server cannot check it. It is stored on the resulting `ConnectedAgent.client` and shown to the owner as a quoted claim. The pattern is a whitelist because this value is displayed at the moment the owner decides what to authorize, so it may not carry markup, whitespace or direction-control characters that could dress one tool up as another.
458
- * Omitted by every connector released before this field existed; those pairings still work and store null.
459
- * @example claude-code
460
- */
461
351
  client?: string;
462
- /**
463
- * @description OPTIONAL. The connector-side profile key behind this keypair - `<tool>` for a tool's default agent, `<tool>.<agent>` for a further one. Same unverified caveat as `client`.
464
- * @example claude-code.trading
465
- */
466
352
  profile?: string;
467
353
  };
468
354
  ApiError: {
469
355
  error: {
470
- /**
471
- * @description Machine code - validation_error | unauthorized | forbidden | not_found | out_of_scope | conflict | internal | unavailable.
472
- * @example out_of_scope
473
- */
474
356
  code: string;
475
- /** @example This action exceeds the per-action cap. */
476
357
  message: string;
477
358
  declineReason?: components["schemas"]["DeclineReason"] | null;
478
359
  details?: {
@@ -481,656 +362,183 @@ export interface components {
481
362
  requestId?: string | null;
482
363
  };
483
364
  };
484
- /**
485
- * @description Maps 1:1 to AgentGuard reverts (owner lane, execution phase) / Smart Sessions policy rejections (delegated lane, validation phase) / MandateExecutor reverts (delegated lane, execution phase). AgentGuard and MandateExecutor name the exact rule that failed; Smart Sessions returns only PolicyViolation, so `policy_violation` is genuinely all that is knowable there. Only the execution-phase reasons carry a transaction hash: a validation-phase rejection is dropped by the bundler before inclusion, so it has no artifact to link.
486
- * @enum {string}
487
- */
488
365
  DeclineReason: "cap_exceeded" | "per_action_exceeded" | "recipient_not_allowed" | "contract_not_allowed" | "contract_denied" | "stablecoin_not_permitted" | "expired" | "max_actions_exceeded" | "account_frozen" | "admin_call_denied" | "delegatecall_denied" | "malformed_call" | "policy_violation" | "delegation_revoked" | "paymaster_not_permitted" | "no_policies_set" | "mandate_revoked" | "venue_not_allowed" | "selector_not_allowed" | "residual_allowance" | "value_not_zero" | "chain_capability_unavailable" | "route_unavailable" | "route_spender_mismatch" | "grant_swap_not_authorised" | "slippage_exceeded" | "mandate_paused" | "venue_denied" | "value_exceeded" | "budget_exceeded" | "arg_cap_exceeded" | "arg_not_allowed" | "insufficient_fee_balance" | "rent_exempt_shortfall" | "blockhash_expired" | "blockhash_not_found" | "mint_not_supported" | "account_not_found" | "trustline_missing" | "reserve_shortfall" | "tx_expired" | "relayer_unavailable" | "bridge_route_unavailable" | "bridge_pool_depth_exceeded" | "pool_not_actionable" | "exit_capacity_exceeded" | "nothing_to_claim" | "farm_simulation_failed" | "privy_rule_blocked" | "insufficient_usdc_for_gas" | "gasless_unavailable" | "kora_cosign_rejected" | "validator_inactive" | "not_enough_approvals" | "gas_cost_exceeds_ceiling" | "action_nonce_already_used" | "unknown_signer" | "duplicate_approval" | "expiry_required" | "approval_blob_too_short" | "approval_entry_out_of_bounds" | "approval_proof_out_of_bounds" | "trailing_approval_bytes" | "unsupported_scheme" | "endpoint_disabled" | "unsupported_endpoint_method" | "request_body_not_supported" | "request_body_too_large" | "provider_unavailable_on_chain" | "provider_unverified" | "provider_unreachable" | "budget_exhausted" | "over_per_call_max" | "payment_required" | "budget_expired" | "requirement_expired" | "validator_not_installed" | "token_not_configured" | "facilitator_rejected" | "provider_rejected_request" | "apis_budget_headroom" | "apis_budget_account_rules" | "commit_not_on_chain" | "mandate_not_found" | "api_mandate_paused" | "mandate_expired" | "provider_not_in_mandate" | "endpoint_not_in_mandate" | "velocity_exceeded" | "over_mandate_per_call_max" | "mandate_budget_exceeded" | "approval_required" | "approval_declined" | "approval_timed_out" | "revoke_requires_uninstall";
489
- /** @description Request a fresh nonce for an agent to sign, to mint a session (POST /agents/session). */
490
366
  AgentSessionNonceInput: {
491
- /** @description The agent's secp256k1 address (must already be a LIVE connected agent). */
492
367
  address: components["schemas"]["Address"];
493
368
  };
494
- /**
495
- * @description A 20-byte EVM address.
496
- * @example 0x8f2A9c4419aD77b0392bC41D8123aa77c0Fe41D0
497
- */
498
369
  Address: string;
499
- /**
500
- * @description A 32-byte hash (tx hash, userOpHash, permissionId, audit hash).
501
- * @example 0x4c1f9a0b2d7e8c3f1a6b0d4e2c9f7a1b4c1f9a0b2d7e8c3f1a6b0d4e2c9f7a1b
502
- */
503
370
  Hash32: string;
504
- /** @description Mint an agent session by proving possession of the private key behind `address`: sign the exact nonce issued by POST /agents/session/nonce and submit the signature here. */
505
371
  AgentSessionInput: {
506
372
  address: components["schemas"]["Address"];
507
- /** @description The nonce returned by POST /agents/session/nonce. */
508
373
  nonce: components["schemas"]["Hash32"];
509
- /**
510
- * @description The agent's secp256k1 signature over `nonce` (hex, with 0x prefix).
511
- * @example 0x...
512
- */
513
374
  signature: string;
514
375
  };
515
- /** @description A short-lived agent session token (Bearer `ags_...`), scoped to @AgentAllowed() routes. */
516
376
  AgentSessionResponse: {
517
- /**
518
- * @description Opaque, revocable bearer token - never derived from the agent's key.
519
- * @example ags_...
520
- */
521
377
  token: string;
522
- /** Format: date-time */
523
378
  expiresAt: string;
524
379
  };
525
- /**
526
- * @description GET /agents/me's answer to an agent's own three questions: who am I, what account am I bound to, and what may I do. `grant` is resolved by matching a Delegation's delegateeAddress against this agent's OWN address - null is a real, honest answer (this agent has been granted nothing yet, not an error and not an empty object), not a placeholder for a future field. This agent can still read and draft under every @AgentAllowed() route regardless of `grant`; every attempt to spend without one is refused for lack of authority, never silently.
527
- * Whatever an agent reads here is a convenience for whoever built it - never the check. The only boundary that counts is on-chain; a bug or a lie in this response changes nothing about what the agent can actually get away with.
528
- */
529
380
  AgentSelf: {
530
- /** @description This agent's connection record ID (same as ConnectedAgent.id). */
531
381
  id: string;
532
- /** @example Claude Code */
533
382
  name: string;
534
383
  address: components["schemas"]["Address"];
535
- /** @example a1b2c3 */
536
384
  fingerprint: string;
537
- /** Format: date-time */
538
385
  connectedAt: string;
539
- /** @description The account this agent is bound to. */
540
386
  accountId: string;
541
- /** @description That account's own on-chain address - the same string the owner sees in the account switcher, so "which account is this agent on?" is answerable without an internal id lookup. accountId above is opaque and appears nowhere in the app, which made an agent paired to a DIFFERENT login than the one the owner had open indistinguishable from a broken pairing. null only when the account row no longer exists - never fabricated. */
542
387
  accountAddress: components["schemas"]["Address"] | null;
543
- /** @description The live delegation whose delegateeAddress is this agent's own address, or null when the owner has granted this agent nothing (yet). Carries the grant's permissionId, bounds (policySet), plain-language sentence (humanSummary) and status - everything the MCP connector's spend tool needs to spend under it. */
544
388
  grant: components["schemas"]["Delegation"] | null;
545
- /** @description Whether the grant's own chain has every setup module the account needs, and which are absent. Exists so an agent learns this BEFORE it spends rather than from a reverted op: a missing executor makes every action under the grant fail identically, and no retry can change it, because installing a module is an authority change only the owner can sign. null when there is no grant (nothing to be ready for) or the check could not be completed - an honest gap, never a fabricated ready:true. */
546
389
  accountSetup: components["schemas"]["AgentAccountSetup"] | null;
547
390
  };
548
- /**
549
- * @description A scoped, revocable session-key delegation = policy set + spent-to-date.
550
- * @example {
551
- * "id": "d1",
552
- * "permissionId": "0x1111111111111111111111111111111111111111111111111111111111111111",
553
- * "name": "Uniswap",
554
- * "kind": "dApp",
555
- * "icon": "arrow-left-right",
556
- * "delegateeAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
557
- * "chain": "Arbitrum",
558
- * "chainId": 42161,
559
- * "status": "active",
560
- * "humanSummary": "This dApp can spend up to 100 USDC in total, and may call 0x3593564c() on Universal Router and approve() on Permit2, max 50 per action, limited to 10 actions. Expires on 2026-08-03.",
561
- * "policySet": {
562
- * "budgets": [
563
- * {
564
- * "token": {
565
- * "symbol": "USDC",
566
- * "chainId": 42161
567
- * },
568
- * "amount": 100
569
- * }
570
- * ],
571
- * "perActionMax": {
572
- * "token": {
573
- * "symbol": "USDC",
574
- * "chainId": 42161
575
- * },
576
- * "amount": 50
577
- * },
578
- * "maxActions": 10,
579
- * "recipientAllowlist": [],
580
- * "allowedActions": [
581
- * {
582
- * "name": "Universal Router",
583
- * "target": "0x66a9893cC07D91D95644AEDD05D03f95e1dBA8Af",
584
- * "selectors": [
585
- * "0x3593564c"
586
- * ]
587
- * },
588
- * {
589
- * "name": "Permit2",
590
- * "target": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
591
- * "selectors": [
592
- * "0x095ea7b3"
593
- * ]
594
- * }
595
- * ],
596
- * "expiresAt": "2026-08-03T00:00:00Z",
597
- * "freezeGated": false
598
- * },
599
- * "spentToDate": [
600
- * {
601
- * "token": {
602
- * "symbol": "USDC",
603
- * "chainId": 42161
604
- * },
605
- * "limit": 100,
606
- * "spent": 42.5,
607
- * "remaining": 57.5,
608
- * "expiresAt": "2026-08-03T00:00:00Z"
609
- * }
610
- * ]
611
- * }
612
- */
613
391
  Delegation: {
614
- /** @example d1 */
615
392
  id: string;
616
393
  permissionId: components["schemas"]["Hash32"];
617
- /**
618
- * @description GRANT-ONLY, mandate-sourced only. Which mandate this grant was compiled from. Null on the legacy name-salted branch and on every non-grant kind. The chain can never tell you which mandate a permission id came from, so the row carries it - and a client that needs to correlate a grant back to its mandate MUST read this rather than matching on `name`, which is not unique within an agent.
619
- * @example m_7f3a
620
- */
621
394
  mandateId?: string | null;
622
- /**
623
- * @description The version of `mandateId` this grant compiled from. Always set together with `mandateId`; a row carrying one without the other is refused at build time.
624
- * @example 2
625
- */
626
395
  mandateVersion?: number | null;
627
- /** @example Uniswap */
628
396
  name: string;
629
397
  kind: components["schemas"]["DelegationKind"];
630
- /**
631
- * @description Lucide icon name (design-system hint).
632
- * @example arrow-left-right
633
- */
634
398
  icon?: string | null;
635
399
  delegateeAddress: components["schemas"]["Address"];
636
- /** @example Arbitrum */
637
400
  chain: string;
638
- /** @example 42161 */
639
401
  chainId: number;
640
402
  status: components["schemas"]["DelegationStatus"];
641
403
  policySet: components["schemas"]["PolicySet"];
642
- /** @description One meter per budget, in the same order as policySet.budgets. */
643
404
  spentToDate: components["schemas"]["SpendMeter"][];
644
- /**
645
- * @description Plain-language rendering of exactly what the encoder bound (FR-1 fidelity).
646
- * @example This dApp can spend up to 100 USDC in total, max 50 per action, limited to 10 actions. Expires on 2026-08-03.
647
- */
648
405
  humanSummary: string;
649
- /** Format: date-time */
650
406
  createdAt?: string;
651
- /** Format: date-time */
652
407
  expiresAt?: string | null;
653
- /**
654
- * @description Set only on the POST /delegations (enable) response, to the just-relayed enable op's id. The grant audit row is normally appended synchronously by a bounded server-side confirm, but that confirm can time out on a slow chain; poll GET /userops/{userOpId} (the same reconciler every other build->sign->relay flow already uses) to reach a terminal audit row for the grant. Absent/null on every other response that returns a Delegation - there is no op to poll there.
655
- * @example op_9f2a1c
656
- */
657
408
  userOpId?: string | null;
658
409
  };
659
- /** @enum {string} */
660
410
  DelegationKind: "dApp" | "automation" | "recurring" | "mandate" | "grant";
661
- /** @enum {string} */
662
411
  DelegationStatus: "active" | "frozen" | "expired" | "revoked";
663
- /** @description Exactly what a delegation binds on-chain via Smart Sessions. Every field here is enforced by a policy, and the plain-language summary is rendered from this and nothing else. Two absences are deliberate, both from ERC-7562 rule OP-011 (no TIMESTAMP opcode in the validation phase where session policies run): there is no per-period cap (a delegation carries a lifetime `budgets` total plus an `expiresAt`, never "100 USDC per week") and no rate limit (`maxActions` is a lifetime count, never "3 per day"). A per-period cap on the owner's OWN account is a different thing that does exist - see AccountCap. */
664
412
  PolicySet: {
665
- /** @description Total spend allowed over the delegation's life, one entry per permitted stablecoin. */
666
413
  budgets: components["schemas"]["TokenAmount"][];
667
414
  perActionMax?: components["schemas"]["TokenAmount"] | null;
668
- /**
669
- * @description Lifetime cap on the NUMBER of delegated actions (Rhinestone UsageLimitPolicy). Not a rate.
670
- * @example 10
671
- */
672
415
  maxActions?: number | null;
673
- /** @description Approved recipients. Empty means genuinely unbounded - the delegatee may pay anyone. */
674
416
  recipientAllowlist: components["schemas"]["AddressBookEntry"][];
675
- /** @description The (contract, function) pairs the delegatee may call, beyond the budgeted transfers. */
676
417
  allowedActions: components["schemas"]["ActionPermission"][];
677
- /** Format: date-time */
678
418
  expiresAt: string;
679
- /** @description Whether a global account freeze also stops this delegation (AgentGuardFreezePolicy attached). */
680
419
  freezeGated: boolean;
681
- /** @description GRANT-ONLY, and ABSENT unless the grant asked to swap. Records which router/token/ceiling this grant's SECOND session action (GrantExecutor.executeUnderGrantWithAllowance) pins - the fact POST /delegations/{delegationId}/actions reads to decide whether a swap is expressible at all. A compiled session is not readable back from a permissionId, so this is the record. */
682
420
  swapVenue?: components["schemas"]["GrantSwapVenue"];
683
421
  };
684
422
  TokenAmount: {
685
423
  token: components["schemas"]["TokenRef"];
686
- /** @example 50 */
687
424
  amount: number;
688
425
  };
689
- /** @description A lightweight reference to a coin. */
690
426
  TokenRef: {
691
- /**
692
- * @description PREFERRED. CAIP-19 asset ref, e.g. `eip155:8453/erc20:0x8335...`. Authoritative when present; `symbol` is advisory.
693
- * @example eip155:8453/erc20:0x8335...
694
- */
695
427
  assetRef?: string | null;
696
- /**
697
- * @description ADVISORY. A label a contract picked for itself - never authoritative, never resolved against.
698
- * @example USDC
699
- */
700
428
  symbol: string;
701
- /** @example 42161 */
702
429
  chainId?: number | null;
703
430
  address?: components["schemas"]["Address"] | null;
704
431
  };
705
- /** @description A named address in the owner's book. `chainId` is OPTIONAL by design: an entry that predates the field, or one whose chain is genuinely unknown, is still a valid entry - the client renders it copy-only with no explorer link rather than guessing a network and emitting a URL that resolves nowhere. */
706
432
  AddressBookEntry: {
707
- /** @example Universal Router */
708
433
  name?: string | null;
709
434
  address: components["schemas"]["Address"];
710
- /**
711
- * @description Which chain this address is meaningful on, when known. Drives the client's explorer link.
712
- * @example 8453
713
- */
714
435
  chainId?: number | null;
715
436
  };
716
- /**
717
- * @description A contract a delegation or grant may call, and (where the lane can express it) which functions on it.
718
- *
719
- * **In a REQUEST** (`DelegationIntent.allowedActions`) `selectors` MUST name at least one 4-byte selector, and an empty list is refused with 422. Smart Sessions binds a delegation's policies to `(actionTarget, selector)` pairs, so "any function on X" is not expressible on that lane and an allowlisted contract with no selector would grant nothing.
720
- *
721
- * **In a RESPONSE** an EMPTY `selectors` list is meaningful, and appears on a `kind: 'grant'` `PolicySet`. A grant binds its allowed contract as a call ARGUMENT (`ArgRuleSetPolicy`, `EQ` at the wrapper's target offset) rather than as the action target - every grant call routes through `GrantExecutor.executeUnderGrant` whatever the inner function is - so the bound genuinely is "any function on this contract", and an empty list is how that is said. The grant's own `humanSummary` names the contract either way.
722
- */
723
437
  ActionPermission: {
724
438
  target: components["schemas"]["Address"];
725
- /** @example Universal Router */
726
439
  name?: string | null;
727
- /**
728
- * @example [
729
- * "0x3593564c"
730
- * ]
731
- */
732
440
  selectors: string[];
733
441
  };
734
- /**
735
- * @description The venue a swap-capable grant is bound to: the ONE router the agent may be given an allowance to, the ONE token that allowance may be on, and the ceiling on it. All three are required together - a swap's tokens leave via the ROUTER's own transferFrom, in a frame whose msg.sender is the router and which no AgentGuard hook sees, so the three EQ/LTE session rules these compile to (plus the mandatory permissionId pin) are the ONLY thing bounding what may be approved, to whom, and how much. The token must be one the same grant also BUDGETS, and must not be the native asset (there is no allowance to grant on native); both are refused at build time.
736
- * @example {
737
- * "router": "0x111111125421cA6dc452d289314280a0f8842A65",
738
- * "token": {
739
- * "symbol": "USDC",
740
- * "chainId": 421614
741
- * },
742
- * "maxAllowance": 50
743
- * }
744
- */
745
442
  GrantSwapVenue: {
746
- /** @description Gets both the allowance and the routed call - the entrypoint has ONE (token, target) pair. A route quote whose approvalAddress differs from its router is declined route_spender_mismatch. */
747
443
  router: components["schemas"]["Address"];
748
444
  token: components["schemas"]["TokenRef"];
749
- /** @description Ceiling on a single frame's allowance, in display units. */
750
445
  maxAllowance: number;
751
446
  };
752
- /** @description A delegation's spend against one of its budgets. Budgets do not reset - they end at expiry - so there is no period/resetsAt here (unlike AccountCap, which is periodic). */
753
447
  SpendMeter: {
754
448
  token: components["schemas"]["TokenRef"];
755
- /** @example 100 */
756
449
  limit: number;
757
- /** @example 42.5 */
758
450
  spent: number;
759
- /** @example 57.5 */
760
451
  remaining: number;
761
- /** Format: date-time */
762
452
  expiresAt?: string | null;
763
453
  };
764
- /** @description Setup readiness for the chain an agent's grant lives on. See AgentSelf.accountSetup. */
765
454
  AgentAccountSetup: {
766
- /** @description True when nothing is missing; an agent may spend without consulting `missing`. */
767
455
  ready: boolean;
768
- /**
769
- * @description Module names absent from the account, in install order. Empty exactly when ready.
770
- * @example [
771
- * "GrantExecutor"
772
- * ]
773
- */
774
456
  missing: string[];
775
- /**
776
- * @description The chain assessed - the grant's own chain, never the agent's pinned row.
777
- * @example 5042002
778
- */
779
457
  chainId: number;
780
458
  };
781
- /** @description One in-flight agent request. The agent has asked the owner to approve an action that exceeded its delegated grant. Requests expire in minutes; an expired request stays in the list marked `expired` so expiry is a recorded, visible event (D8). The owner approves it as their own action - not delegated (§5-43), so the unsigned op carries no `permissionId`. */
782
459
  AgentRequest: {
783
- /** @description The request ID. */
784
460
  id: string;
785
- /** @description The agent that raised this request. */
786
461
  agentId: string;
787
- /** @description The account this request belongs to. */
788
462
  accountId: string;
789
- /** @description The calls the agent wanted to make, exactly as proposed. */
790
463
  calls: {
791
- /**
792
- * @description The target contract address.
793
- * @example 0x...
794
- */
795
464
  to: string;
796
- /**
797
- * @description The encoded call data (hex, with 0x prefix).
798
- * @example 0x...
799
- */
800
465
  data: string;
801
- /**
802
- * @description The native wei to send (decimal string). Usually '0'.
803
- * @example 0
804
- */
805
466
  value: string;
806
- /**
807
- * @description The chain ID where this call should execute.
808
- * @example 8453
809
- */
810
467
  chainId: number;
811
468
  }[];
812
- /**
813
- * @description WHICH bound was crossed - a specific DeclineReason, never a generic failure. Specific enough for the agent to narrow what it was doing (§6-40).
814
- * @example cap_exceeded
815
- */
816
469
  declineReason: string;
817
- /**
818
- * @description Human-readable reason from the agent.
819
- * @example Pay the invoice
820
- */
821
470
  reason: string;
822
- /**
823
- * Format: date-time
824
- * @description When the request was raised.
825
- */
826
471
  raisedAt: string;
827
- /**
828
- * Format: date-time
829
- * @description When this request expires (visible from the moment it is raised, D8). The owner cannot approve it after this time, but the request stays in the list marked `expired` rather than vanishing.
830
- */
831
472
  expiresAt: string;
832
- /**
833
- * @description The request's current status. `open` = awaiting approval. `approved` = owner approved and the op was built. `expired` = past the deadline. `withdrawn` = agent gave up. Expired requests stay visible.
834
- * @enum {string}
835
- */
836
473
  status: "open" | "approved" | "expired" | "withdrawn";
837
474
  };
838
- /** @description Request to raise a pending request when an agent hits a delegation bound. The request carries the originally-proposed calls and the reason the agent is asking, plus a decline reason naming which specific bound was crossed. */
839
475
  AgentRequestInput: {
840
- /**
841
- * @description A human-readable reason for the request (e.g. 'Pay the invoice').
842
- * @example Pay the invoice
843
- */
844
476
  reason: string;
845
- /** @description The calls the agent wanted to make (and was declined). */
846
477
  calls: {
847
- /**
848
- * @description The target contract address.
849
- * @example 0x...
850
- */
851
478
  to: string;
852
- /**
853
- * @description The encoded call data (hex, with 0x prefix).
854
- * @example 0x...
855
- */
856
479
  data: string;
857
- /**
858
- * @description The native wei to send (decimal string). Usually '0'.
859
- * @example 0
860
- */
861
480
  value: string;
862
- /**
863
- * @description The chain ID where this call should execute.
864
- * @example 8453
865
- */
866
481
  chainId: number;
867
482
  }[];
868
483
  };
869
- /**
870
- * @description A view over the owner's own holdings. Never pooled or custodial (FR-S1).
871
- * @example {
872
- * "totalFiat": 12480.06,
873
- * "change24h": 2.4,
874
- * "stablecoinFiat": 12235.32,
875
- * "status": "ready",
876
- * "asOf": "2026-07-07T09:42:00Z",
877
- * "holdings": [
878
- * {
879
- * "assetRef": "eip155:42161/erc20:0xaf88d065e77c8cc2239327c5edb3a432268e5831",
880
- * "symbol": "USDC",
881
- * "amount": 6420.5,
882
- * "priceUsd": 1,
883
- * "fiat": 6420.5,
884
- * "priceAdvisory": true
885
- * },
886
- * {
887
- * "assetRef": "eip155:42161/erc20:0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9",
888
- * "symbol": "USDT",
889
- * "amount": 2100,
890
- * "priceUsd": 1,
891
- * "fiat": 2100,
892
- * "priceAdvisory": true
893
- * },
894
- * {
895
- * "assetRef": "eip155:42161/slip44:60",
896
- * "symbol": "ETH",
897
- * "amount": 0.0921,
898
- * "priceUsd": 2657.3,
899
- * "fiat": 244.74,
900
- * "priceAdvisory": false
901
- * }
902
- * ],
903
- * "tokens": [
904
- * {
905
- * "symbol": "USDC",
906
- * "name": "USD Coin",
907
- * "chain": "Arbitrum",
908
- * "chainId": 42161,
909
- * "tokenAddress": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
910
- * "decimals": 6,
911
- * "amount": 6420.5,
912
- * "fiat": 6420.5,
913
- * "price": 1,
914
- * "change24h": 0,
915
- * "isStablecoin": true,
916
- * "peg": {
917
- * "symbol": "USDC",
918
- * "price": 1,
919
- * "target": 1,
920
- * "deviationBps": 0,
921
- * "status": "ok",
922
- * "observedAt": "2026-07-07T09:40:00Z",
923
- * "source": "chainlink"
924
- * },
925
- * "spendable": true,
926
- * "source": "registry"
927
- * },
928
- * {
929
- * "symbol": "USDT",
930
- * "name": "Tether",
931
- * "chain": "Arbitrum",
932
- * "chainId": 42161,
933
- * "tokenAddress": "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
934
- * "decimals": 6,
935
- * "amount": 2100,
936
- * "fiat": 2100.42,
937
- * "price": 1.0002,
938
- * "change24h": 0.01,
939
- * "isStablecoin": true,
940
- * "peg": {
941
- * "symbol": "USDT",
942
- * "price": 0.9938,
943
- * "target": 1,
944
- * "deviationBps": -62,
945
- * "status": "watch",
946
- * "observedAt": "2026-07-07T09:40:00Z",
947
- * "source": "chainlink"
948
- * },
949
- * "spendable": true,
950
- * "source": "registry"
951
- * },
952
- * {
953
- * "symbol": "ETH",
954
- * "name": "Ether",
955
- * "chain": "Arbitrum",
956
- * "chainId": 42161,
957
- * "tokenAddress": "0x0000000000000000000000000000000000000000",
958
- * "decimals": 18,
959
- * "amount": 0.0921,
960
- * "fiat": 244.74,
961
- * "price": 2657.3,
962
- * "change24h": -1.2,
963
- * "isStablecoin": false,
964
- * "peg": null,
965
- * "spendable": true,
966
- * "source": "registry"
967
- * }
968
- * ]
969
- * }
970
- */
971
484
  UnifiedBalance: {
972
- /** @example 12480.06 */
973
485
  totalFiat: number;
974
- /**
975
- * @description 24h change, percent.
976
- * @example 2.4
977
- */
978
486
  change24h: number;
979
- /**
980
- * @description The unified stablecoin figure (excludes non-stable assets like ETH).
981
- * @example 12235.32
982
- */
983
487
  stablecoinFiat: number;
984
- /** @description Every priced holding across every chain family (EVM, Solana and Stellar alike), each in the one ValuedHolding shape - the row ValuationService.value() produces, the exact function GET /balance and GET /balance/history both call so the headline total and the chart's last point can never disagree. Always present (`[]` when empty), mirroring the three sidecar arrays below. The portfolio-history redesign's Task 21 wires this response up; tokens/ solanaTokens/stellarTokens are DEPRECATED in its favor and kept, unchanged, only until the frontend cuts over to it. */
985
488
  holdings: components["schemas"]["ValuedHolding"][];
986
- /**
987
- * @deprecated
988
- * @description DEPRECATED - superseded by holdings. Kept, unchanged, until the frontend cuts over (portfolio-history redesign Task 22).
989
- */
990
489
  tokens: components["schemas"]["TokenBalance"][];
991
- /**
992
- * @deprecated
993
- * @description DEPRECATED - superseded by holdings. Solana holdings. Always present (`[]` when empty) so a consumer never distinguishes "no Solana holdings" from "this build does not serve Solana". `totalFiat`, `stablecoinFiat` and `change24h` INCLUDE these rows.
994
- */
995
490
  solanaTokens: components["schemas"]["SolanaTokenBalance"][];
996
- /**
997
- * @deprecated
998
- * @description DEPRECATED - superseded by holdings. Stellar holdings. Always present (`[]` when empty), mirroring `solanaTokens` exactly. UNLIKE `solanaTokens`, each row carries no `fiat`/`price` field at all (no dedicated Stellar price port). `totalFiat`/`stablecoinFiat`/`change24h` are summed from `holdings[]` (chain-agnostic), so a Stellar trustline whose symbol is a recognized stablecoin (USDC/USDT) DOES contribute via the same $1 peg-advisory rule any other chain's stablecoin uses; an asset with no such recognition and no price observation (native XLM, today) still contributes nothing.
999
- */
1000
491
  stellarTokens: components["schemas"]["StellarTokenBalance"][];
1001
- /**
1002
- * @description The account's backfill/health state (portfolio-history redesign, Task 21 fix round 1). `building` means the background sweep has not reached this account yet (no sync state, or a sync state with no ledger rows behind it) - `holdings` may be empty and `totalFiat` may read 0, and this is NOT a confirmed zero balance: a client MUST treat a `building` response as unknown, never render it as a real $0. At the moment this redesign first ships, EVERY existing account starts in `building` - the background sweep has never run in production before this cutover - so this is not a rare edge case for launch day, it is the expected state for the whole account population until the sweep catches up. `degraded` means the account has ledger data, but at least one of its chains' background sync is unhealthy right now - `holdings`/`totalFiat` still reflect whatever WAS last successfully synced for every chain, never blanked over one bad chain. `ready` means every chain's last sync succeeded.
1003
- * @example ready
1004
- * @enum {string}
1005
- */
1006
492
  status: "ready" | "building" | "degraded";
1007
- /** Format: date-time */
1008
493
  asOf: string;
1009
494
  };
1010
- /** @description One priced holding, chain-agnostic (EVM/Solana/Stellar alike) - the exact row shape ValuationService.value() produces (src/modules/portfolio/valuation.service.ts), shared verbatim by GET /balance's headline total and GET /balance/history's chart bucket-by-bucket, so the two are structurally incapable of disagreeing. UnifiedBalance.holdings wiring lands in the portfolio-history redesign's Task 21. */
1011
495
  ValuedHolding: {
1012
- /**
1013
- * @description CAIP-19 asset reference, e.g. `eip155:8453/erc20:0x8335...` for an ERC-20, or `eip155:8453/slip44:60` for that chain's native coin. The address segment of an erc20 reference is always lowercased.
1014
- * @example eip155:8453/erc20:0x833589fcd6edb6e08f4c7c32d4f71b54bda02913
1015
- */
1016
496
  assetRef: string;
1017
- /** @example USDC */
1018
497
  symbol: string;
1019
- /**
1020
- * @description Display amount, decimal-formatted from the underlying base-unit balance.
1021
- * @example 6420.5
1022
- */
1023
498
  amount: number;
1024
- /**
1025
- * @description The price this holding was valued at - an observed price when priceAdvisory is false, or the $1 stablecoin TARGET when priceAdvisory is true. 0 when unresolvable (never fabricated).
1026
- * @example 1
1027
- */
1028
499
  priceUsd: number;
1029
- /**
1030
- * @description amount × priceUsd, rounded to 2dp.
1031
- * @example 6420.5
1032
- */
1033
500
  fiat: number;
1034
- /** @description True only for a stablecoin with no observed price currently in force: priceUsd is then the $1 peg TARGET, not an observation - FR-9's honesty signal, telling a reader the number is a target rather than confirmation the asset is actually on peg, even mid-depeg. False in every other case, including a real observed price (stablecoin or not) and an unresolvable price (priceUsd: 0). Today this is the ONLY path ever taken for a stablecoin: no peg-observation source feeds PriceSeries yet (see the portfolio-history redesign design doc's §4 - DepegObservation exists in the schema but nothing writes it), so in practice every stablecoin prices at exactly $1.00 with priceAdvisory true even mid-depeg. An accepted fidelity limitation, not a hidden one. */
1035
501
  priceAdvisory: boolean;
1036
502
  };
1037
- /** @description One held token, presentation-shaped (amount/fiat/price are display values) - EXCEPT amountRaw, which is not: it carries the exact base-unit balance, so this schema is no longer purely presentational and does not carry the x-presentation-only flag the other balance schemas do. Still never pooled or custodial (FR-S1) - only the "presentation-only" framing was inaccurate, never the custody guarantee. */
1038
503
  TokenBalance: {
1039
- /**
1040
- * @description CAIP-19 asset ref, e.g. `eip155:42161/erc20:0x...`. Authoritative identifier for the token.
1041
- * @example eip155:42161/erc20:0xFF970A61A04b1cA14834A43f5dE4533eBDDB5F86
1042
- */
1043
504
  assetRef?: string;
1044
- /** @example USDC */
1045
505
  symbol: string;
1046
- /** @example USD Coin */
1047
506
  name: string;
1048
- /** @example Arbitrum */
1049
507
  chain: string;
1050
- /** @example 42161 */
1051
508
  chainId: number;
1052
509
  tokenAddress: components["schemas"]["Address"];
1053
- /** @example 6 */
1054
510
  decimals: number;
1055
- /** @example 6420.5 */
1056
511
  amount: number;
1057
- /** @example 6420.5 */
1058
512
  fiat: number;
1059
- /** @example 1 */
1060
513
  price: number;
1061
- /** @example 0 */
1062
514
  change24h: number;
1063
515
  isStablecoin: boolean;
1064
516
  peg?: components["schemas"]["PegStatus"] | null;
1065
- /** @description Whether Send/Grant can build against this token today - it has an adapter entry (see `GET /adapters`) for this chain + symbol, or it is native ETH. A displayable token (`registry ∪ discovered ∪ imported`) is not necessarily spendable. */
1066
517
  spendable: boolean;
1067
- /**
1068
- * @description Which feed produced this row. `registry` is the curated, priced set; `discovered` is best-effort on-chain auto-discovery; `imported` is a token the owner added by hand.
1069
- * @enum {string}
1070
- */
1071
518
  source: "registry" | "discovered" | "imported";
1072
- /** @description Coarse spam signal, set only on `discovered` rows with no price and an unrecognized symbol. Never set on `registry`/`imported` rows. A flag only - it never blocks display. */
1073
519
  unrecognized?: boolean;
1074
- /**
1075
- * @description Virtuals launchpad stage, present only for recognized agent tokens.
1076
- * @enum {string}
1077
- */
1078
520
  graduationStatus?: "sentient" | "prototype" | "unknown";
1079
- /** @description True when the price source confirmed this is a real (Virtuals) token. */
1080
521
  recognized?: boolean;
1081
- /** @description Fully-diluted valuation in USD when reported; never fabricated. */
1082
522
  fdvUsd?: number | null;
1083
- /**
1084
- * @description The exact base-unit magnitude backing amount, as a decimal string - e.g. "1500500001" for a 6-decimal token whose true on-chain balance is 1500.500001, alongside amount: 1500.5 (2dp-rounded for display). Copied straight from the on-chain bigint read (bigint.toString()) - never a decimal-string parse and never a Number round-trip - so it carries no rounding beyond whatever the chain itself reported. This is the truth anchor the portfolio-history redesign's balance projection reads: re-deriving base units by multiplying amount back out would replay display rounding into that projection. Only ever set on a REAL on-chain read; omitted, never fabricated, on a fake-mode seeded row.
1085
- * @example 1500500001
1086
- */
1087
523
  amountRaw?: string;
1088
524
  };
1089
- /** @description Peg observation for one stablecoin. Visibility-only in v1. */
1090
525
  PegStatus: {
1091
- /** @example USDT */
1092
526
  symbol: string;
1093
- /**
1094
- * @description Null iff status = unknown - never defaulted to 1, which would read as "on peg".
1095
- * @example 0.9938
1096
- */
1097
527
  price: number | null;
1098
- /** @example 1 */
1099
528
  target: number;
1100
- /**
1101
- * @description Signed basis points from target. Null iff status = unknown.
1102
- * @example -62
1103
- */
1104
529
  deviationBps: number | null;
1105
530
  status: components["schemas"]["PegStatusLevel"];
1106
- /** Format: date-time */
1107
531
  observedAt: string;
1108
- /** @example chainlink */
1109
532
  source?: string | null;
1110
- /**
1111
- * @description Why the peg could not be observed. Set iff status = unknown.
1112
- * @example Chainlink oracle unavailable
1113
- */
1114
533
  unavailableReason?: string | null;
1115
534
  };
1116
- /**
1117
- * @description `unknown` is not cosmetic: FR-9 forbids *silently* holding a depegged asset, so an unobservable peg reads as "we don't know" (price/deviationBps null, unavailableReason set), never as "on peg".
1118
- * @enum {string}
1119
- */
1120
535
  PegStatusLevel: "ok" | "watch" | "depegged" | "unknown";
1121
- /** @description One Solana holding. Deliberately parallel to `TokenBalance` rather than a variant of it: `TokenBalance` requires `chainId` and a 0x `tokenAddress`, and loosening either would make two Solana rows compare equal on chainId. */
1122
536
  SolanaTokenBalance: {
1123
- /** @example SOL */
1124
537
  symbol: string;
1125
- /** @example SOL */
1126
538
  name: string;
1127
- /** @example Solana Devnet */
1128
539
  chain: string;
1129
- /** @example solana-devnet */
1130
540
  key: string;
1131
- /** @description The SPL mint, or null for native SOL, which genuinely has no mint. */
1132
541
  mint: components["schemas"]["SolanaAddress"] | null;
1133
- /** @example 9 */
1134
542
  decimals: number;
1135
543
  amount: number;
1136
544
  fiat: number;
@@ -1138,280 +546,114 @@ export interface components {
1138
546
  change24h: number;
1139
547
  isStablecoin: boolean;
1140
548
  peg?: components["schemas"]["PegStatus"] | null;
1141
- /** @description Always false in this build - the Solana send path does not exist yet. */
1142
549
  spendable: boolean;
1143
- /** @enum {string} */
1144
550
  source: "registry" | "discovered";
1145
551
  };
1146
- /**
1147
- * @description A Solana address (base58-encoded Ed25519 public key, 32-44 characters). DELIBERATELY separate from `Address` rather than widening it: `Address`'s `^0x[a-fA-F0-9]{40}$` pattern is enforced on ~12 DTOs, and widening it to accept base58 would silently weaken every one of them.
1148
- * @example 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM
1149
- */
1150
552
  SolanaAddress: string;
1151
- /** @description One Stellar balance row - native XLM or a trustline asset. Deliberately a RAW shape, unlike `SolanaTokenBalance`: there is no Stellar price port yet, so this carries no `amount`/`fiat`/ `price` - only what the RPC actually observed. */
1152
553
  StellarTokenBalance: {
1153
- /** @example XLM */
1154
554
  symbol: string;
1155
- /** @description The trustline asset's issuer account, or null for native XLM, which genuinely has none. */
1156
555
  issuer: components["schemas"]["StellarAddress"] | null;
1157
- /**
1158
- * @description The raw on-chain balance as a decimal string (bigint-safe transport) - never a number, which would lose precision.
1159
- * @example 1000.0000000
1160
- */
1161
556
  rawAmount: string;
1162
- /** @example 7 */
1163
557
  decimals: number;
1164
- /**
1165
- * @description The chain KEY this row was read from ('stellar' or 'stellar-testnet'), mirroring `SolanaTokenBalance.key`. Distinguishes otherwise-identical XLM/trustline rows held on both Stellar networks.
1166
- * @example stellar
1167
- */
1168
558
  key: string;
1169
559
  };
1170
- /**
1171
- * @description A Stellar account address (StrKey-encoded Ed25519 public key, starts with `G`, 56 characters). DELIBERATELY separate from `Address` and `SolanaAddress` - never widen either existing schema to accept this format.
1172
- * @example GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H
1173
- */
1174
560
  StellarAddress: string;
1175
- /** @description A reference chain. `tier`/`explorerUrl`/`blockscoutUrl`/`gasTokens` are populated by `GET /chains` (Plan 3 Task 5) - the same schema used unenriched elsewhere (`SessionContext.chains`, `ReceiveInfo.chains`) may omit them. */
1176
561
  Chain: {
1177
- /** @example Arbitrum */
1178
562
  name: string;
1179
- /**
1180
- * @description The EVM chainId. `null` on a non-EVM chain (Solana) - the same answer `LaunchpadToken.chainId` gives for a Solana launchpad token. Use `key` to address a chain across namespaces.
1181
- * @example 42161
1182
- */
1183
563
  chainId: number | null;
1184
- /**
1185
- * @description CAIP-2 chain reference (e.g. eip155:84532, solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1, stellar:testnet). The namespace-agnostic identity for this chain - unlike chainId, which is null for every non-EVM chain. Clients scoping a request by chain (GET /balance/history's chainRefs, GET /balance's focusChainRef) MUST send this value, not a key or a name.
1186
- * @example eip155:84532
1187
- */
1188
564
  chainRef: string;
1189
- /**
1190
- * @description Which address/transaction family this chain belongs to. `eip155` is every EVM chain. `solana` is the SVM lane. `stellar` is the Stellar lane - StrKey `G...` addresses, transactions relayed via `POST /stellar/transactions` (a later phase). Clients MUST branch on this to pick an address format and a send path.
1191
- * @example eip155
1192
- * @enum {string}
1193
- */
1194
565
  namespace: "eip155" | "solana" | "stellar";
1195
- /**
1196
- * @description The canonical identifier for this chain across both namespaces. For an EVM chain this is the stringified `chainId` ("8453"); for Solana it is a slug ("solana", "solana-devnet").
1197
- * @example 8453
1198
- */
1199
566
  key: string;
1200
- /** @example arb */
1201
567
  shortName?: string | null;
1202
- /** @example false */
1203
568
  testnet: boolean;
1204
- /** @example ETH */
1205
569
  nativeSymbol?: string | null;
1206
- /**
1207
- * @description `botanary` iff AgentGuard is deployed (delegation/freeze/rules available); `basic` iff the chain has a bundler but no AgentGuard (send only, no delegation); `watch` otherwise (balances/reads only). From `GET /chains` only.
1208
- * @example botanary
1209
- * @enum {string}
1210
- */
1211
570
  tier?: "watch" | "basic" | "botanary";
1212
- /**
1213
- * @description Block-explorer link base for this chain (currently always Blockscout). From `GET /chains` only.
1214
- * @example https://base-sepolia.blockscout.com
1215
- */
1216
571
  explorerUrl?: string;
1217
- /**
1218
- * @description The Blockscout instance base URL for this chain. From `GET /chains` only.
1219
- * @example https://base-sepolia.blockscout.com
1220
- */
1221
572
  blockscoutUrl?: string;
1222
- /**
1223
- * @description Assets that can pay this chain's gas - `native` always, `+USDC` where Circle Paymaster gas is available. From `GET /chains` only.
1224
- * @example [
1225
- * "native",
1226
- * "USDC"
1227
- * ]
1228
- */
1229
573
  gasTokens?: string[];
1230
- /**
1231
- * @description The ERC-20 identity address for a chain whose NATIVE asset is itself a token (Arc: gas is USDC), for DISPLAY/verification only - e.g. a token detail view's "Contract" field and block-explorer link for that chain's native balance row, which otherwise carries the `0x0` native sentinel (not a real, explorer-verifiable contract). `null` on every other chain, and `null` here too on a token-native chain whose ERC-20 address is unverified. Balances are never read or deduped through this address - only through the native sentinel. From `GET /chains` only.
1232
- * @example 0x3600000000000000000000000000000000000000
1233
- */
1234
574
  nativeErc20Address?: string | null;
1235
575
  };
1236
- /** @description How an owner may pay a network fee (FR-8). `usdc` is the default: FR-8 promises that no action requires holding a native gas token, and an owner who has only ever received stablecoins holds none. Choosing it makes `POST /money/send/build` return a `gasPermit`. */
1237
576
  GasMethod: {
1238
577
  method: components["schemas"]["GasMethodName"];
1239
- /** @example Sponsored */
1240
578
  label: string;
1241
- /** @description What the BOUND backend adapter can build - not what a given client can carry to a mined transaction. `usdt` is false in real mode: its Permit2 leg is a seam, not an implementation. */
1242
579
  available: boolean;
1243
580
  token?: components["schemas"]["TokenRef"] | null;
1244
581
  balance?: number | null;
1245
582
  balanceFiat?: number | null;
1246
583
  isDefault: boolean;
1247
- /** @example Pay the network fee in USDC. No ETH needed. */
1248
584
  note?: string | null;
1249
- /**
1250
- * @description What one send is expected to cost with this method, denominated in this method's own `token` - so a client can reserve the fee before there is an op to price. A MAX/"send everything" control MUST subtract this from the balance when `token` is the asset being sent, or it composes a transfer whose fee has nowhere to come from.
1251
- * An ESTIMATE. The authority on affordability is the build (`POST /money/send/build`), which prices the real UserOp and refuses with exact numbers rather than returning a signable op that cannot settle. `native` is priced from the chain's own `maxFeePerGas` and includes the account's deployment while it is still counterfactual. `null` means not estimable here (a paymaster whose spread this endpoint cannot read) - reserve nothing and let the build be the judge. `sponsored` is `0`: nothing leaves the account.
1252
- * @example 0.0009
1253
- */
1254
585
  estimatedFee?: number | null;
1255
586
  };
1256
- /** @enum {string} */
1257
587
  GasMethodName: "sponsored" | "usdc" | "usdt" | "native";
1258
588
  Account: {
1259
- /** @example acct_01H8 */
1260
589
  id: string;
1261
- /** @example Main account */
1262
590
  label: string;
1263
591
  address: components["schemas"]["Address"];
1264
- /** @description The address this account was previously stored as on this chain if it required migration to a new address. Null means the address has never changed on this chain, which is the normal case. */
1265
592
  supersededAddress?: string | null;
1266
- /** @example Smart account */
1267
593
  type: string;
1268
594
  deploymentStatus: components["schemas"]["AccountDeploymentStatus"];
1269
- /**
1270
- * @description `null` on a non-EVM account (Solana). Use `key` to identify the chain. On a collapsed `GET /accounts` entry this is the CANONICAL row's home chain, NOT the only chain the account exists on - the address is the same on every EVM chain, and `chains[]` enumerates the ones it has rows on.
1271
- * @example 42161
1272
- */
1273
595
  chainId: number | null;
1274
- /**
1275
- * @description The chain key this account belongs to ("8453", "solana", "solana-devnet").
1276
- * @example 8453
1277
- */
1278
596
  key?: string;
1279
- /**
1280
- * @example eip155
1281
- * @enum {string}
1282
- */
1283
597
  namespace?: "eip155" | "solana" | "stellar";
1284
- /** @description `null` when this account has NO smart account - a plain Solana wallet, where the key and the money share an address. On EVM this is absent, because the account itself IS the smart account. Present-and-null is the seam that lets a program vault be added later additively. */
1285
598
  smartAccount?: Record<string, never> | null;
1286
599
  signerAddress: components["schemas"]["Address"];
1287
- /** @description Account-level kill-switch state. On a collapsed `GET /accounts` entry, `true` when AT LEAST ONE of `chains[]` is frozen - AgentGuard is deployed per chain, so the flag is per chain underneath; which chain is frozen, and the id to unfreeze it with, are in `chains[]`. Required, because every account this API serves today is an EVM account (`address` is 0x-typed) and every one of them has a kill-switch. A chain with no kill-switch mechanism will OMIT this rather than send `false` - `false` would read as "not frozen" when it means "freeze does not exist here" - and will be expressed as its own arm of a `oneOf` discriminated on `namespace`, not by relaxing this list. */
1288
600
  frozen: boolean;
1289
- /**
1290
- * @description The CREATE2 factory salt this account was derived at. 0 is the first ("Main") account.
1291
- * @example 0
1292
- */
1293
601
  index: number;
1294
- /** @description Presentation-only. A hidden account is NOT deleted: it remains on-chain, remains bounded by AgentGuard, and its delegations remain revocable. Hiding only removes it from the picker. */
1295
602
  hidden: boolean;
1296
- /**
1297
- * @description What this account is for. Absent on an older/legacy account row - treat as "primary". "acp_spending" marks the dedicated, capped account a bounded ACP hire pays from.
1298
- * @example primary
1299
- * @enum {string}
1300
- */
1301
603
  purpose?: "primary" | "acp_spending";
1302
- /** Format: date-time */
1303
604
  createdAt?: string;
1304
- /**
1305
- * @description This account's own unified-balance total (fiat). Present only on `GET /accounts` rows - absent on every other Account-shaped response (`GET /account`, `POST /accounts`, `PATCH /accounts/:id`, …).
1306
- * @example 8765.66
1307
- */
1308
605
  totalFiat?: number;
1309
- /** @description Every chain this ONE logical account exists on, one entry per backing row. Present only where an Account is a COLLAPSED group - `GET /accounts` rows and the `PATCH /accounts/:id` response - and absent everywhere else (`GET /account`, `POST /accounts`, …), which return a single chain's row and mean it. Its presence is what says "this is the account, not one chain of it". The entries carry the per-chain truth the collapsed fields can only summarise: `deploymentStatus` and `frozen` genuinely differ per chain, and `accountId` is what an inherently per-chain operation (`POST /account/freeze` and `/unfreeze`, `POST /accounts/{id}/tokens`) must be given to target one specific chain. */
1310
606
  chains?: components["schemas"]["AccountChain"][];
1311
607
  };
1312
- /** @enum {string} */
1313
608
  AccountDeploymentStatus: "counterfactual" | "deployed";
1314
- /** @description One chain a logical account exists on. NOT a separate account: every entry shares the owner's `address`, `label` and `index` - the same counterfactual Kernel account, whose deployment state is per-chain. */
1315
609
  AccountChain: {
1316
- /** @example 84532 */
1317
610
  chainId: number;
1318
- /**
1319
- * @description The backing row's id, for endpoints that act on ONE chain. The group's own `id` is the canonical row's id and appears here too.
1320
- * @example acct_01H8
1321
- */
1322
611
  accountId: string;
1323
612
  deploymentStatus: components["schemas"]["AccountDeploymentStatus"];
1324
- /** @description This chain's own kill-switch state - AgentGuard is deployed per chain, so an account can be frozen on one chain and live on another. */
1325
613
  frozen: boolean;
1326
- /**
1327
- * @description Whether this chain carries BotanaryPolicyValidator at all - i.e. whether signers and signing policies could EVER work here, independent of anything about this account.
1328
- *
1329
- * A CLIENT CANNOT DERIVE THIS. `chainTier` is no substitute: it keys off `agentGuard`, a different contract, so a `basic`-tier chain and a validator-carrying one are indistinguishable through it. Shipping without this field meant the signing-policy network selector offered - and defaulted to - chains where the feature is permanently impossible.
1330
- *
1331
- * Deliberately about the CHAIN, not the account. `installed`/`migrationEligible` (GET /account/policies) answer "can THIS account use it here", a different and later question. A chain that is `false` here can never become usable; one that is `true` but not yet installed only needs a step, and must stay offered so the owner can take it.
1332
- */
1333
614
  authorityCore: boolean;
1334
615
  };
1335
- /** @description TWO shapes, discriminated by `action`. Omitting `action` is a TRANSFER - `recipient` and `amount` required, unchanged since the route's first shape. Which token it moves is named by `token` (a contract address or CAIP-19 asset ref - Task A11) or, for callers that predate that field, the LEGACY `tokenSymbol` (by symbol); both are optional when the delegation budgets exactly one token. `action: swap` is the swap shape: it requires `tokenIn`, `tokenOut` and `amountIn`, ignores `recipient`/`amount`/`token`/`tokenSymbol`, and is GRANT-ONLY. A swap is refused `grant_swap_not_authorised` unless the grant was built with a `swapVenue` AND the route agrees with the router, token and allowance ceiling that venue pins; and `route_spender_mismatch` when the route's approval spender and router are different addresses (a grant approves exactly the contract it calls, so such a route is not expressible). */
1336
616
  DelegatedActionInput: {
1337
- /**
1338
- * @description Which shape this body is. Omitted → transfer.
1339
- * @enum {string}
1340
- */
1341
617
  action?: "transfer" | "swap";
1342
- /** @description TRANSFER shape, required there. The transfer recipient (re-checked against the delegation's allowlist on-chain). */
1343
618
  recipient: string;
1344
- /** @description TRANSFER shape, required there. Amount in the delegation's stablecoin (re-checked against per-action + cumulative caps). */
1345
619
  amount: number;
1346
- /**
1347
- * @description TRANSFER shape. Which budgeted token to move, by contract address or CAIP-19 asset ref - NEVER a symbol. Same pattern and same rule as `CliSendIntent.token` (see that field's own description): a symbol is a label a contract chose for itself, and this route will not guess which one a caller meant. Optional when the delegation budgets exactly one token (defaults to it); when it budgets more than one, name it explicitly here or in `tokenSymbol` below, or the build is refused rather than silently picking the first budgeted token. Whenever named, must be one of the tokens this delegation actually budgets, or the build declines `stablecoin_not_permitted`.
1348
- * @example 0x036CbD53842c5426634e7929541eC2318f3dCF7e
1349
- */
1350
620
  token?: string;
1351
- /** @description TRANSFER shape. LEGACY - the pre-Task-A11 way to name a budgeted token, BY SYMBOL (e.g. "USDC"). Kept only for callers that predate `token` above; prefer `token`, since a symbol is a label a contract chose for itself and two contracts on one chain can share one. Also matched against the delegation's budgeted assetRefs and declined `stablecoin_not_permitted` when it names an unbudgeted token. */
1352
621
  tokenSymbol?: string;
1353
- /** @description SWAP shape, required there. The token being SOLD, by symbol. Must be the one token this grant's swapVenue pins. */
1354
622
  tokenIn?: string;
1355
- /** @description SWAP shape, required there. The token being BOUGHT, by symbol. Unbounded by the grant - what the account receives increases its holdings, and a grant meters only what leaves. */
1356
623
  tokenOut?: string;
1357
- /** @description SWAP shape, required there. How much of tokenIn to sell, in display units. Must be at or under the venue's maxAllowance. */
1358
624
  amountIn?: number;
1359
- /** @description SWAP shape. Slippage tolerance for the route quote. Defaults to 50 bps. */
1360
625
  maxSlippageBps?: number;
1361
626
  };
1362
- /** @description A built (unsigned) op ready for the owner to sign, with the hash to sign + context. */
1363
627
  UserOpBuild: {
1364
628
  intentType: components["schemas"]["IntentType"];
1365
629
  userOp: components["schemas"]["UnsignedUserOp"];
1366
630
  userOpHash: components["schemas"]["Hash32"];
1367
631
  humanSummary?: string | null;
1368
632
  simulation?: components["schemas"]["Simulation"] | null;
1369
- /** @description Present for swaps whose route supplies exact output amounts; never derived from rounded display amounts. */
1370
633
  swapQuote?: components["schemas"]["SwapExecutionQuote"];
1371
- /** @description Freeze/revoke/withdraw-to-safety - instant, never gated on native gas (FR-2/FR-8). */
1372
634
  riskReducing: boolean;
1373
635
  instant: boolean;
1374
- /** @description Pre-wired to the sponsored / revoke-only paymaster. */
1375
636
  gasless: boolean;
1376
- /** @description Set only when the send chose to pay its fee in USDC. When present, `userOpHash` above is stale - the client attaches `paymasterData` and recomputes it. See GasPermit. */
1377
637
  gasPermit?: components["schemas"]["GasPermit"] | null;
1378
- /** @description Set only when the send chose to pay its fee in USDT and the account's on-chain allowance needed raising. INFORMATIONAL: `calls` are already batched into `userOp.callData`, so - unlike `gasPermit` - no second signature is required and `userOpHash` above remains the hash to sign. */
1379
638
  usdtApproval?: components["schemas"]["UsdtApproval"] | null;
1380
- /** @description Present ONLY for `intentType: farm_deposit` / `farm_withdraw` - live exit constraints for the target pool, probed after the op is built and never cached, so what the owner sees is what the chain says at signing time. Absent (not merely null) for every other intentType. */
1381
639
  exit?: components["schemas"]["ExitTerms"] | null;
1382
- /** @description Present for `intentType: farm_deposit` / `farm_withdraw` / `farm_claim` (Plan 5 Task 4/7 extends this to the claim build), alongside `exit` above where applicable - the verbs this pool's adapter implements for this account, from the same live probe (design spec §7). Absent for every other intentType, and optional here so this addition is non-breaking for clients that predate it. */
1383
640
  verbs?: components["schemas"]["VerbAvailability"][];
1384
- /** @description Present ONLY for `intentType: farm_claim` (Plan 5 Task 4/7) - the reward rows this build read from the SAME probe used to decide whether to build at all, so a client can show what was actually claimed without a second round trip. Absent (not merely `[]`) for every other intentType, including `farm_deposit`/`farm_withdraw` - see `ClaimableReward` for the absence-vs-empty distinction this field itself carries when it IS present. */
1385
641
  claimable?: components["schemas"]["ClaimableReward"][];
1386
- /** @description Present ONLY for the seven v1-authority-core `intentType`s (`policy_set`, `policy_remove`, `signer_add`, `signer_remove`, `guardians_set`, `condition_set_member_set`, `signers_recover`) - what this op costs, both today and once it lands. Absent for every other intentType. */
1387
642
  securityPricing?: components["schemas"]["SecurityPricing"] | null;
1388
- /** @description Present ONLY for `intentType: signers_recover` (Flow 9). Every ACTIVE policy whose `approvals` requirement is clamped down by this signer-set rotation - empty (never absent) when none is affected. Absent for every other intentType. See `PolicyImpact` for exactly what this does and does not capture. */
1389
643
  policyImpact?: components["schemas"]["PolicyImpact"][] | null;
1390
- /** @description Present ONLY for `intentType: signers_recover`, always `true` there - `recover` unconditionally deletes the account's guardian set as part of the same call, regardless of `newSigners`/ `newThreshold`. A structured twin of the same fact already stated in `humanSummary`. Absent for every other intentType. */
1391
644
  guardiansCleared?: boolean | null;
1392
645
  };
1393
- /** @enum {string} */
1394
646
  IntentType: "send" | "swap" | "delegation_enable" | "delegation_freeze" | "delegation_unfreeze" | "delegation_revoke" | "account_freeze" | "account_unfreeze" | "rules_update" | "guardian_add" | "guardian_remove" | "account_deploy" | "account_fund" | "panic_install" | "panic_freeze" | "delegated_action" | "device_add" | "device_remove" | "device_threshold" | "managed_deposit" | "agent_deposit" | "farm_deposit" | "farm_withdraw" | "farm_claim" | "pay_sh_topup" | "policy_set" | "policy_remove" | "signer_add" | "signer_remove" | "signer_threshold" | "guardians_set" | "condition_set_member_set" | "signers_recover" | "action_announce" | "authority_migration_op_a" | "authority_migration_op_b" | "trust_anchor_set" | "apis_budget_commit" | "apis_budget_revoke";
1395
- /** @description ERC-4337 (EntryPoint v0.7) UserOp with an empty signature. The owner signs `userOpHash` (returned alongside in the build envelope) client-side against their Privy embedded wallet. The backend builds and later relays it - it never signs. */
1396
647
  UnsignedUserOp: {
1397
648
  sender: components["schemas"]["Address"];
1398
- /**
1399
- * @description uint256 as a decimal/hex string.
1400
- * @example 0
1401
- */
1402
649
  nonce: string;
1403
650
  factory?: components["schemas"]["Address"] | null;
1404
651
  factoryData?: components["schemas"]["Hex"] | null;
1405
652
  callData: components["schemas"]["Hex"];
1406
- /** @example 200000 */
1407
653
  callGasLimit: string;
1408
- /** @example 150000 */
1409
654
  verificationGasLimit: string;
1410
- /** @example 50000 */
1411
655
  preVerificationGas: string;
1412
- /** @example 1000000000 */
1413
656
  maxFeePerGas: string;
1414
- /** @example 1000000000 */
1415
657
  maxPriorityFeePerGas: string;
1416
658
  paymaster?: components["schemas"]["Address"] | null;
1417
659
  paymasterVerificationGasLimit?: string | null;
@@ -1419,15 +661,9 @@ export interface components {
1419
661
  paymasterData?: components["schemas"]["Hex"] | null;
1420
662
  signature: components["schemas"]["Hex"];
1421
663
  entryPoint: components["schemas"]["Address"];
1422
- /** @example 42161 */
1423
664
  chainId: number;
1424
665
  };
1425
- /**
1426
- * @description Arbitrary-length hex byte string (calldata, paymaster data, signature).
1427
- * @example 0x
1428
- */
1429
666
  Hex: string;
1430
- /** @description Advisory pre-flight (FR-4). The on-chain hook re-asserts. */
1431
667
  Simulation: {
1432
668
  id: string;
1433
669
  intentType: components["schemas"]["IntentType"];
@@ -1435,16 +671,12 @@ export interface components {
1435
671
  declineReason?: components["schemas"]["DeclineReason"] | null;
1436
672
  amountIn?: components["schemas"]["TokenAmount"] | null;
1437
673
  amountOut?: components["schemas"]["TokenAmount"] | null;
1438
- /** @example 1.08 */
1439
674
  rate?: number | null;
1440
- /** @example USDC → EURC via Uniswap v3 */
1441
675
  route?: string | null;
1442
- /** @example 30 */
1443
676
  slippageBps?: number | null;
1444
677
  fees: components["schemas"]["TokenAmount"][];
1445
678
  gas: components["schemas"]["GasEstimate"];
1446
679
  warnings: string[];
1447
- /** Format: date-time */
1448
680
  expiresAt?: string | null;
1449
681
  };
1450
682
  GasEstimate: {
@@ -1452,151 +684,65 @@ export interface components {
1452
684
  cost?: components["schemas"]["TokenAmount"] | null;
1453
685
  sponsored: boolean;
1454
686
  };
1455
- /** @description Exact quote amounts in integer base units, associated with this unsigned swap build. These are estimates for review and subsequent financial-effect reconciliation. This object alone does not prove that the router calldata enforces a minimum or that execution settled. */
1456
687
  SwapExecutionQuote: {
1457
688
  chainId: number;
1458
689
  toChainId: number;
1459
690
  accountAddress: components["schemas"]["Address"];
1460
- /** @description Input token address, or the zero address for native currency. */
1461
691
  inputAsset: components["schemas"]["Address"];
1462
- /** @description Output token address, or the zero address for native currency. */
1463
692
  outputAsset: components["schemas"]["Address"];
1464
- /** @description Exact input amount, at most uint256 max. */
1465
693
  amountInRaw: string;
1466
- /** @description Estimated output amount, at most uint256 max. */
1467
694
  estimatedOutRaw: string;
1468
- /** @description Quoted minimum output, no greater than estimatedOutRaw. */
1469
695
  minimumOutRaw: string;
1470
696
  };
1471
- /**
1472
- * @description Present only when `gasMethod: usdc`. Everything the client needs to let the Circle Paymaster take this op's network fee in USDC, and nothing it could compute for itself.
1473
- *
1474
- * The paymaster is paid through a USDC EIP-2612 permit whose `owner` is the SMART ACCOUNT, so USDC verifies it via ERC-1271 and the owner signs a Kernel-wrapped digest rather than the permit's own EIP-712 hash. The backend reads the chain and computes that digest. **It holds no key and produces no signature** - a hash is not an authorization.
1475
- *
1476
- * The permit is independent of the UserOp, while `paymasterData` is hashed INTO the userOpHash. The order is therefore forced, and **`UserOpBuild.userOpHash` is NOT the hash to sign when this object is present**: sign `permitDigest`, assemble `paymasterData` as `abi.encodePacked(uint8 0, token, permitAmount, signaturePrefix ‖ permitSignature)`, RECOMPUTE the userOpHash over the completed op, sign that, then relay. Two owner signatures per USDC-gassed op; USDC's permit nonce increments on use, so a permit is single-shot and cannot be cached.
1477
- *
1478
- * Every field of the permit is returned, not just the digest, so a client can rebuild the digest and refuse to sign one it did not derive.
1479
- */
1480
697
  GasPermit: {
1481
698
  paymaster: components["schemas"]["Address"];
1482
699
  token: components["schemas"]["Address"];
1483
- /**
1484
- * @description The token's on-chain `name()` - part of its EIP-712 domain. Differs per chain.
1485
- * @example USD Coin
1486
- */
1487
700
  tokenName: string;
1488
- /** @example 2 */
1489
701
  tokenVersion: string;
1490
- /**
1491
- * @description The account version whose ERC-1271 wrapper produced `permitDigest`.
1492
- * @example 0.3.3
1493
- */
1494
702
  kernelVersion: string;
1495
- /**
1496
- * @description The permit's `value`, in the token's base units. MUST equal the amount encoded into `paymasterData`; the two are checked against each other on-chain.
1497
- * @example 212142
1498
- */
1499
703
  permitAmount: string;
1500
- /** @example 2 */
1501
704
  permitNonce: string;
1502
- /** @description uint256 max - a permit is spent by its nonce, not by time. */
1503
705
  permitDeadline: string;
1504
706
  permitDigest: components["schemas"]["Hash32"];
1505
- /** @description Prepend to the owner's 65-byte signature - Kernel's ERC-1271 envelope (`0x01 ‖ rootValidator`). */
1506
707
  signaturePrefix: components["schemas"]["Hex"];
1507
- /**
1508
- * @description The USDC the paymaster pulls up front in the validation phase, refunding the unused part in postOp. The account must hold this on top of the amount it is sending.
1509
- * @example 0.031296
1510
- */
1511
708
  estimatedFee: number;
1512
709
  };
1513
- /** @description The one-time on-chain USDT allowance Pimlico's ERC-20 paymaster needs before it can pull its fee. Present only when `gasMethod: usdt` AND the account's current on-chain `USDT.allowance(account, paymaster)` is insufficient - omitted once approved. USDT has no EIP-2612 permit: `calls` are already batched into `UserOpBuild.userOp.callData`, so there is no digest and no second signature. INFORMATIONAL only - render it, but never collect a second signature. */
1514
710
  UsdtApproval: {
1515
- /** @description USDT on this chain - also every `calls[i].to`. */
1516
711
  token: components["schemas"]["Address"];
1517
- /** @description The Pimlico ERC-20 paymaster being granted the allowance - matches `userOp.paymaster`. */
1518
712
  paymaster: components["schemas"]["Address"];
1519
- /** @description The amount being approved, in USDT base units (a large, persistent allowance). */
1520
713
  amount: string;
1521
- /** @description Unsigned calls, already batched into the op the owner signs once. */
1522
714
  calls: components["schemas"]["UsdtApprovalCall"][];
1523
715
  };
1524
- /** @description One unsigned ERC-20 call, ready to batch into the account's own execution ahead of its intended action (Kernel v3.3 `execute`, batch mode). Not a signed leg - see `UsdtApproval`. */
1525
716
  UsdtApprovalCall: {
1526
717
  to: components["schemas"]["Address"];
1527
718
  data: components["schemas"]["Hex"];
1528
- /** @description Always `"0"` - an ERC-20 `approve` carries no native value. */
1529
719
  value: string;
1530
720
  };
1531
- /** @description Live exit constraints, probed at read time and NEVER cached. ERC-4626 does not guarantee an owner can leave: `maxWithdraw`/`maxRedeem` exist in the standard precisely because a vault can cap exits behind a notice period, a withdrawal queue, or simply pay out only what is currently liquid. All amounts are base-unit decimal strings, never numbers - a vault's TVL overflows float64 precision. */
1532
721
  ExitTerms: {
1533
- /** @description The underlying actually sitting in the vault/reserve right now, base units - ACCOUNT-INDEPENDENT, and the one honest pre-deposit signal: `maxWithdraw` is 0 and meaningless before the account holds any shares. */
1534
722
  liquidAssets: string;
1535
- /** @description The account's own live `maxWithdraw`, base units - what `POST /farm/withdraw/build` enforces against. Null when no account was in scope for the probe (`GET /farm/pools/{id}/terms`, asked before any deposit exists) - never a false zero standing in for "unknown". */
1536
723
  maxWithdrawAssets: string | null;
1537
- /** @description Same null convention as `maxWithdrawAssets`, share-denominated. */
1538
724
  maxRedeemShares: string | null;
1539
- /** @description True only when the account's WHOLE position can be withdrawn right now. Null under the same no-account-in-scope condition as `maxWithdrawAssets`. */
1540
725
  fullExitAvailable: boolean | null;
1541
- /**
1542
- * Format: date-time
1543
- * @description When this probe ran. Never cached - always "now", not a stale sync timestamp.
1544
- */
1545
726
  probedAt: string;
1546
727
  };
1547
- /**
1548
- * @description Whether an account can perform ONE verb against a pool RIGHT NOW, discovered from live chain state (design spec §7) rather than an editorial table. Two things the field names alone do not convey:
1549
- *
1550
- * ABSENCE of a verb from the containing `verbs` array is meaningful, and DIFFERENT from an entry present with `available: false`. Absence means this adapter has NO CLAIM PATH at all for this pool - e.g. `claim` on any pool but Aave-v3 (EVM) or Kamino (Solana). An entry present with `available: false` means the verb IS implemented but is closed right now, with `reason` saying why - for `claim` specifically, `nothing_accrued` (a reward program exists, proven zero accrued) or `rewards_unreadable` (the accrual read itself failed - never reported as a zero, see `ClaimableReward`). Clients depend on this distinction - do not conflate the two.
1551
- *
1552
- * `max: null` means NO PROVEN BOUND, never "unlimited" - a client must not render `null` as a Max amount.
1553
- */
1554
728
  VerbAvailability: {
1555
729
  verb: components["schemas"]["PoolVerb"];
1556
730
  available: boolean;
1557
- /** @description Upper bound in the asset's base units, when the adapter can PROVE one. `null` means no proven bound - see the schema description above. */
1558
731
  max: string | null;
1559
- /** @description Machine-readable why-not. Always `null` when `available` is true. */
1560
732
  reason: string | null;
1561
733
  };
1562
- /**
1563
- * @description One action a pool's adapter can attempt against a live pool (design spec §7): `deposit`, `withdraw`, or `claim`. As of Plan 5, `claim` is a REAL verb two adapters emit: the EVM Aave-v3 adapter (`class: lending`, reading `DEFAULT_INCENTIVES_CONTROLLER`) and the Solana Kamino adapter (`class: kamino-lend`, reading a farm's `UserState`). Every other adapter (ERC-4626, Compound v3, Marinade, Solend, Jito) still never emits it - see `VerbAvailability`'s own description for what that absence means versus a present-but-closed entry.
1564
- * @enum {string}
1565
- */
1566
734
  PoolVerb: "deposit" | "withdraw" | "claim";
1567
- /**
1568
- * @description One accrued reward-token row (design spec §9, Plan 5). Reward tokens are frequently NOT the pool's own asset (e.g. ARB or GHO accrued on an Aave USDC reserve) - `token`/`symbol`/`decimals` describe the REWARD, not the pool.
1569
- *
1570
- * Two things a client cannot infer from the field names alone, and must not conflate:
1571
- *
1572
- * `claimable: []` on a probe response with NO `claim` entry in that same response's `verbs` means this adapter has NO CLAIM PATH for this pool at all - never fabricate a row to fill the gap.
1573
- *
1574
- * A `claim` entry present in `verbs` with `available: false` means claimable IN PRINCIPLE, not right now, and `verbs[].reason` says why - `claimable` itself may still be `[]` in that case (nothing accrued, a PROVEN zero - see `nothing_accrued`) or may carry a nonzero row alongside an `available: false` entry caused by something else entirely (e.g. the reward could not be priced - pricing never gates availability, see `usdValue` below).
1575
- */
1576
735
  ClaimableReward: {
1577
- /**
1578
- * @description The reward token's contract address (EVM) or mint (Solana) - never the pool's own asset.
1579
- * @example 0x912CE59144191C1204E64559FE8253a0e49E6548
1580
- */
1581
736
  token: string;
1582
- /** @description Accrued amount in the reward token's own base units, base-unit decimal string like every other on-chain amount in this API. NEVER a fabricated zero standing in for "the read failed" - see the schema description above. */
1583
737
  amount: string;
1584
- /** @description Null when the reward token's symbol could not be resolved. */
1585
738
  symbol: string | null;
1586
- /** @description Null when the reward token's decimals could not be resolved. */
1587
739
  decimals: number | null;
1588
- /** @description Best-effort USD value of `amount`, priced through the existing oracle/market-data port (Plan 5 Task 5). `null` when the price is missing, stale, the source is unreachable, or `decimals` above is itself `null` (no honest way to scale `amount` into a human figure to price). DISPLAY ONLY: a missing price must NEVER suppress the `claim` verb or drop a row from `claimable` - a claimable reward with no price is still claimable. No "guaranteed" or APY language applies to this figure. */
1589
740
  usdValue: number | null;
1590
741
  };
1591
- /** @description What a policy/signer/guardian/condition-set change costs. `before` is `securityThresholdOf` as it stood BEFORE this change - the number of approvals the returned op itself needs - so tightening a send-policy from 2 to 3 costs 2, and loosening it from 3 back to 2 costs 3. `after` is what `securityThresholdOf` becomes once this change lands, so the UI can show the new cost before the owner commits. */
1592
742
  SecurityPricing: {
1593
743
  before: number;
1594
744
  after: number;
1595
745
  };
1596
- /**
1597
- * @description One ACTIVE policy whose required approval COUNT no longer fits a `signers_recover` rotation (Flow 9 - flows doc §5 test 30 / §3.6.1: "any policy that no longer fits comes down with them - shown before it takes effect"). `approvalsAfter` is always `<= approvalsBefore` (a rotation can only ever shrink what fits) and always `>= 1` (an active policy is never silently zeroed by this preview - `recover` can never leave an account with zero signers).
1598
- * DELIBERATELY NARROWER THAN "everything recover changes about this policy". Every ACTIVE policy is ALSO repointed to the WHOLE new signer set, regardless of whether it appears here - a policy that named one specific person becomes satisfiable by any of the new signers. That repoint is unconditional and already stated in the build's `humanSummary`; this list surfaces only the policies whose required NUMBER of approvals actually drops.
1599
- */
1600
746
  PolicyImpact: {
1601
747
  slot: number;
1602
748
  approvalsBefore: number;
@@ -1606,21 +752,16 @@ export interface components {
1606
752
  accountId: string;
1607
753
  accountAddress: string;
1608
754
  chainId: number;
1609
- /** @enum {string} */
1610
755
  action: "transfer" | "swap";
1611
756
  tokenAddress: string;
1612
- /** @description Positive integer base units. Maximum uint256; never converted through a floating-point amount for encoding or route requests. */
1613
757
  amount: string;
1614
758
  recipient?: string;
1615
759
  tokenOutAddress?: string;
1616
- /** @description Defaults to 50 basis points for swaps. Omit for transfers. */
1617
760
  maxSlippageBps?: number;
1618
761
  } & ({
1619
- /** @constant */
1620
762
  action: "transfer";
1621
763
  recipient: string;
1622
764
  } | {
1623
- /** @constant */
1624
765
  action: "swap";
1625
766
  tokenOutAddress: string;
1626
767
  });
@@ -1633,24 +774,18 @@ export interface components {
1633
774
  accountId: string;
1634
775
  accountAddress: string;
1635
776
  chainId: number;
1636
- /** @enum {string} */
1637
777
  action: "transfer" | "swap";
1638
778
  tokenAddress: string;
1639
- /** @description Positive integer base units. Maximum uint256; never converted through a floating-point amount for encoding or route requests. */
1640
779
  amount: string;
1641
780
  recipient?: string;
1642
781
  tokenOutAddress?: string;
1643
- /** @description Defaults to 50 basis points for swaps. Omit for transfers. */
1644
782
  maxSlippageBps?: number;
1645
- /** @constant */
1646
783
  gasMethod: "native";
1647
784
  };
1648
- /** @description A previously built op with the owner's client-side signature attached, for relay. */
1649
785
  SignedUserOp: {
1650
786
  userOp: components["schemas"]["UnsignedUserOp"];
1651
787
  userOpHash: components["schemas"]["Hash32"];
1652
788
  intentType: components["schemas"]["IntentType"];
1653
- /** @description Owner-browser-only durable approval context. Never accepted from an agent or platform credential. */
1654
789
  hostedOperation?: components["schemas"]["HostedOperationContext"];
1655
790
  };
1656
791
  HostedOperationContext: {
@@ -1658,221 +793,125 @@ export interface components {
1658
793
  attemptId: string;
1659
794
  };
1660
795
  UserOpReceipt: {
1661
- /** @example op_01H8 */
1662
796
  id: string;
1663
797
  userOpHash: components["schemas"]["Hash32"];
1664
798
  status: components["schemas"]["UserOpStatus"];
1665
799
  txHash?: components["schemas"]["Hash32"] | null;
1666
- /** Format: date-time */
1667
800
  submittedAt: string;
1668
801
  error?: string | null;
1669
802
  };
1670
- /** @enum {string} */
1671
803
  UserOpStatus: "pending" | "included" | "failed";
1672
- /** @description One page of the ranked provider catalog, with the total it is a page of. */
1673
804
  ApiProviderList: {
1674
- /** @description This page, ranked by `rankScore` descending then `id` ascending. */
1675
805
  providers: components["schemas"]["ApiProviderListItem"][];
1676
- /** @description Providers matching the filters BEFORE paging. */
1677
806
  total: number;
1678
- /** @description EXACT count of providers withheld. Never capped - the number is the honest part. Since spec 2026-08-26 §12 this is usually the LARGE number: the catalog returns only providers a paid call could complete against, so a provider that has never been measured on this chain is withheld with `provider_unverified`, and most of the catalog is in that state. */
1679
807
  hidden: number;
1680
- /** @description Why providers were hidden, mapped from providerId. Capped at 50 entries, because a chain filter over ~1,498 providers would otherwise staple tens of kilobytes of explanation to a 50-row page. */
1681
808
  reasons: {
1682
809
  [key: string]: string;
1683
810
  };
1684
- /** @description True when `reasons` was cut short of `hidden`. A cap the caller cannot see is a cap that lies, so the cut is reported rather than left for the map and the count to disagree about. */
1685
811
  reasonsTruncated: boolean;
1686
- /** @description How much of the catalog in scope has actually been MEASURED. Not decoration: the catalog returns only what a paid call could complete against, and the large majority of endpoints have never been probed - so a short or empty page is usually a measurement gap rather than a broken catalog, and this is what lets a surface say which. */
1687
812
  coverage: {
1688
- /** @description Endpoint rows in scope carrying at least one probe on a chain in scope. Intersected with the live catalog, so a probe that outlived the endpoint it measured cannot inflate it. */
1689
813
  probedEndpoints: number;
1690
- /** @description Endpoint rows in scope. Never less than `probedEndpoints`. */
1691
814
  totalEndpoints: number;
1692
815
  };
1693
816
  };
1694
- /** @description One row of the catalog grid. Deliberately carries NO `endpoints` array - at ~14,000 endpoints across ~1,498 providers, one of them with 965 endpoints of its own, inlining them makes the list a multi-megabyte response to render a grid that shows a count. `GET /apis/providers/{providerId}` serves the endpoints, a page at a time. */
1695
817
  ApiProviderListItem: {
1696
818
  id: string;
1697
819
  name: string;
1698
- /** @description Grouping the surface filters on, e.g. search, market-data, onchain-analytics. */
1699
820
  category: string;
1700
- /** @description The provider's human documentation page, WITHHELD once a sync has checked it and found it dead. A 200 is not enough to keep it: `arkham.io/docs` answers 200 with a parked "domain for sale" page, so the check also requires a real page title. Null here therefore means "no docs link to offer", never "not checked yet", and the surface renders no button. */
1701
821
  docsUrl: string | null;
1702
- /** @description The provider's own OpenAPI document, where a sync found one. It is both the source of that provider's `openapi` endpoint rows and the fallback the detail page links as "API reference" when there is no live `docsUrl`. A machine document, not a written guide, and labelled as such wherever it is rendered. */
1703
822
  openapiUrl: string | null;
1704
823
  baseUrl: string;
1705
- /** @description Owner has blocked this provider for EVERY agent on this account, whatever their mandates say. Absent state is `false` - a catalog of ~36,000 endpoints is not something an owner opts into one at a time. A convenience filter and a kill-switch, never an authority bound: what binds money is `ApiMandate` plus the on-chain envelope. Was `enabled` (inverted) until spec 2026-08-30 §3.2. */
1706
824
  blocked: boolean;
1707
- /** @description Sorted unique set of chains this provider's listed endpoints sit on. This CAN be the whole supported set: an endpoint that has never been probed and declares no chain of its own is evidence-free, so with no chain filter it lists on every supported chain. That is what "we do not know where this runs" looks like, not a claim that the provider is live everywhere. */
1708
825
  chains: number[];
1709
- /** @description True for the hand-maintained catalog; false for discovery-index entries. Also the list's first sort key, and the surface renders it as a "Verified" badge against "Community" - a curated entry is one a human checked, where a discovered one is self-reported. */
1710
826
  curated: boolean;
1711
- /** @description Responses are synthetic. Must remain visible to agents, not only to humans. */
1712
827
  simulated: boolean;
1713
- /** @description The provider's own mark, hosted by the provider: the icon it registered with the discovery index if it has one, otherwise the icon its own website serves, resolved once at sync time. Null when neither exists, and the surface falls back to a monogram rather than inventing one. */
1714
828
  iconUrl: string | null;
1715
829
  description: string | null;
1716
- /** @description DISTINCT endpoints matching the filters, not listing rows - an endpoint listed on two chains is still one endpoint. */
1717
830
  endpointCount: number;
1718
- /** @description Distinct endpoints we have actually MEASURED - a 402 we parsed, or a 200 proving the endpoint is free. Never exceeds `endpointCount`. */
1719
831
  verifiedCount: number;
1720
- /** @description The provider's busiest endpoint in 30-day unique payers. The list's sort key. */
1721
832
  rankScore: number;
1722
- /** @description Cheapest price across this provider's listed endpoints, in atomic token units. Null when no endpoint carries a usable price. */
1723
833
  minPriceUnits: string | null;
1724
- /** @description Dearest price across this provider's listed endpoints, in atomic token units. */
1725
834
  maxPriceUnits: string | null;
1726
835
  };
1727
- /** @description One provider: every field of `ApiProviderListItem`, plus one page of its endpoints and the `endpointTotal` that page is a page of. */
1728
836
  ApiProviderDetail: components["schemas"]["ApiProviderListItem"] & {
1729
- /** @description One page of endpoints, busiest first. One endpoint listed on two chains appears once per chain, each row with its own price and payability. */
1730
837
  endpoints: components["schemas"]["ApiEndpointSummary"][];
1731
- /** @description Endpoints matching the filters BEFORE paging - what `endpoints` is a page of. */
1732
838
  endpointTotal: number;
1733
- /** @description Where this provider is available, when the family being viewed is not it. A family view drops every listing measured as selling elsewhere, so this is what tells an owner on Testnet that the provider is available on Mainnet at all. Built from the other family's OWN probes - distinct endpoints measured `verified` or `free` there - never inferred from the rows dropped here, because a probe records THAT a provider quoted elsewhere and not WHERE. Null when no `net` was requested and null at a count of zero, so a client renders the pointer only when there is something to point at. */
1734
839
  otherFamily?: {
1735
- /**
1736
- * @description The family the endpoints below were measured on. Never the family being viewed.
1737
- * @enum {string}
1738
- */
1739
840
  net: "mainnet" | "testnet";
1740
- /** @description Distinct endpoints measured available in that family - `verified` or `free`, so this counts reachability and not sales. */
1741
841
  endpointCount: number;
1742
842
  } | null;
1743
843
  };
1744
- /** @description One endpoint under a provider, on one chain. */
1745
844
  ApiEndpointSummary: {
1746
845
  id: string;
1747
846
  path: string;
1748
- /** @enum {string} */
1749
847
  method: "GET" | "POST" | "HEAD" | "PUT" | "PATCH" | "DELETE";
1750
848
  summary: string;
1751
- /** @description Owner has blocked this endpoint for every agent on this account. Resolved: true when EITHER this endpoint or its provider is blocked. Absent state is `false`. Was `enabled` (inverted) until spec 2026-08-30 §3.2. */
1752
849
  blocked: boolean;
1753
- /** @description The chain this endpoint is listed on. Endpoints of one provider may differ. */
1754
850
  chainId: number;
1755
- /** @description Price in atomic token units - measured where `verification` is `verified`, otherwise the provider's own declaration. Null on a `free` endpoint and wherever no usable figure exists; never a fabricated zero. */
1756
851
  priceUnits: string | null;
1757
852
  asset: string | null;
1758
- /** @description Whether a paid call to this row could succeed at all. True only when an x402PaymentValidator is deployed on this endpoint's chain, the endpoint's `method` is one the paid lane can settle (GET or POST), `verification` is not `free`, AND `verification` is `verified` - that is, a probe has actually MEASURED a settleable 402 here. Never a policy decision - see `blocked` for that. The measured clause is spec 2026-08-26 §12: without it a never-probed row and a measured-failing row both read as payable, which offers a call the proxy would decline. */
1759
853
  payable: boolean;
1760
- /** @description Which of them, when `payable` is false. Reported in the order the proxy itself checks them, so the reason named is the one a caller would actually hit: `chain_capability_unavailable` (no validator on this chain - the only one a caller can act on, so it leads), `unsupported_endpoint_method` (the discovery index publishes all six verbs; the paid lane settles only GET and POST, and will not issue a stranger's DELETE to discover its price), `no_payment_required` (we measured a 200; there is nothing to settle), `provider_unverified` (never probed on this chain, so we cannot say a paid call would complete - the ORDINARY case, since most endpoints have never been probed), `provider_unreachable` (the last probe genuinely failed) or `provider_unavailable_on_chain` (measured as quoting elsewhere). */
1761
854
  unpayableReason: string | null;
1762
- /**
1763
- * @description What we MEASURED, never a gate. `verified` - a probe returned a 402 quoting this chain. `free` - a probe returned 200. `declared` - not probed yet, so price and asset are the provider's own claim. `other_chain` - the provider answered with a valid 402 but quoted payment on a DIFFERENT chain, so there is nothing to settle against here; it is reachable and is not a failure. A listing in this state is dropped from every family-scoped and chain-filtered response before a client ever sees it, so the value is retained in this enum only for backward compatibility and no longer appears on a returned row. `unreachable` - the last probe genuinely failed (a non-402 status, an unparseable challenge, a timeout); still listed, so a vanished provider has an explanation rather than silently disappearing. `other_chain` was carved OUT of `unreachable`: 650 of 1,510 stored probes are that case, and reporting a live provider as unreachable because it sells on mainnet is a false claim about a third party.
1764
- * @enum {string}
1765
- */
1766
855
  verification: "verified" | "free" | "declared" | "unreachable" | "other_chain";
1767
- /** @description 30-day unique payers, from the discovery index. A ranking signal only, never a gate. */
1768
856
  uniquePayers: number;
1769
- /** @description The provider's own OpenAPI OPERATION for this endpoint - `parameters` plus the JSON Schema at `requestBody.content['application/json'].schema` - matched by path and method from a document the SITE pass already fetched. NULL means the provider publishes no OpenAPI document, the sync has not read it yet, or the matched operation exceeded the size this catalog is willing to store (half a schema is worse than none). A NULL HERE MEANS THE CALLING AGENT IS GUESSING AT THE REQUEST SHAPE - there is no way to tell "no schema published" from "not fetched yet" apart from this field alone, and `call_api` pays before the provider gets a chance to reject a malformed body. */
1770
857
  requestSchema: {
1771
858
  parameters?: unknown[];
1772
859
  requestBody?: unknown;
1773
860
  } | null;
1774
861
  };
1775
- /** @description The current API budget state for an agent on a chain. */
1776
862
  ApiBudget: {
1777
863
  agentId: string;
1778
864
  chainId: number;
1779
- /** @description Unused indices below count. */
1780
865
  remaining: number;
1781
- /** @description Maximum value per call in token units. */
1782
866
  perCallMax: string;
1783
- /** Format: date-time */
1784
867
  expiresAt: string;
1785
868
  epoch: number;
1786
- /** @description The ERC-20 token address. */
1787
869
  token: string;
1788
- /** @description Maximum value exposure in token units. */
1789
870
  maxExposure: string;
1790
- /** @description Amount already spent in token units. */
1791
871
  spent: string;
1792
872
  };
1793
- /** @description The disjoint outcomes of `buildApiCallRequirements` - see each branch's own description. A `oneOf` discriminated on the literal `status` value (mirrors the `kind`-discriminated intent union on `POST /delegations/build`), so a client can never read `payload`/`authorization`/ `index`/`validator` off a response that carries none of them. */
1794
873
  ApiCallRequirements: components["schemas"]["ApiCallRequirementsReady"] | components["schemas"]["ApiCallRequirementsPending"];
1795
- /** @description `buildApiCallRequirements`'s ready branch - carries the EIP-3009 payload to sign, plus everything else a client needs to build the ERC-1271 envelope around its signature. For a Kernel account (the only kind this product ever creates) the relay signature is `0x01 || validator || abi.encode(agentKey, authorization, index, rawSig)`: `index` is a stateful server-side reservation with no formula a caller could reproduce, `authorization.validBefore` is stamped off the server's clock, and `validator` is returned rather than hardcoded because deployment addresses are nonce-shifted between chains - the same address is `agentGuard` on one chain and something else on another. */
1796
874
  ApiCallRequirementsReady: {
1797
875
  requirementId: string;
1798
- /**
1799
- * @description discriminator enum property added by openapi-typescript
1800
- * @enum {string}
1801
- */
1802
876
  status: "ready";
1803
- /** @description The EIP-3009 digest to sign. */
1804
877
  payload: string;
1805
- /** @description The provider's own quoted payment schemes (the x402 `accepts` array), echoed so a client can show what it is about to pay for without re-challenging. */
1806
878
  requirements: {
1807
879
  [key: string]: unknown;
1808
880
  }[];
1809
- /** @description The EIP-3009 authorization the payload digests. */
1810
881
  authorization: components["schemas"]["X402Authorization"];
1811
- /** @description The reserved authorization index. */
1812
882
  index: number;
1813
- /** @description The `X402PaymentValidator` address on this chain - bytes 1 to 20 of the Kernel ERC-1271 envelope a client must build around its signature. */
1814
883
  validator: string;
1815
884
  };
1816
- /** @description The exact EIP-3009 `TransferWithAuthorization` tuple `payload` digests. Building the Kernel- prefixed ERC-1271 signature envelope needs this verbatim - see `X402ProxyService.buildRequirements`'s own doc comment in the BE source for the byte layout. */
1817
885
  X402Authorization: {
1818
- /** @description The owner's account address. */
1819
886
  from: string;
1820
- /** @description The provider's `payTo` address. */
1821
887
  to: string;
1822
- /** @description Base units, decimal string - the wire format, not a bigint. */
1823
888
  value: string;
1824
- /** @description Unix seconds, decimal string. Always '0' today. */
1825
889
  validAfter: string;
1826
- /** @description Unix seconds, decimal string - timestamped off the BACKEND's clock at build time, never the caller's, and bounded by the provider's own stated timeout. */
1827
890
  validBefore: string;
1828
- /** @description 32 bytes, hex. Read live from `X402PaymentValidator.authorizationNonce` for this exact (epoch, index) - never generated by the backend. */
1829
891
  nonce: string;
1830
892
  };
1831
- /** @description `buildApiCallRequirements`'s pending branch (Task 11) - the quoted call crossed the agent's mandate `confirmAbove` threshold, so nothing sign-able was built. THE SECURITY PROPERTY: `payload`, `authorization`, `index` and `validator` are not merely empty here, they are not declared on this branch at all - `X402PaymentValidator._authorizationNonce` is a `pure` function of public inputs and the agent chooses its own `validBefore`, so an agent holding `(authorization, index, payload)` could sign and settle through any facilitator without ever calling Botanary again, which would make the confirmation threshold decorative. Poll `GET /apis/calls/requirements/{id}` for the owner's decision. */
1832
893
  ApiCallRequirementsPending: {
1833
894
  requirementId: string;
1834
- /**
1835
- * @description discriminator enum property added by openapi-typescript
1836
- * @enum {string}
1837
- */
1838
895
  status: "pending_approval";
1839
- /** @description The raised request's own id (equal to `requirementId`). */
1840
896
  approvalId: string;
1841
- /**
1842
- * Format: date-time
1843
- * @description When this pending approval closes unanswered - the same instant `requirementId` itself expires.
1844
- */
1845
897
  expiresAt: string;
1846
898
  };
1847
- /** @description `GET /apis/calls/requirements/{id}` (Task 11) - what the owner decided, if anything, about a call raised above the agent's `confirmAbove` threshold. See that route's own description for THE SECURITY PROPERTY this schema encodes: `payload`/`authorization`/`index`/`validator` (Task 14) present only when `status: 'approved'`. */
1848
899
  ApiCallRequirementStatus: {
1849
- /** @enum {string} */
1850
900
  status: "pending" | "approved" | "declined" | "expired";
1851
- /** @description The EIP-3009 digest to sign. Present only when status is 'approved'. */
1852
901
  payload?: string;
1853
902
  authorization?: components["schemas"]["X402Authorization"];
1854
- /** @description The reserved authorization index. Present only when status is 'approved'. */
1855
903
  index?: number;
1856
- /** @description The `X402PaymentValidator` address on this requirement's chain - bytes 1 to 20 of the Kernel ERC-1271 envelope a client builds around the signature. Present only when status is 'approved', same as the three fields above. */
1857
904
  validator?: string;
1858
905
  };
1859
- /** @description Recoverable payment status. Submitted means the provider may have received the authorization; never create another paid call to recover it. Settled means finalized chain evidence proves payment. The provider may still have refused the requested service; inspect providerStatus. */
1860
906
  ApiCallResult: {
1861
907
  requirementId: string;
1862
- /** @enum {string} */
1863
908
  status: "ready" | "pending_approval" | "submitted" | "settled" | "declined";
1864
- /** @enum {string} */
1865
909
  paymentStatus: "not_submitted" | "pending" | "settled" | "not_settled";
1866
- /** @description True if the provider or chain evidence is simulated. */
1867
910
  simulated: boolean;
1868
- /** @description The provider HTTP status, when a response was recorded. It is not payment proof. */
1869
911
  providerStatus?: number;
1870
- /** @description The provider response body, when available. May be any JSON value. */
1871
912
  response?: unknown;
1872
- /** @description Verified finalized transaction hash. Provider hints are not exposed as proof. */
1873
913
  txHash?: string;
1874
914
  facilitatorReason?: string;
1875
- /** @description Signing material is present only for an unsubmitted requirement with any required owner approval satisfied. */
1876
915
  ready?: {
1877
916
  payload: string;
1878
917
  authorization: components["schemas"]["X402Authorization"];
@@ -1883,70 +922,59 @@ export interface components {
1883
922
  DeveloperAgentChallenge: {
1884
923
  id: string;
1885
924
  appId: string;
1886
- /** @enum {string} */
1887
925
  environment: "test" | "live";
1888
926
  address: string;
1889
927
  publicKey: string;
1890
928
  message: string;
1891
- /** Format: date-time */
1892
929
  expiresAt: string;
1893
930
  };
1894
931
  DeveloperAgentRegistration: {
1895
932
  id: string;
1896
933
  appId: string;
1897
- /** @enum {string} */
1898
934
  environment: "test" | "live";
1899
935
  name: string;
1900
936
  publicKey: string;
1901
937
  address: string;
1902
938
  fingerprint: string;
1903
- /** Format: date-time */
1904
939
  createdAt: string;
1905
- /** Format: date-time */
1906
940
  disabledAt: string | null;
1907
- /** @enum {string} */
1908
941
  apiAccess: "awaiting_connection" | "active" | "disabled" | "app_disabled" | "key_revoked" | "connection_revoked" | "unavailable";
1909
- /** @enum {string} */
1910
942
  grantStatus: "none" | "pending" | "active" | "paused" | "expired" | "revoked" | "unknown";
1911
- /** @description Durable grants attributed to this exact registration, including strict observed chain state when available. */
1912
943
  grants?: components["schemas"]["PublicGrant"][];
1913
944
  connectionId: string | null;
945
+ embeddedBindingId?: string | null;
946
+ authorizationKind?: "hosted" | "embedded" | null;
1914
947
  };
1915
948
  PublicGrant: {
1916
949
  id: string;
1917
950
  appId: string;
1918
- /** @enum {string} */
1919
951
  environment: "test" | "live";
1920
- connectionId: string;
952
+ authorizationKind: "hosted" | "embedded";
953
+ connectionId: string | null;
954
+ embeddedBindingId: string | null;
955
+ bindingVersion: number | null;
1921
956
  registrationId: string;
1922
957
  agentId: string;
1923
958
  accountId: string;
1924
959
  accountAddress: components["schemas"]["Address"];
1925
960
  agentAddress: components["schemas"]["Address"];
1926
- /** @enum {integer} */
1927
961
  chainId: 84532;
1928
962
  name: string;
1929
963
  version: number;
1930
964
  permissionId: string;
965
+ salt: string;
1931
966
  grantExecutor: components["schemas"]["Address"];
1932
967
  policy: components["schemas"]["PublicGrantPolicy"];
1933
968
  compiled: components["schemas"]["PublicGrantCompiled"];
1934
- /** @enum {string} */
1935
969
  apiAccess: "active" | "awaiting_connection" | "connection_revoked" | "key_revoked" | "disabled" | "app_disabled" | "unavailable";
1936
970
  chainState: components["schemas"]["PublicGrantChainState"];
1937
971
  createOperationId: string;
1938
- /** Format: uri */
1939
- createApprovalUrl: string;
1940
- /** @enum {string} */
972
+ createApprovalUrl: string | null;
1941
973
  createStatus: "awaiting_approval" | "submitted" | "confirmed" | "failed" | "canceled" | "expired" | "unresolved";
1942
974
  revokeOperationId: string | null;
1943
- /** Format: uri */
1944
975
  revokeApprovalUrl: string | null;
1945
- /** @enum {string|null} */
1946
976
  revokeStatus: "awaiting_approval" | "submitted" | "confirmed" | "failed" | "canceled" | "expired" | "unresolved" | null;
1947
- /** Format: date-time */
1948
977
  createdAt: string;
1949
- /** Format: date-time */
1950
978
  updatedAt: string;
1951
979
  };
1952
980
  PublicGrantPolicy: {
@@ -1975,13 +1003,10 @@ export interface components {
1975
1003
  token: components["schemas"]["Address"];
1976
1004
  maxAllowanceRaw: string;
1977
1005
  } | null;
1978
- /** Format: date-time */
1979
1006
  expiresAt: string;
1980
1007
  };
1981
1008
  PublicGrantCondition: {
1982
- /** @enum {string} */
1983
1009
  field: "class" | "token" | "amount" | "total_value" | "recipient" | "target" | "selector" | "arg" | "call_count";
1984
- /** @enum {string} */
1985
1010
  op: "eq" | "neq" | "gte" | "lte" | "in_set" | "not_in_set";
1986
1011
  argOffset: number;
1987
1012
  value: string;
@@ -1989,7 +1014,6 @@ export interface components {
1989
1014
  PublicGrantCompiled: {
1990
1015
  enableCallData: string;
1991
1016
  configCalls: components["schemas"]["PublicGrantConfigurationCall"][];
1992
- /** @description Ordered account-global AgentGuard calls, including any transition from allow-all to an explicit token set. */
1993
1017
  accountGlobalConfigurationCalls: components["schemas"]["PublicGrantConfigurationCall"][];
1994
1018
  };
1995
1019
  PublicGrantConfigurationCall: {
@@ -1998,9 +1022,7 @@ export interface components {
1998
1022
  data: string;
1999
1023
  };
2000
1024
  PublicGrantChainState: {
2001
- /** @enum {string} */
2002
1025
  status: "unknown" | "active" | "paused" | "expired" | "revoked";
2003
- /** @enum {string|null} */
2004
1026
  reason: "not_observed" | "inconsistent_limits" | "observation_unavailable" | null;
2005
1027
  observedAt?: components["schemas"]["ConnectionOperationChainPoint"];
2006
1028
  remaining?: components["schemas"]["PublicGrantRemaining"][];
@@ -2025,7 +1047,6 @@ export interface components {
2025
1047
  };
2026
1048
  };
2027
1049
  responses: {
2028
- /** @description Malformed request. */
2029
1050
  BadRequest: {
2030
1051
  headers: {
2031
1052
  [name: string]: unknown;
@@ -2034,41 +1055,22 @@ export interface components {
2034
1055
  "application/json": components["schemas"]["ApiError"];
2035
1056
  };
2036
1057
  };
2037
- /** @description Missing or invalid session token. */
2038
1058
  Unauthorized: {
2039
1059
  headers: {
2040
1060
  [name: string]: unknown;
2041
1061
  };
2042
1062
  content: {
2043
- /**
2044
- * @example {
2045
- * "error": {
2046
- * "code": "unauthorized",
2047
- * "message": "Session token missing or expired."
2048
- * }
2049
- * }
2050
- */
2051
1063
  "application/json": components["schemas"]["ApiError"];
2052
1064
  };
2053
1065
  };
2054
- /** @description Access denied. */
2055
1066
  Forbidden: {
2056
1067
  headers: {
2057
1068
  [name: string]: unknown;
2058
1069
  };
2059
1070
  content: {
2060
- /**
2061
- * @example {
2062
- * "error": {
2063
- * "code": "forbidden",
2064
- * "message": "Access denied."
2065
- * }
2066
- * }
2067
- */
2068
1071
  "application/json": components["schemas"]["ApiError"];
2069
1072
  };
2070
1073
  };
2071
- /** @description Resource not found. */
2072
1074
  NotFound: {
2073
1075
  headers: {
2074
1076
  [name: string]: unknown;
@@ -2077,7 +1079,6 @@ export interface components {
2077
1079
  "application/json": components["schemas"]["ApiError"];
2078
1080
  };
2079
1081
  };
2080
- /** @description The intent is out of scope for the account rules or delegation policy. Carries the same decline-reason vocabulary the on-chain revert would produce. */
2081
1082
  PolicyDeclined: {
2082
1083
  headers: {
2083
1084
  [name: string]: unknown;
@@ -2086,26 +1087,16 @@ export interface components {
2086
1087
  "application/json": components["schemas"]["ApiError"];
2087
1088
  };
2088
1089
  };
2089
- /** @description This surface is turned off by an operator kill-switch (e.g. `PAY_SH_ENABLED=false`). Unlike NotImplemented, this IS transient: the same request will succeed once the flag is flipped back, with no other state to reconcile. */
2090
1090
  ServiceUnavailable: {
2091
1091
  headers: {
2092
1092
  [name: string]: unknown;
2093
1093
  };
2094
1094
  content: {
2095
- /**
2096
- * @example {
2097
- * "error": {
2098
- * "code": "unavailable",
2099
- * "message": "pay.sh is temporarily disabled."
2100
- * }
2101
- * }
2102
- */
2103
1095
  "application/json": components["schemas"]["ApiError"];
2104
1096
  };
2105
1097
  };
2106
1098
  };
2107
1099
  parameters: {
2108
- /** @example d1 */
2109
1100
  DelegationId: string;
2110
1101
  };
2111
1102
  requestBodies: never;
@@ -2127,14 +1118,12 @@ export interface operations {
2127
1118
  };
2128
1119
  };
2129
1120
  responses: {
2130
- /** @description Pairing initiated - the code is now active for claiming. */
2131
1121
  200: {
2132
1122
  headers: {
2133
1123
  [name: string]: unknown;
2134
1124
  };
2135
1125
  content: {
2136
1126
  "application/json": {
2137
- /** @example a1b2c3-d4e5f6 */
2138
1127
  code: string;
2139
1128
  };
2140
1129
  };
@@ -2155,7 +1144,6 @@ export interface operations {
2155
1144
  };
2156
1145
  };
2157
1146
  responses: {
2158
- /** @description A fresh nonce to sign. */
2159
1147
  200: {
2160
1148
  headers: {
2161
1149
  [name: string]: unknown;
@@ -2181,7 +1169,6 @@ export interface operations {
2181
1169
  };
2182
1170
  };
2183
1171
  responses: {
2184
- /** @description A fresh agent session token. */
2185
1172
  200: {
2186
1173
  headers: {
2187
1174
  [name: string]: unknown;
@@ -2202,7 +1189,6 @@ export interface operations {
2202
1189
  };
2203
1190
  requestBody?: never;
2204
1191
  responses: {
2205
- /** @description This agent's identity, account, and (if any) live grant. */
2206
1192
  200: {
2207
1193
  headers: {
2208
1194
  [name: string]: unknown;
@@ -2219,7 +1205,6 @@ export interface operations {
2219
1205
  listAgentRequests: {
2220
1206
  parameters: {
2221
1207
  query?: {
2222
- /** @description Specific account ID (owner only). Defaults to primary. */
2223
1208
  accountId?: string;
2224
1209
  };
2225
1210
  header?: never;
@@ -2228,7 +1213,6 @@ export interface operations {
2228
1213
  };
2229
1214
  requestBody?: never;
2230
1215
  responses: {
2231
- /** @description Array of agent requests (may be empty). */
2232
1216
  200: {
2233
1217
  headers: {
2234
1218
  [name: string]: unknown;
@@ -2254,7 +1238,6 @@ export interface operations {
2254
1238
  };
2255
1239
  };
2256
1240
  responses: {
2257
- /** @description The request has been raised. */
2258
1241
  200: {
2259
1242
  headers: {
2260
1243
  [name: string]: unknown;
@@ -2272,12 +1255,7 @@ export interface operations {
2272
1255
  getUnifiedBalance: {
2273
1256
  parameters: {
2274
1257
  query?: {
2275
- /** @description Scope the read to this specific account of the caller's (must belong to the authenticated signer - a foreign or unknown id is rejected, never silently ignored). Omitted defaults to the signer's lowest-visible-index account. */
2276
1258
  accountId?: string;
2277
- /**
2278
- * @description The chain the caller is currently viewing, as a CAIP-2 ref. A hint only: it promotes that chain to the front of this account's next background refresh so a first-ever deposit on an otherwise-untouched chain appears promptly. Never affects the response body. Forgiving - an unrecognized value is ignored, never a 400.
2279
- * @example solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1
2280
- */
2281
1259
  focusChainRef?: string;
2282
1260
  };
2283
1261
  header?: never;
@@ -2286,7 +1264,6 @@ export interface operations {
2286
1264
  };
2287
1265
  requestBody?: never;
2288
1266
  responses: {
2289
- /** @description The unified balance. */
2290
1267
  200: {
2291
1268
  headers: {
2292
1269
  [name: string]: unknown;
@@ -2308,7 +1285,6 @@ export interface operations {
2308
1285
  };
2309
1286
  requestBody?: never;
2310
1287
  responses: {
2311
- /** @description Supported chains. */
2312
1288
  200: {
2313
1289
  headers: {
2314
1290
  [name: string]: unknown;
@@ -2323,14 +1299,8 @@ export interface operations {
2323
1299
  listGasMethods: {
2324
1300
  parameters: {
2325
1301
  query?: {
2326
- /** @description Scope the per-method balances to this specific account of the caller's (must belong to the authenticated signer - a foreign or unknown id is rejected, never silently ignored). Omitted defaults to the signer's lowest-visible-index account. */
2327
1302
  accountId?: string;
2328
- /** @description Compute gas-method availability for this specific EVM chain. A basic-tier chain (a bundler but no Circle Paymaster - e.g. Robinhood) reports USDC/USDT gas as unavailable and native gas as the default. At least one of `chainId`/`key` is REQUIRED; a request with neither is a 400. If both are supplied, `key` takes priority and this is ignored. */
2329
1303
  chainId?: number;
2330
- /**
2331
- * @description Compute gas-method availability for this specific Stellar chain KEY instead of an EVM `chainId` (Stellar is key-keyed, not chainId-keyed). When present, returns Stellar's `native` (always) and `usdc` (only when the hosted gasless relayer - design doc §2 - is healthy) rows, in place of the EVM chainId-keyed path.
2332
- * @example stellar-testnet
2333
- */
2334
1304
  key?: string;
2335
1305
  };
2336
1306
  header?: never;
@@ -2339,7 +1309,6 @@ export interface operations {
2339
1309
  };
2340
1310
  requestBody?: never;
2341
1311
  responses: {
2342
- /** @description Gas methods. */
2343
1312
  200: {
2344
1313
  headers: {
2345
1314
  [name: string]: unknown;
@@ -2356,7 +1325,6 @@ export interface operations {
2356
1325
  getAccount: {
2357
1326
  parameters: {
2358
1327
  query?: {
2359
- /** @description When present, returns the address that is actually usable on this chain, deriving and persisting a counterfactual record for it if the account has never touched it. Omitted keeps the chain-blind default (whichever row is deployed, or the lowest index). */
2360
1328
  chainId?: number;
2361
1329
  };
2362
1330
  header?: never;
@@ -2365,7 +1333,6 @@ export interface operations {
2365
1333
  };
2366
1334
  requestBody?: never;
2367
1335
  responses: {
2368
- /** @description The account. */
2369
1336
  200: {
2370
1337
  headers: {
2371
1338
  [name: string]: unknown;
@@ -2383,7 +1350,6 @@ export interface operations {
2383
1350
  query?: never;
2384
1351
  header?: never;
2385
1352
  path: {
2386
- /** @example d1 */
2387
1353
  delegationId: components["parameters"]["DelegationId"];
2388
1354
  };
2389
1355
  cookie?: never;
@@ -2394,7 +1360,6 @@ export interface operations {
2394
1360
  };
2395
1361
  };
2396
1362
  responses: {
2397
- /** @description Unsigned delegated-action op (session-key-signed). */
2398
1363
  200: {
2399
1364
  headers: {
2400
1365
  [name: string]: unknown;
@@ -2424,7 +1389,6 @@ export interface operations {
2424
1389
  };
2425
1390
  };
2426
1391
  responses: {
2427
- /** @description Unsigned agent operation bound to the explicit execution context. */
2428
1392
  200: {
2429
1393
  headers: {
2430
1394
  [name: string]: unknown;
@@ -2433,7 +1397,6 @@ export interface operations {
2433
1397
  "application/json": components["schemas"]["ExactDelegatedActionBuild"];
2434
1398
  };
2435
1399
  };
2436
- /** @description Request refused or unavailable; no signature is produced by the API. */
2437
1400
  400: {
2438
1401
  headers: {
2439
1402
  [name: string]: unknown;
@@ -2442,7 +1405,6 @@ export interface operations {
2442
1405
  "application/json": components["schemas"]["ApiError"];
2443
1406
  };
2444
1407
  };
2445
- /** @description Request refused or unavailable; no signature is produced by the API. */
2446
1408
  401: {
2447
1409
  headers: {
2448
1410
  [name: string]: unknown;
@@ -2451,7 +1413,6 @@ export interface operations {
2451
1413
  "application/json": components["schemas"]["ApiError"];
2452
1414
  };
2453
1415
  };
2454
- /** @description Request refused or unavailable; no signature is produced by the API. */
2455
1416
  403: {
2456
1417
  headers: {
2457
1418
  [name: string]: unknown;
@@ -2460,7 +1421,6 @@ export interface operations {
2460
1421
  "application/json": components["schemas"]["ApiError"];
2461
1422
  };
2462
1423
  };
2463
- /** @description Request refused or unavailable; no signature is produced by the API. */
2464
1424
  404: {
2465
1425
  headers: {
2466
1426
  [name: string]: unknown;
@@ -2469,7 +1429,6 @@ export interface operations {
2469
1429
  "application/json": components["schemas"]["ApiError"];
2470
1430
  };
2471
1431
  };
2472
- /** @description Request refused or unavailable; no signature is produced by the API. */
2473
1432
  409: {
2474
1433
  headers: {
2475
1434
  [name: string]: unknown;
@@ -2478,7 +1437,6 @@ export interface operations {
2478
1437
  "application/json": components["schemas"]["ApiError"];
2479
1438
  };
2480
1439
  };
2481
- /** @description Request refused or unavailable; no signature is produced by the API. */
2482
1440
  422: {
2483
1441
  headers: {
2484
1442
  [name: string]: unknown;
@@ -2487,7 +1445,6 @@ export interface operations {
2487
1445
  "application/json": components["schemas"]["ApiError"];
2488
1446
  };
2489
1447
  };
2490
- /** @description Request refused or unavailable; no signature is produced by the API. */
2491
1448
  429: {
2492
1449
  headers: {
2493
1450
  [name: string]: unknown;
@@ -2496,7 +1453,6 @@ export interface operations {
2496
1453
  "application/json": components["schemas"]["ApiError"];
2497
1454
  };
2498
1455
  };
2499
- /** @description Request refused or unavailable; no signature is produced by the API. */
2500
1456
  500: {
2501
1457
  headers: {
2502
1458
  [name: string]: unknown;
@@ -2505,7 +1461,6 @@ export interface operations {
2505
1461
  "application/json": components["schemas"]["ApiError"];
2506
1462
  };
2507
1463
  };
2508
- /** @description Request refused or unavailable; no signature is produced by the API. */
2509
1464
  503: {
2510
1465
  headers: {
2511
1466
  [name: string]: unknown;
@@ -2529,7 +1484,6 @@ export interface operations {
2529
1484
  };
2530
1485
  };
2531
1486
  responses: {
2532
- /** @description Accepted for relay. */
2533
1487
  202: {
2534
1488
  headers: {
2535
1489
  [name: string]: unknown;
@@ -2540,7 +1494,6 @@ export interface operations {
2540
1494
  };
2541
1495
  400: components["responses"]["BadRequest"];
2542
1496
  401: components["responses"]["Unauthorized"];
2543
- /** @description Hosted operation requires the authenticated owner browser. */
2544
1497
  403: {
2545
1498
  headers: {
2546
1499
  [name: string]: unknown;
@@ -2549,7 +1502,6 @@ export interface operations {
2549
1502
  "application/json": components["schemas"]["ApiError"];
2550
1503
  };
2551
1504
  };
2552
- /** @description Hosted submission is already in progress or its review changed. Resume the durable operation ID. */
2553
1505
  409: {
2554
1506
  headers: {
2555
1507
  [name: string]: unknown;
@@ -2572,7 +1524,6 @@ export interface operations {
2572
1524
  };
2573
1525
  requestBody?: never;
2574
1526
  responses: {
2575
- /** @description The UserOp receipt / status. */
2576
1527
  200: {
2577
1528
  headers: {
2578
1529
  [name: string]: unknown;
@@ -2597,7 +1548,6 @@ export interface operations {
2597
1548
  };
2598
1549
  requestBody?: never;
2599
1550
  responses: {
2600
- /** @description The recorded operation and its current settlement status. */
2601
1551
  200: {
2602
1552
  headers: {
2603
1553
  [name: string]: unknown;
@@ -2606,7 +1556,6 @@ export interface operations {
2606
1556
  "application/json": components["schemas"]["UserOpReceipt"];
2607
1557
  };
2608
1558
  };
2609
- /** @description Receipt lookup refused, unknown or unavailable. */
2610
1559
  400: {
2611
1560
  headers: {
2612
1561
  [name: string]: unknown;
@@ -2615,7 +1564,6 @@ export interface operations {
2615
1564
  "application/json": components["schemas"]["ApiError"];
2616
1565
  };
2617
1566
  };
2618
- /** @description Receipt lookup refused, unknown or unavailable. */
2619
1567
  401: {
2620
1568
  headers: {
2621
1569
  [name: string]: unknown;
@@ -2624,7 +1572,6 @@ export interface operations {
2624
1572
  "application/json": components["schemas"]["ApiError"];
2625
1573
  };
2626
1574
  };
2627
- /** @description Receipt lookup refused, unknown or unavailable. */
2628
1575
  403: {
2629
1576
  headers: {
2630
1577
  [name: string]: unknown;
@@ -2633,7 +1580,6 @@ export interface operations {
2633
1580
  "application/json": components["schemas"]["ApiError"];
2634
1581
  };
2635
1582
  };
2636
- /** @description Receipt lookup refused, unknown or unavailable. */
2637
1583
  404: {
2638
1584
  headers: {
2639
1585
  [name: string]: unknown;
@@ -2642,7 +1588,6 @@ export interface operations {
2642
1588
  "application/json": components["schemas"]["ApiError"];
2643
1589
  };
2644
1590
  };
2645
- /** @description Receipt lookup refused, unknown or unavailable. */
2646
1591
  429: {
2647
1592
  headers: {
2648
1593
  [name: string]: unknown;
@@ -2651,7 +1596,6 @@ export interface operations {
2651
1596
  "application/json": components["schemas"]["ApiError"];
2652
1597
  };
2653
1598
  };
2654
- /** @description Receipt lookup refused, unknown or unavailable. */
2655
1599
  500: {
2656
1600
  headers: {
2657
1601
  [name: string]: unknown;
@@ -2660,7 +1604,6 @@ export interface operations {
2660
1604
  "application/json": components["schemas"]["ApiError"];
2661
1605
  };
2662
1606
  };
2663
- /** @description Receipt lookup refused, unknown or unavailable. */
2664
1607
  503: {
2665
1608
  headers: {
2666
1609
  [name: string]: unknown;
@@ -2674,15 +1617,10 @@ export interface operations {
2674
1617
  listApiProviders: {
2675
1618
  parameters: {
2676
1619
  query?: {
2677
- /** @description The chain to filter by. Only providers with an endpoint listed on this chain are included. Omitted, every chain the catalog knows is returned instead. */
2678
1620
  chainId?: number;
2679
- /** @description Optional asset address. If provided, further filters to providers quoting this specific asset on the chain. Bounded like the other free-text filters - an EVM address is 42 characters, a Solana mint at most 44. */
2680
1621
  asset?: string;
2681
- /** @description Case-insensitive substring over a provider's id, name, category and description. Applied server-side, and to the hidden set as well as the shown one, so `hidden` answers the question the search asked rather than one about the whole catalog. */
2682
1622
  q?: string;
2683
- /** @description Page size. Out of range is refused, never clamped. */
2684
1623
  limit?: number;
2685
- /** @description Rows to skip. The order is total (`curated` first, then `rankScore` descending, then `id` ascending), so paging can neither duplicate nor drop a provider. The curated tier leads because it is the only tier anyone has reviewed; `rankScore` measures traffic, not trust. */
2686
1624
  offset?: number;
2687
1625
  };
2688
1626
  header?: never;
@@ -2691,7 +1629,6 @@ export interface operations {
2691
1629
  };
2692
1630
  requestBody?: never;
2693
1631
  responses: {
2694
- /** @description One page of the ranked catalog, with the total it is a page of. */
2695
1632
  200: {
2696
1633
  headers: {
2697
1634
  [name: string]: unknown;
@@ -2708,15 +1645,10 @@ export interface operations {
2708
1645
  getApiProvider: {
2709
1646
  parameters: {
2710
1647
  query?: {
2711
- /** @description The chain to FILTER endpoints by. Only endpoints with measured or declared evidence for this chain are included. Omitted, every chain the catalog knows is included, so an endpoint with no measured or declared chain lists once per supported chain. */
2712
1648
  chainId?: number;
2713
- /** @description Which network family to VIEW this provider on - a view scope, not a filter, and NOT a synonym for `chainId`. It narrows the chains considered to that family without asking an evidence question, so an endpoint that declares no chain still lists once, unmeasured, instead of disappearing. This is what makes a Testnet/Mainnet toggle possible on a provider whose endpoints declare no chain, which is every curated provider in the catalog. Sending both is accepted and `chainId` wins, being the stricter of the two. */
2714
1649
  net?: "mainnet" | "testnet";
2715
- /** @description Case-insensitive substring over an endpoint's path, summary and method. */
2716
1650
  q?: string;
2717
- /** @description Page size. Out of range is refused, never clamped. */
2718
1651
  limit?: number;
2719
- /** @description Endpoints to skip. The order is total (`uniquePayers` descending, then path, chainId, id), so paging can neither duplicate nor drop a row. */
2720
1652
  offset?: number;
2721
1653
  };
2722
1654
  header?: never;
@@ -2727,7 +1659,6 @@ export interface operations {
2727
1659
  };
2728
1660
  requestBody?: never;
2729
1661
  responses: {
2730
- /** @description The provider, with one page of its endpoints. */
2731
1662
  200: {
2732
1663
  headers: {
2733
1664
  [name: string]: unknown;
@@ -2753,7 +1684,6 @@ export interface operations {
2753
1684
  };
2754
1685
  requestBody?: never;
2755
1686
  responses: {
2756
- /** @description The current budget state. */
2757
1687
  200: {
2758
1688
  headers: {
2759
1689
  [name: string]: unknown;
@@ -2781,18 +1711,12 @@ export interface operations {
2781
1711
  providerId: string;
2782
1712
  endpointId: string;
2783
1713
  agentId: string;
2784
- /**
2785
- * Format: uri
2786
- * @description Full URL of the endpoint to call, query parameters included. A GET endpoint's parameters belong here - it is the only place they can go.
2787
- */
2788
1714
  url: string;
2789
- /** @description Raw request body for a POST endpoint, forwarded to the provider byte for byte and never parsed, reshaped or logged by Botanary - it may carry the caller's own credentials for that provider. Send it as a string (JSON endpoints: the serialised JSON), not an object. The body a price is quoted for is the body that gets paid for: it is captured with the 402 challenge and replayed at relay, so it cannot be changed after the quote. Supplying one for a GET endpoint is declined (`request_body_not_supported`). Size limit: **32768 UTF-8 BYTES**, measured on the wire - not characters. The `maxLength: 32768` above is JSON Schema's own rule and counts CHARACTERS, so it is a necessary bound but not the whole one: a string under 32768 characters can still be up to four times that in UTF-8, and the server declines it with `request_body_too_large`. Size the body in bytes, not in `String.length`. */
2790
1715
  body?: string;
2791
1716
  };
2792
1717
  };
2793
1718
  };
2794
1719
  responses: {
2795
- /** @description The EIP-3009 authorization payload. */
2796
1720
  200: {
2797
1721
  headers: {
2798
1722
  [name: string]: unknown;
@@ -2811,14 +1735,12 @@ export interface operations {
2811
1735
  query?: never;
2812
1736
  header?: never;
2813
1737
  path: {
2814
- /** @description The requirement id from `buildApiCallRequirements`. */
2815
1738
  id: string;
2816
1739
  };
2817
1740
  cookie?: never;
2818
1741
  };
2819
1742
  requestBody?: never;
2820
1743
  responses: {
2821
- /** @description The current status, and the signing material once (and only once) approved. */
2822
1744
  200: {
2823
1745
  headers: {
2824
1746
  [name: string]: unknown;
@@ -2829,7 +1751,6 @@ export interface operations {
2829
1751
  };
2830
1752
  400: components["responses"]["BadRequest"];
2831
1753
  401: components["responses"]["Unauthorized"];
2832
- /** @description No such id, it does not belong to this account, or it belongs to a different agent - the same refusal for all three, since which one is true is not information this route may leak. */
2833
1754
  404: {
2834
1755
  headers: {
2835
1756
  [name: string]: unknown;
@@ -2851,15 +1772,12 @@ export interface operations {
2851
1772
  requestBody: {
2852
1773
  content: {
2853
1774
  "application/json": {
2854
- /** @description The ID returned by buildApiCallRequirements. */
2855
1775
  requirementId: string;
2856
- /** @description The agent's signature of the EIP-3009 payload. */
2857
1776
  signature: string;
2858
1777
  };
2859
1778
  };
2860
1779
  };
2861
1780
  responses: {
2862
- /** @description The provider's response, marked simulated or real. */
2863
1781
  200: {
2864
1782
  headers: {
2865
1783
  [name: string]: unknown;
@@ -2885,7 +1803,6 @@ export interface operations {
2885
1803
  };
2886
1804
  requestBody?: never;
2887
1805
  responses: {
2888
- /** @description Durable status, with signing material only while ready and authorized. */
2889
1806
  200: {
2890
1807
  headers: {
2891
1808
  [name: string]: unknown;
@@ -2900,4 +1817,3 @@ export interface operations {
2900
1817
  };
2901
1818
  };
2902
1819
  }
2903
- //# sourceMappingURL=schema.d.ts.map