W weft/api v1 v0.32.1

Weft API Reference

Build buyer applications that discover and pay for resources on Weft.

Quickstart

Connecting an AI agent? Use https://weft.network/setup.md instead — it connects the account with browser OAuth, and there is no API key to paste into the conversation. This quickstart is for developers building their own buyer application.

Weft's buyer API uses a wk_* key created in the dashboard. The signup and sign-in API endpoints do not issue a bearer token.

  1. Create a Weft account and confirm your email.
  2. Create a buyer API key.
  3. Copy the wk_* key when it is shown. It cannot be displayed again.
  4. Store it as WEFT_API_KEY and make your first request.
export WEFT_API_KEY='wk_your_key_here'

curl --fail-with-body https://weft.network/api/v1/me \
  --header "Authorization: Bearer $WEFT_API_KEY"

Search is authenticated and free for buyers in the current release:

curl --fail-with-body https://weft.network/api/v1/search \
  --header "Authorization: Bearer $WEFT_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"query":"company enrichment API","max_results":3}'

Guides

Human-oriented guides live on weftlabs.com:

Agent bootstrap

An agent without a Weft account can start a 30-minute, email-claimed bootstrap. It asks the human only for an email address—never a password—and returns one wbt_* secret. Creation is public and rate-limited per IP and normalized email.

curl --fail-with-body https://weft.network/api/v1/account_bootstraps \
  --header "Content-Type: application/json" \
  --data '{
    "email":"human@example.com",
    "agent_name":"Research agent",
    "host_name":"Claude Code",
    "reason":"Find weather data"
  }'

The response never says whether that email already has an account. A separate, private claim link goes only to the email address. The human creates an account or freshly signs in, reviews the agent context and fixed access, enters the matching user_code shown by the agent, then approves or rejects it. The server capability set is not caller-configurable.

Successful create, status, and cancel responses use the normal top-level data envelope. If the mail relay cannot accept the claim email, creation returns a retryable 503 and leaves no bootstrap row or unusable credential.

Treat wbt_* exactly like an API key: do not print, paste, log, or commit it. Before claim it can call only search, status, and cancel while the 30-minute claim window remains open. After approval, the same bearer becomes durable and can call identity, search, balance, fetch, purchase history, status, and self-revocation. It cannot call seller, organization, API-key administration, dashboard-session, transfer, withdrawal, or MCP surfaces. Human revocation from Connections denies every subsequent request immediately.

Beyond a possible one-time signup grant (campaign-gated), there is no promotional balance or treasury subsidy in this flow. Paid fetch starts only after human claim, normal wallet provisioning, and funding — the human adds money at https://weft.network/dashboard/wallet.

Base URLs

  • Production: https://weft.network

Authentication

Send credentials in the bearer header:

Authorization: Bearer <credential>
  • Credential identity: both wk_* and ax_live_* keys authorize me; the response identifies whether the credential represents a buyer User or a seller Organization.
  • Buyer runtime: use a dashboard-created wk_* key for balance, search, fetch, and purchase history.
  • Seller administration: organization and resource-management operations require an ax_live_* resource key. These keys do not authorize buyer-only runtime operations.
  • Connected clients: an OAuth access token can authorize the buyer operations covered by its scopes.
  • Claimed agents: a promoted wbt_* bearer can authorize only its fixed buyer-runtime allowlist until the human revokes it.
  • Public operations: signup, sign-in, account recovery, OpenAPI download, and resource enrollment do not require a bearer credential.

Treat every key as a secret. Keep it out of source control and client-side browser bundles, and rotate it from the dashboard if it is exposed.

TypeScript SDK

TypeScript is Weft's supported application SDK. WeftClient is the primary buyer interface; generated API classes remain available for advanced use.

npm install @weftlabs/sdk
import { WeftClient } from "@weftlabs/sdk";

const apiKey = process.env.WEFT_API_KEY;
if (!apiKey) {
  throw new Error("Set WEFT_API_KEY to a buyer wk_* API key");
}

const weft = new WeftClient({
  apiKey,
  ...(process.env.WEFT_BASE_URL ? { baseUrl: process.env.WEFT_BASE_URL } : {}),
});

const account = await weft.me();
const search = await weft.search({ query: "weather data API" });

console.log(JSON.stringify({ account: account.data, results: search.results }));

Python, Ruby, and Go packages are generated API clients. They are available for developers who need low-level access, but they are not yet at feature parity with the supported TypeScript WeftClient experience.

SDK examples are shown alongside endpoints where a verified example is available.

Charge for your API

Everything above is the buyer side: you spend. This section is the seller side: you get paid. An agent pays per request, and the money settles to your wallet. Weft never holds it.

1. Create a seller key

Selling needs a seller key, not the buyer wk_* key above.

  1. Create a seller API key.
  2. Copy the ax_live_* key when it is shown. It cannot be displayed again.
  3. Store it as WEFT_SELLER_API_KEY.

A buyer wk_* key spends. A seller ax_live_* key gets paid. They are not interchangeable, and the middleware needs the seller key.

2. Install

npm install @weftlabs/sdk @x402/core @x402/evm express

The SDK carries the payment middleware. @x402/evm carries the scheme that prices the route and shapes the payment. Both are required: a route whose scheme is not registered is rejected at startup.

3. Set the environment

Variable Meaning
WEFT_SELLER_API_KEY Your ax_live_* seller key. Authenticates settlement.
WEFT_PAY_TO The wallet address that receives the money.
WEFT_NETWORK CAIP-2 chain id. Defaults to eip155:8453 (Base).
X402_FACILITATOR_URL Optional override. Defaults to https://x402.weft.network.

Treat WEFT_SELLER_API_KEY like any other secret: never in source control, never in a browser bundle.

4. Protect a route — Express

import express from "express";
import { ExactEvmScheme } from "@x402/evm/exact/server";
import { weftPaymentMiddleware } from "@weftlabs/sdk/facilitator/middleware";

const apiKey = process.env.WEFT_SELLER_API_KEY;
if (!apiKey) {
  throw new Error("Set WEFT_SELLER_API_KEY to a seller ax_live_* API key");
}

const payTo = process.env.WEFT_PAY_TO;
if (!payTo) {
  throw new Error("Set WEFT_PAY_TO to the wallet address that gets paid");
}

const network = process.env.WEFT_NETWORK ?? "eip155:8453";

const app = express();

app.use(
  weftPaymentMiddleware(
    {
      "GET /v1/quote": {
        accepts: { scheme: "exact", network, payTo, price: "$0.01" },
      },
    },
    {
      apiKey,
      name: "Acme Pricing API",
      type: "api",
      tags: ["finance", "pricing"],
      schemes: [{ network, server: new ExactEvmScheme() }],
    },
  ),
);

app.get("/v1/quote", (_req, res) => {
  res.json({ symbol: "ACME", price: "12.34", currency: "USD" });
});

const port = Number(process.env.PORT ?? 3000);
app.listen(port, () => {
  console.log(JSON.stringify({ listening: port }));
});

5. Or with Hono

weftPaymentMiddlewareHono takes the same configuration:

import { Hono } from "hono";
import { ExactEvmScheme } from "@x402/evm/exact/server";
import { weftPaymentMiddlewareHono } from "@weftlabs/sdk/facilitator/middleware";

const apiKey = process.env.WEFT_SELLER_API_KEY;
if (!apiKey) {
  throw new Error("Set WEFT_SELLER_API_KEY to a seller ax_live_* API key");
}

const payTo = process.env.WEFT_PAY_TO;
if (!payTo) {
  throw new Error("Set WEFT_PAY_TO to the wallet address that gets paid");
}

const network = process.env.WEFT_NETWORK ?? "eip155:8453";

const app = new Hono();

app.use(
  weftPaymentMiddlewareHono(
    {
      "GET /v1/quote": {
        accepts: { scheme: "exact", network, payTo, price: "$0.01" },
      },
    },
    {
      apiKey,
      name: "Acme Pricing API",
      type: "api",
      tags: ["finance", "pricing"],
      schemes: [{ network, server: new ExactEvmScheme() }],
    },
  ),
);

app.get("/v1/quote", (c) =>
  c.json({ symbol: "ACME", price: "12.34", currency: "USD" }),
);

export default app;

What happens per request

An unpaid caller does not reach your handler. It receives 402 Payment Required with a PAYMENT-REQUIRED header describing the price, the network and the payee. The caller pays, retries with a PAYMENT-SIGNATURE header, and this time your handler runs and returns its normal response.

Behind that, the middleware calls the facilitator twice. /verify checks the buyer's payment before your handler runs. /settle moves the money after your handler returns success.

/settle rejects a call without your seller key — every settlement returns 401 and you are never paid. /verify does not require the key, but it reads it when present, and the facilitator uses it to attribute verification attempts to your product. Set apiKey once and both are covered.

Your handler is never charged for twice: a response with status 400 or above is returned to the caller without settling.

When something fails

What you see What it means What to do
[weft] facilitator sync failed at boot The facilitator was unreachable when the process started. Nothing. The server keeps serving and re-syncs in the background.
402 with Settlement failed The settlement call did not complete. Retryable by the caller.
Every settlement fails with 401 The seller key is missing, malformed, or from another organization. Seller action: check WEFT_SELLER_API_KEY.
Startup rejects the route The route's scheme and network pair has no registered implementation. Seller action: pass schemes as the examples do.
402 challenges name no payee payTo is unset. Seller action: set WEFT_PAY_TO.

Advanced: the facilitator REST contract

The middleware is the normal path. If you implement x402 yourself, the facilitator exposes /supported, /verify, and /settle directly at https://x402.weft.network. That contract is documented in the x402-facilitator repository. You do not need it to charge for a route.

The Weft API powers the weft CLI, the hosted MCP server (weft.network/mcp), and third-party applications that discover and pay for resources on Weft. The buyer runtime covers six concerns:

  1. Account creation and recovery (/api/v1/auth/*)
  2. Credential identity (/api/v1/me)
  3. Wallet visibility (/api/v1/balance)
  4. Discovery (/api/v1/search)
  5. Paid execution (/api/v1/fetch)
  6. Purchase history (/api/v1/purchases)

Buyer runtime calls require a dashboard-created wk_* account key, an OAuth access token with the relevant scope, or a claimed wbt_* bearer on its fixed allowlist. The organization-scoped API key and payment operations in this document are seller administration surfaces and require an ax_live_* resource key. These credential types are not interchangeable.

This document is a deliberate subset of the /api/v1 surface, not an inventory of it. The seller-side management endpoints — /api/v1/agents, /api/v1/webhook_endpoints, and /api/v1/analytics — are reachable with an ax_live_* key but are intentionally left undocumented: they are dashboard-facing and not part of the published client contract. Nothing outside this document is a supported contract, and the response-validation gate in config/environments/test.rb enforces only what is declared here.

Before claim, a wbt_* bearer is temporary and permits only search plus its own status/cancel operations for 30 minutes. Human approval binds it to the User and promotes the same secret to durable identity, search, balance, fetch, purchase-history, status, and revocation capabilities. It remains valid until revoked. Seller, organization, API-key administration, dashboard-session, transfer, withdrawal, and MCP surfaces always refuse it.

Bootstrap lifecycle successes follow the API-standard { "data": ... } envelope. All errors share the envelope defined by ErrorResponse, except the buyer-runtime endpoints (/search, /fetch) which use bespoke envelopes carrying additional context — see SearchErrorResponse and FetchErrorResponse.

Authentication

  • HTTP Authentication, scheme: bearer Dashboard wk_* key, OAuth token, or a claimed wbt_* bearer on its fixed identity, search, balance, fetch, and purchase-history allowlist.

  • HTTP Authentication, scheme: bearer A wbt_* credential. Before claim it permits search, status, and cancellation for 30 minutes. Human approval promotes the same bearer to a fixed durable capability set until revocation.

Agent Bootstrap

Temporary search-only access followed by human promotion of the same bearer.

Create a temporary agent bootstrap

POST /api/v1/account_bootstraps

Creates a 30-minute, search-only bootstrap and emails a separate claim link to the supplied address. Human approval binds the same wbt_* bearer to the account and promotes it to the fixed durable capability set. The response is deliberately identical for new and existing account emails and never contains the claim token. Rate limits apply per IP and normalized email; request bodies over 4 KiB are rejected before parsing. The bootstrap row and one-time credentials are committed only after the mail relay accepts the claim email. A retryable 503 leaves no bootstrap row behind.

Request body

{
  "email": "human@example.com",
  "agent_name": "Research agent",
  "host_name": "OpenCode",
  "reason": "Find weather data"
}

Parameters

Name In Type Required Description
body body AccountBootstrapRequest true none

201 Response

{
  "data": {
    "id": "boot_01K3C9Y7Q4R6T8V2W5X0Z1A3B4",
    "status": "pending",
    "capabilities": [
      "search",
      "status",
      "cancel"
    ],
    "expires_at": "2026-08-22T14:30:00Z",
    "approval": {
      "method": "email_link",
      "expires_in": 1800,
      "interval": 5,
      "user_code": "W3FT-7K2M"
    },
    "temporary_api_key": "wbt_example_store_as_a_secret"
  }
}

Responses

Status Meaning Description Schema
201 Created Bootstrap created after the claim email is accepted for delivery AccountBootstrapCreatedResponse
413 Payload Too Large Request body exceeds the 4 KiB limit ErrorResponse
422 Unprocessable Entity Invalid bootstrap context ErrorResponse
429 Too Many Requests Rate limit exceeded RateLimitResponse
503 Service Unavailable Claim email delivery is temporarily unavailable; no bootstrap was created and the request may be retried ErrorResponse

Response Headers

Status Header Type Format Description
503 Retry-After string Suggested delay before retrying, in seconds.

No authentication required

Read bootstrap lifecycle status

GET /api/v1/account_bootstraps/{id}

Parameters

Name In Type Required Description
id path string true none

200 Response

{
  "data": {
    "id": "boot_01K3C9Y7Q4R6T8V2W5X0Z1A3B4",
    "status": "claimed",
    "capabilities": [
      "identity",
      "search",
      "balance",
      "fetch",
      "purchases",
      "status",
      "revoke"
    ],
    "expires_at": null,
    "approval": {
      "method": "email_link",
      "expires_in": 0,
      "interval": 5
    }
  }
}

Responses

Status Meaning Description Schema
200 OK Current lifecycle and polling guidance while the credential can authenticate AccountBootstrapStatusResponse
401 Unauthorized Unknown ID or non-matching bootstrap credential ErrorResponse

Cancel or revoke a bootstrap credential

DELETE /api/v1/account_bootstraps/{id}

A pending bootstrap becomes rejected. A claimed promoted credential becomes revoked and fails every subsequent request immediately.

Parameters

Name In Type Required Description
id path string true none

200 Response

{
  "data": {
    "id": "boot_01K3C9Y7Q4R6T8V2W5X0Z1A3B4",
    "status": "claimed",
    "capabilities": [
      "identity",
      "search",
      "balance",
      "fetch",
      "purchases",
      "status",
      "revoke"
    ],
    "expires_at": null,
    "approval": {
      "method": "email_link",
      "expires_in": 0,
      "interval": 5
    }
  }
}

Responses

Status Meaning Description Schema
200 OK Rejected or revoked terminal lifecycle status AccountBootstrapStatusResponse
401 Unauthorized Unknown ID or non-matching bootstrap credential ErrorResponse

Auth

Account creation and authentication flows.

Create an account

POST /api/v1/auth/sign_up

Request body

{
  "email": "user@example.com",
  "password": "string",
  "password_confirmation": "string"
}

Parameters

Name In Type Required Description
body body SignUpRequest true none

200 Response

{
  "data": {
    "user": {
      "id": 0,
      "email": "user@example.com",
      "status": "string"
    },
    "token": "string",
    "confirmation_required": true
  }
}

Responses

Status Meaning Description Schema
200 OK Account created AuthResponse
422 Unprocessable Entity Validation error ErrorResponse
429 Too Many Requests Rate limit exceeded (20 accounts/hour/IP) ErrorResponse

No authentication required

Confirm an account

POST /api/v1/auth/confirm

Request body

{
  "confirmation_token": "string"
}

Parameters

Name In Type Required Description
body body ConfirmRequest true none

200 Response

{
  "data": {
    "user": {
      "id": 0,
      "email": "user@example.com",
      "status": "string"
    },
    "token": "string",
    "confirmation_required": true
  }
}

Responses

Status Meaning Description Schema
200 OK Account confirmed AuthResponse
422 Unprocessable Entity Invalid token ErrorResponse

No authentication required

Resend confirmation email

POST /api/v1/auth/resend-confirmation

Request body

{
  "email": "user@example.com"
}

Parameters

Name In Type Required Description
body body ResendConfirmationRequest true none

200 Response

{
  "data": {
    "message": "string"
  }
}

Responses

Status Meaning Description Schema
200 OK Confirmation sent MessageResponse

No authentication required

Sign in with email and password

POST /api/v1/auth/sign_in

Request body

{
  "email": "user@example.com",
  "password": "string"
}

Parameters

Name In Type Required Description
body body SignInRequest true none

200 Response

{
  "data": {
    "user": {
      "id": 0,
      "email": "user@example.com",
      "status": "string"
    },
    "token": "string",
    "confirmation_required": true
  }
}

Responses

Status Meaning Description Schema
200 OK Signed in AuthResponse
401 Unauthorized Invalid credentials ErrorResponse

No authentication required

Request password reset

POST /api/v1/auth/password/reset

Request body

{
  "email": "user@example.com"
}

Parameters

Name In Type Required Description
body body PasswordResetRequest true none

200 Response

{
  "data": {
    "message": "string"
  }
}

Responses

Status Meaning Description Schema
200 OK Reset email sent MessageResponse

No authentication required

Update password with reset token

POST /api/v1/auth/password/update

Request body

{
  "reset_password_token": "string",
  "password": "string",
  "password_confirmation": "string"
}

Parameters

Name In Type Required Description
body body PasswordUpdateRequest true none

200 Response

{
  "data": {
    "message": "string"
  }
}

Responses

Status Meaning Description Schema
200 OK Password updated MessageResponse
422 Unprocessable Entity Invalid or expired reset token ErrorResponse

No authentication required

Account

Current user account information.

Get the current credential principal

GET /api/v1/me

Returns the seller Organization represented by an ax_live_* resource key, or the buyer User represented by a wk_* account key, OAuth access token, or claimed wbt_* bearer. Branch on data.principal_type.

200 Response

{
  "data": {
    "principal_type": "organization",
    "id": 0,
    "name": "string",
    "slug": "string",
    "kind": "string",
    "api_key": {
      "id": 0,
      "name": "string",
      "created_at": "2019-08-24T14:15:22Z",
      "last_used_at": "2019-08-24T14:15:22Z",
      "created_by": {
        "id": 0,
        "email": "user@example.com",
        "display_name": "string"
      }
    }
  }
}

Responses

Status Meaning Description Schema
200 OK Current Organization or User principal MeResponse
401 Unauthorized Unauthorized ErrorResponse

Requires authentication: Bearer token

Verified SDK example

WeftClient.me()

import { WeftClient } from "@weftlabs/sdk";

const apiKey = process.env.WEFT_API_KEY;
if (!apiKey) {
  throw new Error("Set WEFT_API_KEY to a buyer wk_* API key");
}

const weft = new WeftClient({
  apiKey,
  ...(process.env.WEFT_BASE_URL ? { baseUrl: process.env.WEFT_BASE_URL } : {}),
});

const account = await weft.me();
const search = await weft.search({ query: "weather data API" });

console.log(JSON.stringify({ account: account.data, results: search.results }));

API Keys

Manage seller organization/resource keys (ax_live_*). Buyer runtime keys (wk_*) are created and rotated in the buyer dashboard.

List API keys

GET /api/v1/api_keys

List ax_live_* resource keys for the seller Organization.

200 Response

{
  "data": [
    {
      "id": 0,
      "name": "string",
      "key_prefix": "string",
      "last_used_at": "2019-08-24T14:15:22Z",
      "revoked_at": "2019-08-24T14:15:22Z",
      "created_at": "2019-08-24T14:15:22Z"
    }
  ],
  "pagination": {
    "page": 0,
    "per_page": 0,
    "total": 0,
    "total_pages": 0
  }
}

Responses

Status Meaning Description Schema
200 OK List of API keys ApiKeyListResponse
401 Unauthorized Unauthorized ErrorResponse
403 Forbidden The credential authenticated but has no organization context

(ORGANIZATION_REQUIRED). Account-scoped (buyer) keys cannot read this org-scoped endpoint.|ErrorResponse|

Requires authentication: Bearer token

Create an API key

POST /api/v1/api_keys

Create an ax_live_* resource key for the authenticated seller Organization. Buyer wk_* keys are created in the buyer dashboard.

Request body

{
  "name": "string"
}

Parameters

Name In Type Required Description
body body CreateApiKeyRequest true none

201 Response

{
  "data": {
    "id": 0,
    "name": "string",
    "key_prefix": "string",
    "raw_key": "string",
    "created_at": "2019-08-24T14:15:22Z"
  }
}

Responses

Status Meaning Description Schema
201 Created API key created (includes raw key, shown only once) ApiKeyCreatedResponse
401 Unauthorized Unauthorized ErrorResponse
422 Unprocessable Entity Validation error ErrorResponse

Requires authentication: Bearer token

Revoke an API key

DELETE /api/v1/api_keys/{id}

Parameters

Name In Type Required Description
id path integer true API key ID

200 Response

{
  "data": {
    "message": "string"
  }
}

Responses

Status Meaning Description Schema
200 OK API key revoked MessageResponse
401 Unauthorized Unauthorized ErrorResponse
404 Not Found API key not found ErrorResponse

Requires authentication: Bearer token

Balance

Read-only snapshot of the buyer's wallet, spending policy, and current-window spend (today / this week).

Get wallet, spending policy, and current-window spend

GET /api/v1/balance

Read-only snapshot for the buyer behind the bearer token. The response always includes a promo block — values are zero in v1 and fill in once the freemium promo ledger ships, without a shape change. The Base USDC balance is fetched server-side through Crossmint. If Crossmint is unreachable, the balance fields are null; consumers must not interpret that as zero.

Account-scoped: the bearer must be a buyer-scoped API key, an OAuth access token carrying balance, or a claimed wbt_* bearer.

200 Response

{
  "promo": {
    "balance_usd": "0.00",
    "scope": "weft-search",
    "expires_at": "2019-08-24T14:15:22Z"
  },
  "wallet": {
    "provider": "crossmint",
    "address": "string",
    "balance_usdc": "12.34",
    "balance_tempo_usd": "2.03",
    "total_usd": "12.34",
    "network": "string"
  },
  "spent_today_usd": "0.0005",
  "spent_week_usd": "3.10",
  "policy_used_today_usd": "0.30",
  "policy_used_week_usd": "3.30",
  "policy": {
    "max_tx_usd": "1.00",
    "daily_limit_usd": "10.00",
    "weekly_limit_usd": "50.00"
  }
}

Responses

Status Meaning Description Schema
200 OK Wallet + policy + spend snapshot BalanceResponse
401 Unauthorized Unauthorized — missing or non-buyer-scoped API key ErrorResponse
403 Forbidden The OAuth access token authenticated but lacks the balance

scope (RFC 6750 insufficient_scope). Carries a WWW-Authenticate: Bearer error="insufficient_scope", scope="balance" header. wk_ API keys are unscoped and never see this.|InsufficientScopeResponse|

Requires authentication: Bearer token

Search

Semantic search across the Weft index of paid agent resources. Returns A2A-shaped AgentCards with pricing, skills, ranking, and endpoints.

Search the Weft index

POST /api/v1/search

Semantic search over the Weft index of paid agent resources. The request body is the weft-search-platform /v1/search contract: a free-text query, optional max_results, and optional structured filters (price / priceatomic / type / protocol — the canonical FilterSpec v1 vocabulary, vendored verbatim from the platform). Price is a dual representation of one constraint: price in USD decimal strings (the reasoning form) XOR `priceatomic` in integer micro-USD (the settlement form) — mutually exclusive, set at most one.

Account-scoped: the bearer token must be a buyer-scoped API key, an OAuth token carrying search, or a pending or claimed wbt_* bootstrap bearer. Pending bootstrap access uses an anonymous bootstrap identity; after claim, the promoted bearer uses its bound User. Rejection, cancellation, expiry, and revocation end bootstrap search. Bootstrap search is limited to 60 requests per credential and 120 per IP each hour before native credential promotion.

Response negotiation: Accept: application/json (default) returns the structured envelope; Accept: text/markdown returns a rendered Markdown digest of the same results — useful for piping into a chat UI or LLM prompt.

Compact view: send view: "compact" to get the agent view of the hosted MCP weft_search tool. Each result is a small contract for the next paid call (below 2,000 JSON bytes): typed inputs, the request recipe, one access method with price, attribution, a ready next_call to POST /api/v1/fetch when the request is determined, and the authenticated contract_url for the full contract. Use it when you give search results to a model. The compact rows are in compact_results; results is empty. The compact view is JSON only and needs the curated search backend.

Request body

{
  "query": "send email from an agent",
  "max_results": 10,
  "filters": {
    "price": {
      "lte": "string",
      "gte": "string",
      "eq": "string",
      "range_gte": "string",
      "range_lte": "string"
    },
    "price_atomic": {
      "lte": 0,
      "gte": 0,
      "eq": 0,
      "range_gte": 0,
      "range_lte": 0
    },
    "type": {
      "eq": "api",
      "in": [
        "api"
      ]
    },
    "protocol": {
      "eq": "x402",
      "in": [
        "x402"
      ]
    },
    "category": {
      "eq": "string",
      "in": [
        "string"
      ]
    },
    "method": {
      "eq": "GET",
      "in": [
        "GET"
      ]
    },
    "execution_mode": {
      "eq": "sync",
      "in": [
        "sync"
      ]
    },
    "weft_fetch_compatible": true,
    "include_unknown_prices": false
  },
  "view": "full"
}

Parameters

Name In Type Required Description
body body SearchRequest true none

200 Response

{
  "query_trace_id": "2e536172-f35a-49b0-b5b1-ca3970d0f446",
  "query": "string",
  "format": "json",
  "markdown": "string",
  "result_count": 0,
  "served_from": "live",
  "as_of": "2019-08-24T14:15:22Z",
  "stale": true,
  "payment_note": "string",
  "applied_filters": {
    "price": {
      "lte": "string",
      "gte": "string",
      "eq": "string",
      "range_gte": "string",
      "range_lte": "string"
    },
    "price_atomic": {
      "lte": 0,
      "gte": 0,
      "eq": 0,
      "range_gte": 0,
      "range_lte": 0
    },
    "type": {
      "eq": "api",
      "in": [
        "api"
      ]
    },
    "protocol": {
      "eq": "x402",
      "in": [
        "x402"
      ]
    },
    "category": {
      "eq": "string",
      "in": [
        "string"
      ]
    },
    "method": {
      "eq": "GET",
      "in": [
        "GET"
      ]
    },
    "execution_mode": {
      "eq": "sync",
      "in": [
        "sync"
      ]
    },
    "weft_fetch_compatible": true,
    "include_unknown_prices": false
  },
  "decomposition_source": "CALLER",
  "embedder_model": "string",
  "candidates_considered": 0,
  "warnings": [
    {
      "code": "string",
      "message": "string",
      "cause": "string",
      "context": {}
    }
  ],
  "match_quality": "strong",
  "reason": "below_relevance_floor",
  "suggestion": "string",
  "results": [
    {
      "provider": {
        "provider_id": "string",
        "display_name": "string",
        "origin_domains": [
          "string"
        ]
      },
      "capability": {
        "capability_id": "string",
        "capability_type": "string"
      },
      "endpoints": [
        {
          "endpoint_id": "string",
          "url": "string",
          "resource_type": "string",
          "primary_protocol": "string",
          "call": {
            "method": "string",
            "input_schema": {},
            "example_request": {},
            "example_response": null
          },
          "price": {
            "indexed_usd": "string",
            "atomic": 0,
            "source": "probe",
            "last_observed_at": "2019-08-24T14:15:22Z",
            "live_verified": true
          },
          "payment": [
            {
              "protocol": "string",
              "scheme": "string",
              "network": "string",
              "asset": "string",
              "amount": "string",
              "pay_to": "string",
              "max_timeout_seconds": 0,
              "facilitator": "string"
            }
          ],
          "access_methods": [
            {
              "access_method_id": "string",
              "protocol": "x402",
              "scheme": "string",
              "network": "string",
              "asset": "string",
              "asset_decimals": 0,
              "price": {},
              "merchant": {},
              "terms": {},
              "status": "listed",
              "weft_fetch": {
                "state": "supported",
                "reason": "string",
                "contract_version": 0,
                "coverage": "terminal_response"
              }
            }
          ],
          "service": {
            "id": "string",
            "name": "string"
          },
          "operation": {
            "id": "string",
            "name": "string",
            "description": "string"
          },
          "docs": {
            "website": "http://example.com",
            "homepage": "http://example.com",
            "api": "http://example.com",
            "llms_txt": "http://example.com"
          },
          "contract_url": "http://example.com",
          "output_schema": {},
          "output": {},
          "execution": {
            "mode": "sync"
          },
          "callability": {
            "state": "complete",
            "missing": [
              "string"
            ]
          },
          "compatibility": {},
          "source": {
            "catalog": "curated_marketplace",
            "snapshot_version": 0,
            "captured_at": "2019-08-24T14:15:22Z"
          },
          "operator_type": "first_party",
          "operated_by_id": "string",
          "settled_via_facilitator_id": "string",
          "settlements": 0,
          "last_verified_at": "2019-08-24T14:15:22Z",
          "latency_p50_ms": 0
        }
      ],
      "score": 0
    }
  ],
  "view": "full",
  "compact_results": [
    {
      "provider": {
        "id": "string",
        "name": "string"
      },
      "operation": {
        "id": "string",
        "name": "string",
        "description": "string"
      },
      "inputs": {},
      "request": {},
      "example": null,
      "access": {
        "id": "string",
        "protocol": "string",
        "weft_fetch": {},
        "price": {
          "kind": "string",
          "indexed_usd": "string",
          "unit": "string",
          "hint": "string"
        }
      },
      "attribution": {
        "search_id": "d5826b15-4ef0-45f4-80df-3b8d5f941dd6",
        "operation_id": "string",
        "access_method_id": "string"
      },
      "output": {},
      "docs": {
        "website": "http://example.com",
        "homepage": "http://example.com",
        "api": "http://example.com",
        "llms_txt": "http://example.com"
      },
      "contract_url": "http://example.com",
      "contract_detail": "string",
      "completion": "string",
      "blocked_scopes": [
        {
          "scope": "string",
          "state": "string"
        }
      ],
      "contract_gaps": [
        "string"
      ],
      "readiness": {
        "property1": {
          "state": "string",
          "scope": "string"
        },
        "property2": {
          "state": "string",
          "scope": "string"
        }
      },
      "next_call": {
        "method": "POST",
        "path": "/api/v1/fetch",
        "body": {},
        "fill": [
          "string"
        ]
      }
    }
  ],
  "omitted_results": 1
}

Responses

Status Meaning Description Schema
200 OK Search results string
401 Unauthorized Unauthorized — missing or non-buyer-scoped API key ErrorResponse
403 Forbidden The OAuth access token authenticated but lacks the search

scope (RFC 6750 insufficient_scope). Carries a WWW-Authenticate: Bearer error="insufficient_scope", scope="search" header. wk_ API keys are unscoped and never see this.|InsufficientScopeResponse| |406|Not Acceptable|The requested response format is not JSON or Markdown.|None| |422|Unprocessable Entity|Invalid request — empty/missing query, out-of-range max_results, an unknown top-level parameter, invalid filters (unknown filter key/operator, bad enum value, or a sub-filter without exactly one operator), or an invalid view (unknown value, Accept: text/markdown, or a backend without the compact view). See the error code.|SearchErrorResponse| |429|Too Many Requests|Bootstrap search rate limit exceeded|RateLimitResponse| |500|Internal Server Error|Internal server error|SearchErrorResponse| |502|Bad Gateway|Search service unavailable|SearchErrorResponse|

Requires authentication: Bearer token

Verified SDK example

WeftClient.search(request)

import { WeftClient } from "@weftlabs/sdk";

const apiKey = process.env.WEFT_API_KEY;
if (!apiKey) {
  throw new Error("Set WEFT_API_KEY to a buyer wk_* API key");
}

const weft = new WeftClient({
  apiKey,
  ...(process.env.WEFT_BASE_URL ? { baseUrl: process.env.WEFT_BASE_URL } : {}),
});

const account = await weft.me();
const search = await weft.search({ query: "weather data API" });

console.log(JSON.stringify({ account: account.data, results: search.results }));

Fetch

The universal x402/MPP fetch proxy. POST any URL the agent wants to reach, with a max_cost_usd ceiling; Weft handles the 402 Payment Required challenge, authorizes payment from the buyer's wallet on the selected rail, replays the request, and streams the upstream artifact back base64-encoded. Errors always carry the buyer's current policy + balance + dashboard URL so the caller can surface "what changed?" without a second round-trip.

Pay-and-fetch any URL (x402/MPP proxy)

POST /api/v1/fetch

Universal x402/MPP fetch proxy. The caller provides a target url, a merchant-principal max_cost_usd ceiling, and optional method / body / headers. Weft:

  1. Issues the request.
  2. On 402 Payment Required, selects a supported x402 or MPP challenge.
  3. Compares the asking price to max_cost_usd and the buyer's policy (max_tx_usd, daily/weekly limits).
  4. If refill is allowed and an eligible mainnet MPP challenge finds its Tempo token short, creates or adopts a buyer-owned Base-to-Tempo refill and returns 409 FUNDING_PENDING with details.reason=funding_active. If an overlapping payment invalidates the balance observation before a bridge is created, the same retryable response carries details.reason=balance_changed. The caller retries the identical fetch after details.retry_after_seconds; that later request obtains a fresh challenge and reruns rail selection and all payment controls.
  5. Authorizes payment from the buyer's wallet on the selected rail.
  6. Replays the request with the protocol-specific payment credential.
  7. Streams the upstream artifact back, base64-encoded under body_base64, with paid_usd, held_usd, payment_status, tx_hash, protocol, and purchase_id. paid_usd is "0.00" until the charge is CONFIRMED settled — a signed-but- unsettled hold (the common case for x402, which settles asynchronously) reports its amount in held_usd instead, never in paid_usd. purchase_id is the id that GET /api/v1/purchases/{id} accepts, so a caller can read how a pending charge ends.

Opt-in safety controls: allow_tempo_refill: false prevents this request from creating, adopting, or enqueueing a Base-to-Tempo bridge. A Tempo shortfall returns 402 INSUFFICIENT_BALANCE; unrelated bridges and their jobs remain unchanged. access_method_id is advisory and does not enforce a payment rail.

max_total_cost_usd is an all-in ceiling covering merchant principal, network gas, provider fees, and prerequisite buyer-paid operations. It disables refill; explicitly combining it with allow_tempo_refill: true returns 422 INCOMPATIBLE_FETCH_CONTROLS. Current wallet integrations provide no supported binding all-in fee guarantee. Therefore all-in requests return 402 TOTAL_COST_UNVERIFIABLE before payment preparation, approval, reservation, or refill. This also refuses recovery of older payments and SIWX wallet signing; it admits no positive paid route. Increasing the ceiling does not resolve missing fee authority.

Omitted controls preserve existing behavior. Ordinary non-402 merchant responses retain MERCHANT_RETURNED_NON_402. Stored-result replay is historical payment information, not a new bounded authorization.

Errors are structured with a stable error code, and each error response carries the buyer's policy, balance, and a dashboard_url so a CLI can render an actionable message without a second round-trip.

Account-scoped: the bearer must be a buyer-scoped API key, an OAuth access token carrying fetch, or a claimed wbt_* bearer.

Forwarded headers: the caller's headers are passed through to the upstream, except a denylist of hop-by-hop and Weft-internal headers (host, authorization, cookie, proxy-authorization, x-forwarded-*, x-real-ip, x-payment, connection, upgrade). Up to 32 headers, 4 KB of combined value bytes.

Request body

{
  "url": "https://x402.api.agentmail.to/v0/inboxes",
  "max_cost_usd": "0.05",
  "allow_tempo_refill": false,
  "max_total_cost_usd": "0.05",
  "method": "GET",
  "body": "string",
  "headers": {
    "Accept": "application/json",
    "User-Agent": "my-agent/1.0"
  },
  "search_id": "11111111-1111-4111-8111-111111111111",
  "operation_id": "string",
  "access_method_id": "string"
}

Parameters

Name In Type Required Description
Idempotency-Key header string false Opaque caller-generated retry key. Reusing the same key for the
body body FetchRequest true none

Detailed descriptions

Idempotency-Key: Opaque caller-generated retry key. Reusing the same key for the same buyer converges on one paid fetch; keys are hashed and namespaced by buyer before storage. Send this header for every unattended or retryable paid request. Effective safety controls participate in retry identity. Changing them under a reserved key returns IDEMPOTENCY_CONFLICT; an older unconstrained payment cannot become a bounded success on retry.

200 Response

{
  "status": 200,
  "headers": {
    "property1": "string",
    "property2": "string"
  },
  "body_base64": "string",
  "paid_usd": "0.002",
  "held_usd": "0.002",
  "payment_status": "pending",
  "tx_hash": "string",
  "protocol": "x402",
  "artifact_id": 0,
  "purchase_id": "pur_4V3n9mQ0b7XyK2sLpR8tWc1d"
}

Responses

Status Meaning Description Schema
200 OK Paid fetch succeeded; artifact streamed back base64-encoded. FetchResponse
401 Unauthorized Unauthorized — missing or non-buyer-scoped API key ErrorResponse
402 Payment Required Payment refused. EXCEEDED_MAX_COST (over the caller cap) or

INSUFFICIENT_BALANCE (the buyer is genuinely short — details.asset, when present, names the exact token the failed check read). TOTAL_COST_UNVERIFIABLE means no binding upper bound on all buyer costs is available; details.reason is binding_cost_unavailable. No payment operation or refill is authorized by this refusal. An earlier uncertain payment remains uncertain; the refusal does not cancel or release it. These errors use FetchErrorResponse.|FetchErrorResponse| |403|Forbidden|Policy violation, missing Crossmint payment permission (PAYMENT_AUTHORIZATION_REQUIRED — details carries the wallet-page URL where the authenticated user can enable payments), denylisted recipient, or a merchant challenge on a chain outside the wallet's own environment — a testnet wallet may not pay a mainnet challenge, nor the reverse (WALLET_ENVIRONMENT_MISMATCH; terminal, not retryable). All four use FetchErrorResponse. Alternatively an OAuth access token lacking the fetch scope (InsufficientScopeResponse, RFC 6750 insufficient_scope, with a WWW-Authenticate challenge). The two envelopes are disjoint; branch on the error value.|Inline| |409|Conflict|IDEMPOTENCY_CONFLICT — this buyer already used the supplied Idempotency-Key for a different fetch request. Generate a new key for the new operation; retry the original operation unchanged.

Or WALLET_SETUP_INCOMPLETE — the buyer's wallet has not been created yet, so there is nothing to pay from. details.wallet_url carries the page where the authenticated user finishes setup. No retry succeeds until they do.

Or ACCOUNT_CLOSING — account closure has started, so the wallet cannot reserve a new payment.

Or FUNDING_PENDING — retry after details.retry_after_seconds. details.reason is funding_active when a buyer-owned Base-to-Tempo refill exists, or balance_changed when an overlapping payment invalidated the balance observation before funding could start.

Or DELIVERY_REPLAY_UNAVAILABLE — the merchant already returned a successful response for this settled MPP payment, but Weft could not persist its bytes for replay. The merchant is not called again; details.tx_hash identifies the settled payment. All five use FetchErrorResponse.|FetchErrorResponse| |413|Payload Too Large|Upstream artifact exceeded the proxy's size cap.|FetchErrorResponse| |422|Unprocessable Entity|Invalid request fields, method, cost, body, headers, idempotency key, or URL. Safety controls use INVALID_ALLOW_TEMPO_REFILL, INVALID_MAX_TOTAL_COST_USD, or INCOMPATIBLE_FETCH_CONTROLS. UNSUPPORTED_ASSET means the merchant requested an asset this wallet cannot settle. UNSUPPORTED_PAYMENT_METHOD means the MPP challenge requested a method Weft cannot execute.|FetchErrorResponse| |424|Failed Dependency|MERCHANT_RETURNED_NON_402 — the upstream merchant is at fault: it did not return a 402, or its 402 challenge was invalid. A 4xx (not 5xx) because Weft behaved correctly and the caller should act on details.reason (e.g. pick another merchant); it also keeps the error envelope intact through CDNs that replace 5xx bodies.

PAID_DELIVERY_FAILED — the MPP payment settled, but the merchant did not deliver a successful response. details.tx_hash identifies the settled payment; details.merchant_status is present when the merchant returned an HTTP response.|FetchErrorResponse| |502|Bad Gateway|Merchant connection failure (MERCHANT_CONNECTION_FAILED) or settlement signing failed on Weft's side (SETTLEMENT_FAILED). For merchant failures, details.phase identifies challenge or paid; paid requests may have moved funds. Reuse the same idempotency key. details.reason carries a stable payment sentence. details.protocol names a direct payment rail when that is safe and useful. It is absent for automatic-funding failures so provider, bridge, and retry details stay internal.|FetchErrorResponse| |504|Gateway Time-out|MERCHANT_TIMEOUT — the upstream merchant did not complete the challenge or paid request inside Weft's transport budget. details.phase names the request. When it is paid, details.payment_may_have_moved is true because the credential was already sent. Retry the identical operation with the same Idempotency-Key.

SETTLEMENT_PENDING — the payment was submitted and the wallet provider had not reached a terminal state before Weft's polling budget ran out. NOTHING is known to have failed: the charge may already have settled, so this is not SETTLEMENT_FAILED and the amount is not lost. details.retry_with_same_idempotency_key is true.

Retry the identical request shortly. Sending the same Idempotency-Key resumes the same provider operation; a caller that sends no key is also safe, because Weft resumes its own in-flight operation for the same merchant, amount and network rather than opening a second one. Either way the retry resolves the original payment instead of charging twice.|FetchErrorResponse|

Response Schema

Enumerated Values

Property Value
error INVALID_REQUEST
error UNKNOWN_PARAMETER
error INVALID_URL
error INVALIDMAXCOST_USD
error INVALIDALLOWTEMPO_REFILL
error INVALIDMAXTOTALCOSTUSD
error INCOMPATIBLEFETCHCONTROLS
error UNSUPPORTED_METHOD
error INVALID_BODY
error INVALID_HEADERS
error INVALIDIDEMPOTENCYKEY
error IDEMPOTENCY_CONFLICT
error ACCOUNT_CLOSING
error EXCEEDEDMAXCOST
error TOTALCOSTUNVERIFIABLE
error FUNDING_PENDING
error INSUFFICIENT_BALANCE
error PAYMENTAUTHORIZATIONREQUIRED
error WALLETSETUPINCOMPLETE
error MERCHANTRETURNEDNON_402
error MERCHANT_TIMEOUT
error MERCHANTCONNECTIONFAILED
error PAIDDELIVERYFAILED
error DELIVERYREPLAYUNAVAILABLE
error ARTIFACTTOOLARGE
error DENYLISTED_RECIPIENT
error WALLETENVIRONMENTMISMATCH
error UNSUPPORTED_ASSET
error UNSUPPORTEDPAYMENTMETHOD
error SETTLEMENT_FAILED
error SETTLEMENT_PENDING
error POLICYVIOLATIONMAX_TX
error POLICYVIOLATIONDAILY
error POLICYVIOLATIONWEEKLY
error insufficient_scope

Requires authentication: Bearer token

Payments

Seller Organization payment receipts.

List payments

GET /api/v1/payments

Parameters

Name In Type Required Description
page query integer false Page number
per_page query integer false Items per page

200 Response

{
  "data": [
    {
      "id": 0,
      "tx_hash": "string",
      "payer_address": "string",
      "recipient_address": "string",
      "amount": 0,
      "amount_formatted": "string",
      "currency": "string",
      "network": "string",
      "resource_url": "string",
      "resource_host": "string",
      "settlement_latency_ms": 0,
      "settled_at": "2019-08-24T14:15:22Z",
      "api_key_name": "string"
    }
  ],
  "pagination": {
    "page": 0,
    "per_page": 0,
    "total": 0,
    "total_pages": 0
  }
}

Responses

Status Meaning Description Schema
200 OK List of payments PaymentListResponse
401 Unauthorized Unauthorized ErrorResponse
403 Forbidden The credential authenticated but has no organization context

(ORGANIZATION_REQUIRED). Account-scoped (buyer) keys cannot read this org-scoped endpoint.|ErrorResponse|

Requires authentication: Bearer token

Get payment details

GET /api/v1/payments/{id}

Parameters

Name In Type Required Description
id path integer true Payment ID

200 Response

{
  "data": {
    "id": 0,
    "tx_hash": "string",
    "payer_address": "string",
    "recipient_address": "string",
    "amount": 0,
    "amount_formatted": "string",
    "currency": "string",
    "network": "string",
    "resource_url": "string",
    "resource_host": "string",
    "settlement_latency_ms": 0,
    "settled_at": "2019-08-24T14:15:22Z",
    "api_key_name": "string"
  }
}

Responses

Status Meaning Description Schema
200 OK Payment details PaymentResponse
401 Unauthorized Unauthorized ErrorResponse
404 Not Found Payment not found ErrorResponse

Requires authentication: Bearer token

Purchases

Buyer signing and settlement history.

List buyer purchases

GET /api/v1/purchases

Returns the authenticated buyer's signing and settlement ledger. Unlike /api/v1/payments, this endpoint is User-scoped and backed by signed_events, so rejected and pending attempts are included.

Scoped to the buyer's own merchant spend, matching the dashboard's Purchases page. Internal signings are excluded: historical refill self-transfers (rebalance) and operator signings (manual) are not payments the buyer made and never appear here.

Parameters

Name In Type Required Description
page query integer false Page number
per_page query integer false Items per page

200 Response

{
  "data": [
    {
      "id": 0,
      "purchase_id": "pur_4V3n9mQ0b7XyK2sLpR8tWc1d",
      "status": "signed",
      "amount_usd": "string",
      "recipient_address": "string",
      "network": "string",
      "protocol": "mpp",
      "context": "string",
      "search_id": "string",
      "attribution_status": "attributed",
      "tx_hash": "string",
      "reject_reason": "string",
      "failure_reason": "string",
      "idempotency_key": "string",
      "signed_at": "2019-08-24T14:15:22Z",
      "settled_at": "2019-08-24T14:15:22Z",
      "artifact": {
        "id": 0,
        "merchant_url": "http://example.com",
        "bytes": 0,
        "mime": "string"
      }
    }
  ],
  "pagination": {
    "page": 0,
    "per_page": 0,
    "total": 0,
    "total_pages": 0
  }
}

Responses

Status Meaning Description Schema
200 OK Buyer purchase ledger PurchaseListResponse
401 Unauthorized Unauthorized — missing or non-buyer-scoped credential ErrorResponse
403 Forbidden OAuth token lacks the balance scope. InsufficientScopeResponse

Requires authentication: Bearer token

Get a buyer purchase

GET /api/v1/purchases/{id}

Parameters

Name In Type Required Description
id path any true The opaque purchase_id (pur_…) that fetch returns, or the

Detailed descriptions

id: The opaque purchase_id (pur_…) that fetch returns, or the legacy integer id. Both resolve only within the caller's own purchases. New callers should store and send purchase_id.

200 Response

{
  "data": {
    "id": 0,
    "purchase_id": "pur_4V3n9mQ0b7XyK2sLpR8tWc1d",
    "status": "signed",
    "amount_usd": "string",
    "recipient_address": "string",
    "network": "string",
    "protocol": "mpp",
    "context": "string",
    "search_id": "string",
    "attribution_status": "attributed",
    "tx_hash": "string",
    "reject_reason": "string",
    "failure_reason": "string",
    "idempotency_key": "string",
    "signed_at": "2019-08-24T14:15:22Z",
    "settled_at": "2019-08-24T14:15:22Z",
    "artifact": {
      "id": 0,
      "merchant_url": "http://example.com",
      "bytes": 0,
      "mime": "string"
    }
  }
}

Responses

Status Meaning Description Schema
200 OK Buyer purchase details PurchaseResponse
401 Unauthorized Unauthorized — missing or non-buyer-scoped credential ErrorResponse
403 Forbidden OAuth token lacks the balance scope. InsufficientScopeResponse
404 Not Found Purchase not found or owned by another buyer ErrorResponse

Requires authentication: Bearer token

Resources

Public, unauthenticated ghost-resource enrollment. Lets an agent self-register so its human controller can later claim it from the dashboard.

Self-enroll a ghost resource (public, no auth)

POST /api/v1/resources/enroll

Lets an unauthenticated agent (or its operator) self-enroll a Resource as a "ghost" (no owning provider). The server generates the slug and a single-use claim_token; the response also carries a claim_url the agent hands to its human controller to claim the resource from the dashboard.

Client-supplied slug and category are silently ignored: slugs are server-generated from name (so callers cannot squat on reserved names), and category is a post-claim concern set by a real human.

Rate-limited to 10 enrollments/hour/IP.

Request body

{
  "kind": "agent",
  "name": "Self-Enrolled Bot",
  "description": "string",
  "wallet_address": "string"
}

Parameters

Name In Type Required Description
body body ResourceEnrollmentRequest true none

201 Response

{
  "data": {
    "id": 0,
    "name": "string",
    "slug": "string",
    "description": "string",
    "kind": "agent",
    "visibility": "public_profile",
    "wallet_address": "string",
    "category": "string",
    "verified": true,
    "claimed": true,
    "created_at": "2019-08-24T14:15:22Z",
    "stats": {
      "total_paid": 0,
      "total_received": 0,
      "payments_made": 0,
      "payments_received": 0,
      "unique_counterparties": 0,
      "first_seen": "2019-08-24T14:15:22Z",
      "last_active": "2019-08-24T14:15:22Z"
    },
    "claim_token": "string",
    "claim_url": "string"
  }
}

Responses

Status Meaning Description Schema
201 Created Ghost resource created ResourceEnrollmentResponse
422 Unprocessable Entity Validation error (missing/blank fields, or unknown kind) ErrorResponse
429 Too Many Requests Rate limit exceeded (10 enrollments/hour/IP) ErrorResponse

No authentication required

Documentation

This document, served for tooling that reads the spec directly.

Fetch this OpenAPI document

GET /docs/openapi.yaml

200 Response

Responses

Status Meaning Description Schema
200 OK OpenAPI 3.1 document (YAML) string

No authentication required

Schemas

AccountBootstrapRequest

{
  "email": "human@example.com",
  "agent_name": "Research agent",
  "host_name": "OpenCode",
  "reason": "Find weather data"
}

Properties

Name Type Required Restrictions Description
email string(email) true none none
agent_name string true none none
host_name string false none none
reason string false none none
oauthclientid string false none Transitional compatibility for older CLI releases that use OAuth device exchange.
requested_scopes [string] false none Transitional compatibility for older CLI releases that use OAuth device exchange.

AccountBootstrapCreated

{
  "id": "boot_01K3C9Y7Q4R6T8V2W5X0Z1A3B4",
  "status": "pending",
  "capabilities": [
    "search",
    "status",
    "cancel"
  ],
  "expires_at": "2026-08-22T14:30:00Z",
  "approval": {
    "method": "email_link",
    "expires_in": 1800,
    "interval": 5,
    "user_code": "W3FT-7K2M"
  },
  "temporary_api_key": "wbt_example_store_as_a_secret"
}

Properties

Name Type Required Restrictions Description
id string true none none
status string true none none
capabilities [string] true none none
expires_at string,null(date-time)¦null true none Claim-window expiry. Null after the credential is promoted.
approval AccountBootstrapCreatedApproval true none none
temporaryapikey string true none Returned once. Store as a secret; it cannot be recovered.
device_code string false none Transitional response field for older CLI releases that use OAuth device exchange.

Enumerated Values

Property Value
status pending
status claimed
status rejected
status expired
status consumed
status revoked

AccountBootstrapCreatedResponse

{
  "data": {
    "id": "boot_01K3C9Y7Q4R6T8V2W5X0Z1A3B4",
    "status": "pending",
    "capabilities": [
      "search",
      "status",
      "cancel"
    ],
    "expires_at": "2026-08-22T14:30:00Z",
    "approval": {
      "method": "email_link",
      "expires_in": 1800,
      "interval": 5,
      "user_code": "W3FT-7K2M"
    },
    "temporary_api_key": "wbt_example_store_as_a_secret"
  }
}

Properties

Name Type Required Restrictions Description
data AccountBootstrapCreated true none none

AccountBootstrapStatusResponse

{
  "data": {
    "id": "boot_01K3C9Y7Q4R6T8V2W5X0Z1A3B4",
    "status": "claimed",
    "capabilities": [
      "identity",
      "search",
      "balance",
      "fetch",
      "purchases",
      "status",
      "revoke"
    ],
    "expires_at": null,
    "approval": {
      "method": "email_link",
      "expires_in": 0,
      "interval": 5
    }
  }
}

Properties

Name Type Required Restrictions Description
data AccountBootstrapStatus true none none

AccountBootstrapStatus

{
  "id": "boot_01K3C9Y7Q4R6T8V2W5X0Z1A3B4",
  "status": "claimed",
  "capabilities": [
    "identity",
    "search",
    "balance",
    "fetch",
    "purchases",
    "status",
    "revoke"
  ],
  "expires_at": null,
  "approval": {
    "method": "email_link",
    "expires_in": 0,
    "interval": 5
  }
}

Properties

Name Type Required Restrictions Description
id string true none none
status string true none none
capabilities [string] true none none
expires_at string,null(date-time)¦null true none Claim-window expiry. Null after the credential is promoted.
approval AccountBootstrapApproval true none none

Enumerated Values

Property Value
status pending
status claimed
status rejected
status expired
status consumed
status revoked

AccountBootstrapApproval

{
  "method": "email_link",
  "expires_in": 0,
  "interval": 1
}

Properties

Name Type Required Restrictions Description
method string true none none
expires_in integer true none none
interval integer true none Minimum status polling interval in seconds.

Enumerated Values

Property Value
method email_link

AccountBootstrapCreatedApproval

{
  "method": "email_link",
  "expires_in": 0,
  "interval": 1,
  "user_code": "string"
}

Properties

Name Type Required Restrictions Description
method string true none none
expires_in integer true none none
interval integer true none Minimum status polling interval in seconds.
user_code string true none Show this code to the human; approval requires a matching normalized code.

Enumerated Values

Property Value
method email_link

RateLimitResponse

{
  "error": "too_many_requests",
  "error_description": "string"
}

Properties

Name Type Required Restrictions Description
error string true none none
error_description string true none none

Enumerated Values

Property Value
error toomanyrequests

ErrorResponse

{
  "error": {
    "code": "unauthorized",
    "message": "Invalid or expired API key",
    "request_id": "req_01HX9F3K7B2N4P8Q1R6T8Y2Z5"
  }
}

Standard error envelope returned by all /api/v1 endpoints except /search and /fetch (which use bespoke envelopes carrying additional context). error.code is stable across releases and safe to branch on; error.message is human-readable and may change.

Properties

Name Type Required Restrictions Description
error Error true none A single error inside an ErrorResponse envelope. code is the
stable machine-readable identifier (snakecase), message is
human-readable, details carries optional structured context
(e.g. validation field breakdown), and `request
id` correlates
with server logs for debugging.

Error

{
  "code": "validation_failed",
  "message": "Email has already been taken",
  "details": {},
  "request_id": "req_01HX9F3K7B2N4P8Q1R6T8Y2Z5"
}

A single error inside an ErrorResponse envelope. code is the stable machine-readable identifier (snakecase), message is human-readable, details carries optional structured context (e.g. validation field breakdown), and `requestid` correlates with server logs for debugging.

Properties

Name Type Required Restrictions Description
code string true none Stable machine-readable error code (snake_case).
message string true none Human-readable error description.
details object¦null false none Optional structured context about the failure.
request_id string false none Correlates with server logs; include when reporting bugs.

InsufficientScopeResponse

{
  "error": "insufficient_scope",
  "error_description": "The access token does not include the required scope.",
  "scope": "balance"
}

RFC 6750 §3.1 insufficient_scope error. Returned with HTTP 403 and a WWW-Authenticate: Bearer error="insufficient_scope", scope="..." header when an OAuth access token authenticates successfully but does not carry the scope the endpoint requires. Only OAuth bearer tokens are scope-gated; wk_-prefixed API keys are unscoped and never see this response.

Properties

Name Type Required Restrictions Description
error string true none none
error_description string true none none
scope string true none Space-delimited list of scopes the endpoint requires.

Enumerated Values

Property Value
error insufficient_scope

MessageResponse

{
  "data": {
    "message": "string"
  }
}

Properties

Name Type Required Restrictions Description
data object true none none
» message string true none none

ResourceEnrollmentRequest

{
  "kind": "agent",
  "name": "Self-Enrolled Bot",
  "description": "string",
  "wallet_address": "string"
}

slug and category are accepted but silently ignored — the server generates the slug from name, and category is a post-claim concern.

Properties

Name Type Required Restrictions Description
kind string true none Resource kind. Must be one of the supported kinds (currently
agent); an unknown value is rejected with a 422.
name string true none Human-readable name; the server derives the slug from it.
description string false none none
wallet_address string false none Declared EVM wallet address for the ghost resource. Stored as a
claim (unverified) until the resource is claimed.

ResourceEnrollmentResponse

{
  "data": {
    "id": 0,
    "name": "string",
    "slug": "string",
    "description": "string",
    "kind": "agent",
    "visibility": "public_profile",
    "wallet_address": "string",
    "category": "string",
    "verified": true,
    "claimed": true,
    "created_at": "2019-08-24T14:15:22Z",
    "stats": {
      "total_paid": 0,
      "total_received": 0,
      "payments_made": 0,
      "payments_received": 0,
      "unique_counterparties": 0,
      "first_seen": "2019-08-24T14:15:22Z",
      "last_active": "2019-08-24T14:15:22Z"
    },
    "claim_token": "string",
    "claim_url": "string"
  }
}

Properties

Name Type Required Restrictions Description
data EnrolledResource true none The :created view of a ghost resource. Adds stats, the single-use
claim_token, and the claim_url to the base resource shape. The
claim fields appear ONLY on this enrollment response — never in list
or read views.

EnrolledResource

{
  "id": 0,
  "name": "string",
  "slug": "string",
  "description": "string",
  "kind": "agent",
  "visibility": "public_profile",
  "wallet_address": "string",
  "category": "string",
  "verified": true,
  "claimed": true,
  "created_at": "2019-08-24T14:15:22Z",
  "stats": {
    "total_paid": 0,
    "total_received": 0,
    "payments_made": 0,
    "payments_received": 0,
    "unique_counterparties": 0,
    "first_seen": "2019-08-24T14:15:22Z",
    "last_active": "2019-08-24T14:15:22Z"
  },
  "claim_token": "string",
  "claim_url": "string"
}

The :created view of a ghost resource. Adds stats, the single-use claim_token, and the claim_url to the base resource shape. The claim fields appear ONLY on this enrollment response — never in list or read views.

Properties

Name Type Required Restrictions Description
id integer true none none
name string true none none
slug string true none none
description string¦null false none none
kind string true none none
visibility string true none none
wallet_address string¦null false none Declared wallet address, or null if none was provided.
category string¦null true none Legacy v3 taxonomy field. Returns a string only for agent-kind
resources that carry a category in their metadata; null for
all other kinds and for agents without one. Always null on
enrollment (category is a post-claim concern).
verified boolean true none none
claimed boolean true none True once the resource has an owning provider. Always false at enrollment.
created_at string(date-time) true none none
stats ResourceStats true none Aggregate public payment stats for the resource.
claim_token string true none Single-use token for the magic claim URL. Surfaced only on enrollment.
claim_url string¦null true none Dashboard path the agent hands to its human to claim the resource.

ResourceStats

{
  "total_paid": 0,
  "total_received": 0,
  "payments_made": 0,
  "payments_received": 0,
  "unique_counterparties": 0,
  "first_seen": "2019-08-24T14:15:22Z",
  "last_active": "2019-08-24T14:15:22Z"
}

Aggregate public payment stats for the resource.

Properties

Name Type Required Restrictions Description
total_paid integer true none Total atomic units paid out by this resource.
total_received integer true none Total atomic units received by this resource.
payments_made integer true none none
payments_received integer true none none
unique_counterparties integer true none none
first_seen string(date-time)¦null true none none
last_active string(date-time)¦null true none none

Pagination

{
  "page": 0,
  "per_page": 0,
  "total": 0,
  "total_pages": 0
}

Properties

Name Type Required Restrictions Description
page integer true none none
per_page integer true none none
total integer true none none
total_pages integer true none none

SignUpRequest

{
  "email": "user@example.com",
  "password": "string",
  "password_confirmation": "string"
}

Properties

Name Type Required Restrictions Description
email string(email) true none none
password string true none none
password_confirmation string true none none

SignInRequest

{
  "email": "user@example.com",
  "password": "string"
}

Properties

Name Type Required Restrictions Description
email string(email) true none none
password string true none none

ConfirmRequest

{
  "confirmation_token": "string"
}

Properties

Name Type Required Restrictions Description
confirmation_token string true none none

ResendConfirmationRequest

{
  "email": "user@example.com"
}

Properties

Name Type Required Restrictions Description
email string(email) true none none

PasswordResetRequest

{
  "email": "user@example.com"
}

Properties

Name Type Required Restrictions Description
email string(email) true none none

PasswordUpdateRequest

{
  "reset_password_token": "string",
  "password": "string",
  "password_confirmation": "string"
}

Properties

Name Type Required Restrictions Description
resetpasswordtoken string true none none
password string true none none
password_confirmation string true none none

AuthResponse

{
  "data": {
    "user": {
      "id": 0,
      "email": "user@example.com",
      "status": "string"
    },
    "token": "string",
    "confirmation_required": true
  }
}

Properties

Name Type Required Restrictions Description
data object true none none
» user User true none none
» token string¦null false none none
» confirmation_required boolean true none none

User

{
  "id": 0,
  "email": "user@example.com",
  "status": "string"
}

Properties

Name Type Required Restrictions Description
id integer true none none
email string(email) true none none
status string false none none

MeResponse

{
  "data": {
    "principal_type": "organization",
    "id": 0,
    "name": "string",
    "slug": "string",
    "kind": "string",
    "api_key": {
      "id": 0,
      "name": "string",
      "created_at": "2019-08-24T14:15:22Z",
      "last_used_at": "2019-08-24T14:15:22Z",
      "created_by": {
        "id": 0,
        "email": "user@example.com",
        "display_name": "string"
      }
    }
  }
}

Properties

Name Type Required Restrictions Description
data any true none none

oneOf

Name Type Required Restrictions Description
» anonymous AccountDetails false none The Organization that owns the authenticated API key — the principal
in API v1 (the key represents an Org, not a person). api_key carries
audit info about the key itself, including the user who minted it
(created_by, which may be null if that user has left the Org).

xor

Name Type Required Restrictions Description
» anonymous UserPrincipal false none The buyer User represented by an account API key or OAuth token.

AccountDetails

{
  "principal_type": "organization",
  "id": 0,
  "name": "string",
  "slug": "string",
  "kind": "string",
  "api_key": {
    "id": 0,
    "name": "string",
    "created_at": "2019-08-24T14:15:22Z",
    "last_used_at": "2019-08-24T14:15:22Z",
    "created_by": {
      "id": 0,
      "email": "user@example.com",
      "display_name": "string"
    }
  }
}

The Organization that owns the authenticated API key — the principal in API v1 (the key represents an Org, not a person). api_key carries audit info about the key itself, including the user who minted it (created_by, which may be null if that user has left the Org).

Properties

Name Type Required Restrictions Description
principal_type string true none none
id integer true none none
name string true none none
slug string true none none
kind string true none none
api_key MeApiKey true none none

UserPrincipal

{
  "principal_type": "user",
  "id": 0,
  "email": "user@example.com",
  "display_name": "string",
  "status": "active",
  "buyer_enabled": true,
  "seller_enabled": true,
  "provisioning_status": "pending",
  "wallet": {
    "address": "string",
    "network": "string"
  }
}

The buyer User represented by an account API key or OAuth token.

Properties

Name Type Required Restrictions Description
principal_type string true none none
id integer true none none
email string(email) true none none
display_name string¦null false none none
status string true none none
buyer_enabled boolean true none none
seller_enabled boolean true none none
provisioning_status string true none none
wallet any true none none

anyOf

Name Type Required Restrictions Description
» anonymous PrincipalWallet false none none

or

Name Type Required Restrictions Description
» anonymous null false none none

Enumerated Values

Property Value
status active
status blocked
provisioning_status pending
provisioning_status ready
provisioning_status not_applicable

PrincipalWallet

{
  "address": "string",
  "network": "string"
}

Properties

Name Type Required Restrictions Description
address string true none none
network string true none none

MeApiKey

{
  "id": 0,
  "name": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "last_used_at": "2019-08-24T14:15:22Z",
  "created_by": {
    "id": 0,
    "email": "user@example.com",
    "display_name": "string"
  }
}

Properties

Name Type Required Restrictions Description
id integer true none none
name string¦null false none none
created_at string(date-time) true none none
lastusedat string(date-time)¦null false none none
created_by MeApiKeyCreator false none The user who minted this API key, surfaced for audit rendering only.
null if that user has since left the Organization. NEVER use for
authorization.

MeApiKeyCreator

{
  "id": 0,
  "email": "user@example.com",
  "display_name": "string"
}

The user who minted this API key, surfaced for audit rendering only. null if that user has since left the Organization. NEVER use for authorization.

Properties

Name Type Required Restrictions Description
id integer true none none
email string(email) true none none
display_name string¦null false none none

CreateApiKeyRequest

{
  "name": "string"
}

Properties

Name Type Required Restrictions Description
name string false none A friendly name for the API key

ApiKey

{
  "id": 0,
  "name": "string",
  "key_prefix": "string",
  "last_used_at": "2019-08-24T14:15:22Z",
  "revoked_at": "2019-08-24T14:15:22Z",
  "created_at": "2019-08-24T14:15:22Z"
}

Properties

Name Type Required Restrictions Description
id integer true none none
name string¦null false none none
key_prefix string true none First 16 characters of the key for identification
lastusedat string(date-time)¦null false none none
revoked_at string(date-time)¦null false none none
created_at string(date-time) true none none

ApiKeyCreated

{
  "id": 0,
  "name": "string",
  "key_prefix": "string",
  "raw_key": "string",
  "created_at": "2019-08-24T14:15:22Z"
}

Properties

Name Type Required Restrictions Description
id integer true none none
name string¦null false none none
key_prefix string true none none
raw_key string true none Full API key (shown only once at creation)
created_at string(date-time) true none none

ApiKeyListResponse

{
  "data": [
    {
      "id": 0,
      "name": "string",
      "key_prefix": "string",
      "last_used_at": "2019-08-24T14:15:22Z",
      "revoked_at": "2019-08-24T14:15:22Z",
      "created_at": "2019-08-24T14:15:22Z"
    }
  ],
  "pagination": {
    "page": 0,
    "per_page": 0,
    "total": 0,
    "total_pages": 0
  }
}

Properties

Name Type Required Restrictions Description
data [ApiKey] true none none
pagination Pagination true none none

ApiKeyCreatedResponse

{
  "data": {
    "id": 0,
    "name": "string",
    "key_prefix": "string",
    "raw_key": "string",
    "created_at": "2019-08-24T14:15:22Z"
  }
}

Properties

Name Type Required Restrictions Description
data ApiKeyCreated true none none

Payment

{
  "id": 0,
  "tx_hash": "string",
  "payer_address": "string",
  "recipient_address": "string",
  "amount": 0,
  "amount_formatted": "string",
  "currency": "string",
  "network": "string",
  "resource_url": "string",
  "resource_host": "string",
  "settlement_latency_ms": 0,
  "settled_at": "2019-08-24T14:15:22Z",
  "api_key_name": "string"
}

Properties

Name Type Required Restrictions Description
id integer true none none
tx_hash string true none none
payer_address string true none none
recipient_address string true none none
amount integer true none Amount in atomic units (1 USDC = 1,000,000)
amount_formatted string true none Human-readable amount (e.g. "1.00 USDC")
currency string true none none
network string true none CAIP-2 chain identifier
resource_url string¦null false none none
resource_host string¦null false none none
settlementlatencyms integer¦null false none none
settled_at string(date-time) true none none
apikeyname string true none none

PaymentListResponse

{
  "data": [
    {
      "id": 0,
      "tx_hash": "string",
      "payer_address": "string",
      "recipient_address": "string",
      "amount": 0,
      "amount_formatted": "string",
      "currency": "string",
      "network": "string",
      "resource_url": "string",
      "resource_host": "string",
      "settlement_latency_ms": 0,
      "settled_at": "2019-08-24T14:15:22Z",
      "api_key_name": "string"
    }
  ],
  "pagination": {
    "page": 0,
    "per_page": 0,
    "total": 0,
    "total_pages": 0
  }
}

Properties

Name Type Required Restrictions Description
data [Payment] true none none
pagination Pagination true none none

PaymentResponse

{
  "data": {
    "id": 0,
    "tx_hash": "string",
    "payer_address": "string",
    "recipient_address": "string",
    "amount": 0,
    "amount_formatted": "string",
    "currency": "string",
    "network": "string",
    "resource_url": "string",
    "resource_host": "string",
    "settlement_latency_ms": 0,
    "settled_at": "2019-08-24T14:15:22Z",
    "api_key_name": "string"
  }
}

Properties

Name Type Required Restrictions Description
data Payment true none none

Purchase

{
  "id": 0,
  "purchase_id": "pur_4V3n9mQ0b7XyK2sLpR8tWc1d",
  "status": "signed",
  "amount_usd": "string",
  "recipient_address": "string",
  "network": "string",
  "protocol": "mpp",
  "context": "string",
  "search_id": "string",
  "attribution_status": "attributed",
  "tx_hash": "string",
  "reject_reason": "string",
  "failure_reason": "string",
  "idempotency_key": "string",
  "signed_at": "2019-08-24T14:15:22Z",
  "settled_at": "2019-08-24T14:15:22Z",
  "artifact": {
    "id": 0,
    "merchant_url": "http://example.com",
    "bytes": 0,
    "mime": "string"
  }
}

Properties

Name Type Required Restrictions Description
id integer true none none
purchase_id string false none Opaque purchase id: the value fetch returns as purchase_id and
that GET /api/v1/purchases/{id} accepts. Prefer it over the
sequential id. Current servers always send this field; it is
optional in this schema so that a client also accepts a response
from an older server.
status string true none none
amount_usd string true none Exact decimal USD amount with up to six fractional digits. Settled rows report the amount that moved; pending and failed rows report their authorization amount.
recipient_address string true none none
network string true none none
protocol string,null¦null true none none
context string,null¦null true none none
search_id string,null¦null true none Search trace ID used to attribute this purchase, when available.
attribution_status string true none none
tx_hash string,null¦null true none none
reject_reason string,null¦null true none none
failure_reason string,null¦null true none none
idempotency_key string,null¦null true none none
signed_at string(date-time) true none none
settled_at string,null(date-time)¦null true none none
artifact any true none none

anyOf

Name Type Required Restrictions Description
» anonymous PurchaseArtifact false none none

or

Name Type Required Restrictions Description
» anonymous null false none none

Enumerated Values

Property Value
status signed
status settled
status locked
status rejected
status declined
status expired
status reverted
protocol mpp
protocol x402
protocol null
attribution_status attributed
attribution_status unattributed

PurchaseArtifact

{
  "id": 0,
  "merchant_url": "http://example.com",
  "bytes": 0,
  "mime": "string"
}

Properties

Name Type Required Restrictions Description
id integer true none none
merchant_url string(uri) true none none
bytes integer true none none
mime string,null¦null true none none

PurchaseListResponse

{
  "data": [
    {
      "id": 0,
      "purchase_id": "pur_4V3n9mQ0b7XyK2sLpR8tWc1d",
      "status": "signed",
      "amount_usd": "string",
      "recipient_address": "string",
      "network": "string",
      "protocol": "mpp",
      "context": "string",
      "search_id": "string",
      "attribution_status": "attributed",
      "tx_hash": "string",
      "reject_reason": "string",
      "failure_reason": "string",
      "idempotency_key": "string",
      "signed_at": "2019-08-24T14:15:22Z",
      "settled_at": "2019-08-24T14:15:22Z",
      "artifact": {
        "id": 0,
        "merchant_url": "http://example.com",
        "bytes": 0,
        "mime": "string"
      }
    }
  ],
  "pagination": {
    "page": 0,
    "per_page": 0,
    "total": 0,
    "total_pages": 0
  }
}

Properties

Name Type Required Restrictions Description
data [Purchase] true none none
pagination Pagination true none none

PurchaseResponse

{
  "data": {
    "id": 0,
    "purchase_id": "pur_4V3n9mQ0b7XyK2sLpR8tWc1d",
    "status": "signed",
    "amount_usd": "string",
    "recipient_address": "string",
    "network": "string",
    "protocol": "mpp",
    "context": "string",
    "search_id": "string",
    "attribution_status": "attributed",
    "tx_hash": "string",
    "reject_reason": "string",
    "failure_reason": "string",
    "idempotency_key": "string",
    "signed_at": "2019-08-24T14:15:22Z",
    "settled_at": "2019-08-24T14:15:22Z",
    "artifact": {
      "id": 0,
      "merchant_url": "http://example.com",
      "bytes": 0,
      "mime": "string"
    }
  }
}

Properties

Name Type Required Restrictions Description
data Purchase true none none

BalanceResponse

{
  "promo": {
    "balance_usd": "0.00",
    "scope": "weft-search",
    "expires_at": "2019-08-24T14:15:22Z"
  },
  "wallet": {
    "provider": "crossmint",
    "address": "string",
    "balance_usdc": "12.34",
    "balance_tempo_usd": "2.03",
    "total_usd": "12.34",
    "network": "string"
  },
  "spent_today_usd": "0.0005",
  "spent_week_usd": "3.10",
  "policy_used_today_usd": "0.30",
  "policy_used_week_usd": "3.30",
  "policy": {
    "max_tx_usd": "1.00",
    "daily_limit_usd": "10.00",
    "weekly_limit_usd": "50.00"
  }
}

Buyer's wallet snapshot. Note: unlike /me / /payments / /api_keys, this endpoint does NOT use a data: envelope — the response object is the snapshot directly.

Properties

Name Type Required Restrictions Description
promo PromoBalance true none Freemium promo credit. v1 returns zero values; once the promo
ledger ships (deferred from spec 10), real balances appear here
without a shape change.
wallet Wallet true none none
spenttodayusd string true none USD spent in the current calendar day (UTC). Exact to the micro-dollar so sub-cent micro-payments survive ("0.0005", "0.42"), never narrower than two decimals; a zero total renders as "0.00".
spentweekusd string true none USD spent in the current calendar week (UTC, Monday start). Exact to the micro-dollar ("0.0005", "3.10"), never narrower than two decimals; a zero total renders as "0.00".
policyusedtoday_usd string true none USD currently counted against the daily spending limit: pending authorizations at their maximum plus settled payments at the amount that moved. Exact to the micro-dollar; zero renders as "0.00".
policyusedweek_usd string true none USD currently counted against the weekly spending limit: pending authorizations at their maximum plus settled payments at the amount that moved. Exact to the micro-dollar; zero renders as "0.00".
policy SpendingPolicy true none none

PromoBalance

{
  "balance_usd": "0.00",
  "scope": "weft-search",
  "expires_at": "2019-08-24T14:15:22Z"
}

Freemium promo credit. v1 returns zero values; once the promo ledger ships (deferred from spec 10), real balances appear here without a shape change.

Properties

Name Type Required Restrictions Description
balance_usd string true none none
scope string true none Where the promo can be spent.
expires_at string(date-time)¦null true none none

Wallet

{
  "provider": "crossmint",
  "address": "string",
  "balance_usdc": "12.34",
  "balance_tempo_usd": "2.03",
  "total_usd": "12.34",
  "network": "string"
}

Properties

Name Type Required Restrictions Description
provider string true none Crossmint is the only buyer-wallet provider.
address string¦null true none Base smart-wallet address. Null only when Crossmint is unavailable.
balance_usdc string¦null true none Live Base USDC balance, exact to the micro-dollar (up to 6 decimals, minimum 2). Null when Crossmint is unreachable; consumers must not interpret null as zero.
balancetempousd string¦null true none Live aggregate Tempo dollar-token balance, exact to the micro-dollar (up to 6 decimals, minimum 2). Null when Crossmint is unreachable; consumers must not interpret null as zero.
total_usd string¦null true none Single aggregated USD balance across Base USDC and Tempo dollar tokens, exact to the micro-dollar. Null when either pocket is unreachable, because the surface never claims zero for a component it could not read.
network string¦null true none Selected Crossmint environment (base_sepolia or base_mainnet).

Enumerated Values

Property Value
provider crossmint

SpendingPolicy

{
  "max_tx_usd": "1.00",
  "daily_limit_usd": "10.00",
  "weekly_limit_usd": "50.00"
}

Properties

Name Type Required Restrictions Description
maxtxusd string true none Maximum USD per single transaction.
dailylimitusd string true none Maximum USD spent in a 24-hour window.
weeklylimitusd string true none Maximum USD spent in a 7-day window.

SearchRequest

{
  "query": "send email from an agent",
  "max_results": 10,
  "filters": {
    "price": {
      "lte": "string",
      "gte": "string",
      "eq": "string",
      "range_gte": "string",
      "range_lte": "string"
    },
    "price_atomic": {
      "lte": 0,
      "gte": 0,
      "eq": 0,
      "range_gte": 0,
      "range_lte": 0
    },
    "type": {
      "eq": "api",
      "in": [
        "api"
      ]
    },
    "protocol": {
      "eq": "x402",
      "in": [
        "x402"
      ]
    },
    "category": {
      "eq": "string",
      "in": [
        "string"
      ]
    },
    "method": {
      "eq": "GET",
      "in": [
        "GET"
      ]
    },
    "execution_mode": {
      "eq": "sync",
      "in": [
        "sync"
      ]
    },
    "weft_fetch_compatible": true,
    "include_unknown_prices": false
  },
  "view": "full"
}

Properties

Name Type Required Restrictions Description
query string true none Free-text query. Required and non-empty.
max_results integer false none Max number of hits to return. Invalid values are rejected, not clamped.
filters SearchFilterSpec false none Structured hard constraints on the query — the weft-search-platform
FilterSpec v1 typed subset, vendored verbatim (D1 contract). Every
field is optional; an empty object is the no-filter query. Set fields
are ANDed. Each sub-filter takes exactly one operator; unknown filter
keys and unknown operators are rejected (422 INVALID_FILTERS).

price (USD decimal strings) and price_atomic (integer micro-USD) are
two representations of ONE price constraint — the reasoning form and the
settlement form. They are MUTUALLY EXCLUSIVE: setting both is
422 INVALID_FILTERS. A JSON number in price is rejected (only decimal
strings), so {lte: 5} can never be mis-read as 5 micro-dollars.

The canonical enum value sets are pinned to the platform spec by the CI
drift gate (docs/contracts/search-platform.openapi.yaml).
view string false none Response view. Absent means full: the complete SearchResult
rows in results. compact returns the hosted MCP agent view in
compact_results (see SearchCompactResult). The compact view
applies the same selection as hosted MCP search: it leaves out
incomplete PayWithLocus gateway contracts. It does not add filters;
send weft_fetch_compatible: true to get only results that
POST /api/v1/fetch can pay.

Enumerated Values

Property Value
view full
view compact

SearchFilterSpec

{
  "price": {
    "lte": "string",
    "gte": "string",
    "eq": "string",
    "range_gte": "string",
    "range_lte": "string"
  },
  "price_atomic": {
    "lte": 0,
    "gte": 0,
    "eq": 0,
    "range_gte": 0,
    "range_lte": 0
  },
  "type": {
    "eq": "api",
    "in": [
      "api"
    ]
  },
  "protocol": {
    "eq": "x402",
    "in": [
      "x402"
    ]
  },
  "category": {
    "eq": "string",
    "in": [
      "string"
    ]
  },
  "method": {
    "eq": "GET",
    "in": [
      "GET"
    ]
  },
  "execution_mode": {
    "eq": "sync",
    "in": [
      "sync"
    ]
  },
  "weft_fetch_compatible": true,
  "include_unknown_prices": false
}

Structured hard constraints on the query — the weft-search-platform FilterSpec v1 typed subset, vendored verbatim (D1 contract). Every field is optional; an empty object is the no-filter query. Set fields are ANDed. Each sub-filter takes exactly one operator; unknown filter keys and unknown operators are rejected (422 INVALID_FILTERS).

price (USD decimal strings) and price_atomic (integer micro-USD) are two representations of ONE price constraint — the reasoning form and the settlement form. They are MUTUALLY EXCLUSIVE: setting both is 422 INVALID_FILTERS. A JSON number in price is rejected (only decimal strings), so {lte: 5} can never be mis-read as 5 micro-dollars.

The canonical enum value sets are pinned to the platform spec by the CI drift gate (docs/contracts/search-platform.openapi.yaml).

Properties

Name Type Required Restrictions Description
price SearchPriceUsdFilter false none Price constraint in USD, as decimal STRINGS (the reasoning form). Set
exactly one operator: a scalar (lte / gte / eq) OR a range
(range_gte + range_lte together, lower ≤ upper). Each value is a
string matching ^\d+(\.\d{1,6})?$ (≤ 6 decimals, ≥ 0); a JSON number is
rejected. Mutually exclusive with price_atomic. An unpriced resource is
excluded from any price-filtered query.
price_atomic SearchPriceAtomicFilter false none The same price constraint in integer micro-USD (1 USDC = 1000000
micro-USD) — the settlement form. Set exactly one operator: a scalar
(lte / gte / eq) OR a range (range_gte + range_lte together,
lower ≤ upper). Mutually exclusive with price. An unpriced resource is
excluded from any price-filtered query.
type SearchResourceTypeFilter false none Resource-type constraint. Set exactly one of eq / in.
protocol SearchProtocolFilter false none Payment-protocol constraint. Set exactly one of eq / in.
category SearchStringSetFilter false none none
method SearchMethodFilter false none none
execution_mode SearchExecutionModeFilter false none none
weftfetchcompatible boolean false none True requires at least one access method whose paid request is supported by the current Weft fetch runtime. For async operations this can mean submission-only coverage followed by the provider workflow.
includeunknownprices boolean false none With a price constraint, also retain dynamic and unknown prices.

SearchPriceUsdFilter

{
  "lte": "string",
  "gte": "string",
  "eq": "string",
  "range_gte": "string",
  "range_lte": "string"
}

Price constraint in USD, as decimal STRINGS (the reasoning form). Set exactly one operator: a scalar (lte / gte / eq) OR a range (range_gte + range_lte together, lower ≤ upper). Each value is a string matching ^\d+(\.\d{1,6})?$ (≤ 6 decimals, ≥ 0); a JSON number is rejected. Mutually exclusive with price_atomic. An unpriced resource is excluded from any price-filtered query.

Properties

Name Type Required Restrictions Description
lte string false none Price ≤ this many USD (inclusive ceiling), e.g. "0.009".
gte string false none Price ≥ this many USD (inclusive floor), e.g. "0.001".
eq string false none Price exactly this many USD, e.g. "1.5".
range_gte string false none Range lower bound (inclusive), USD. Set with range_lte.
range_lte string false none Range upper bound (inclusive), USD. Set with range_gte.

SearchPriceAtomicFilter

{
  "lte": 0,
  "gte": 0,
  "eq": 0,
  "range_gte": 0,
  "range_lte": 0
}

The same price constraint in integer micro-USD (1 USDC = 1000000 micro-USD) — the settlement form. Set exactly one operator: a scalar (lte / gte / eq) OR a range (range_gte + range_lte together, lower ≤ upper). Mutually exclusive with price. An unpriced resource is excluded from any price-filtered query.

Properties

Name Type Required Restrictions Description
lte integer false none Price ≤ this many micro-USD (inclusive ceiling).
gte integer false none Price ≥ this many micro-USD (inclusive floor).
eq integer false none Price exactly this many micro-USD.
range_gte integer false none Range lower bound (inclusive), micro-USD. Set with range_lte.
range_lte integer false none Range upper bound (inclusive), micro-USD. Set with range_gte.

SearchResourceTypeFilter

{
  "eq": "api",
  "in": [
    "api"
  ]
}

Resource-type constraint. Set exactly one of eq / in.

Properties

Name Type Required Restrictions Description
eq string false none Resource type is exactly this value.
in [string] false none Resource type is one of these values.

Enumerated Values

Property Value
eq api
eq agent
eq mcp_tool
eq webpage
eq feed
eq document
eq dataset

SearchProtocolFilter

{
  "eq": "x402",
  "in": [
    "x402"
  ]
}

Payment-protocol constraint. Set exactly one of eq / in.

Properties

Name Type Required Restrictions Description
eq string false none Primary protocol is exactly this value.
in [string] false none Primary protocol is one of these values.

Enumerated Values

Property Value
eq x402
eq a2a
eq mpp
eq erc_8004

SearchStringSetFilter

{
  "eq": "string",
  "in": [
    "string"
  ]
}

Properties

Name Type Required Restrictions Description
eq string false none none
in [string] false none none

SearchMethodFilter

{
  "eq": "GET",
  "in": [
    "GET"
  ]
}

Properties

Name Type Required Restrictions Description
eq string false none none
in [string] false none none

Enumerated Values

Property Value
eq GET
eq POST
eq PUT
eq PATCH
eq DELETE
eq HEAD
eq OPTIONS

SearchExecutionModeFilter

{
  "eq": "sync",
  "in": [
    "sync"
  ]
}

Properties

Name Type Required Restrictions Description
eq string false none none
in [string] false none none

Enumerated Values

Property Value
eq sync
eq async
eq stream

SearchResponse

{
  "query_trace_id": "2e536172-f35a-49b0-b5b1-ca3970d0f446",
  "query": "string",
  "format": "json",
  "markdown": "string",
  "result_count": 0,
  "served_from": "live",
  "as_of": "2019-08-24T14:15:22Z",
  "stale": true,
  "payment_note": "string",
  "applied_filters": {
    "price": {
      "lte": "string",
      "gte": "string",
      "eq": "string",
      "range_gte": "string",
      "range_lte": "string"
    },
    "price_atomic": {
      "lte": 0,
      "gte": 0,
      "eq": 0,
      "range_gte": 0,
      "range_lte": 0
    },
    "type": {
      "eq": "api",
      "in": [
        "api"
      ]
    },
    "protocol": {
      "eq": "x402",
      "in": [
        "x402"
      ]
    },
    "category": {
      "eq": "string",
      "in": [
        "string"
      ]
    },
    "method": {
      "eq": "GET",
      "in": [
        "GET"
      ]
    },
    "execution_mode": {
      "eq": "sync",
      "in": [
        "sync"
      ]
    },
    "weft_fetch_compatible": true,
    "include_unknown_prices": false
  },
  "decomposition_source": "CALLER",
  "embedder_model": "string",
  "candidates_considered": 0,
  "warnings": [
    {
      "code": "string",
      "message": "string",
      "cause": "string",
      "context": {}
    }
  ],
  "match_quality": "strong",
  "reason": "below_relevance_floor",
  "suggestion": "string",
  "results": [
    {
      "provider": {
        "provider_id": "string",
        "display_name": "string",
        "origin_domains": [
          "string"
        ]
      },
      "capability": {
        "capability_id": "string",
        "capability_type": "string"
      },
      "endpoints": [
        {
          "endpoint_id": "string",
          "url": "string",
          "resource_type": "string",
          "primary_protocol": "string",
          "call": {
            "method": "string",
            "input_schema": {},
            "example_request": {},
            "example_response": null
          },
          "price": {
            "indexed_usd": "string",
            "atomic": 0,
            "source": "probe",
            "last_observed_at": "2019-08-24T14:15:22Z",
            "live_verified": true
          },
          "payment": [
            {
              "protocol": "string",
              "scheme": "string",
              "network": "string",
              "asset": "string",
              "amount": "string",
              "pay_to": "string",
              "max_timeout_seconds": 0,
              "facilitator": "string"
            }
          ],
          "access_methods": [
            {
              "access_method_id": "string",
              "protocol": "x402",
              "scheme": "string",
              "network": "string",
              "asset": "string",
              "asset_decimals": 0,
              "price": {},
              "merchant": {},
              "terms": {},
              "status": "listed",
              "weft_fetch": {
                "state": "supported",
                "reason": "string",
                "contract_version": 0,
                "coverage": "terminal_response"
              }
            }
          ],
          "service": {
            "id": "string",
            "name": "string"
          },
          "operation": {
            "id": "string",
            "name": "string",
            "description": "string"
          },
          "docs": {
            "website": "http://example.com",
            "homepage": "http://example.com",
            "api": "http://example.com",
            "llms_txt": "http://example.com"
          },
          "contract_url": "http://example.com",
          "output_schema": {},
          "output": {},
          "execution": {
            "mode": "sync"
          },
          "callability": {
            "state": "complete",
            "missing": [
              "string"
            ]
          },
          "compatibility": {},
          "source": {
            "catalog": "curated_marketplace",
            "snapshot_version": 0,
            "captured_at": "2019-08-24T14:15:22Z"
          },
          "operator_type": "first_party",
          "operated_by_id": "string",
          "settled_via_facilitator_id": "string",
          "settlements": 0,
          "last_verified_at": "2019-08-24T14:15:22Z",
          "latency_p50_ms": 0
        }
      ],
      "score": 0
    }
  ],
  "view": "full",
  "compact_results": [
    {
      "provider": {
        "id": "string",
        "name": "string"
      },
      "operation": {
        "id": "string",
        "name": "string",
        "description": "string"
      },
      "inputs": {},
      "request": {},
      "example": null,
      "access": {
        "id": "string",
        "protocol": "string",
        "weft_fetch": {},
        "price": {
          "kind": "string",
          "indexed_usd": "string",
          "unit": "string",
          "hint": "string"
        }
      },
      "attribution": {
        "search_id": "d5826b15-4ef0-45f4-80df-3b8d5f941dd6",
        "operation_id": "string",
        "access_method_id": "string"
      },
      "output": {},
      "docs": {
        "website": "http://example.com",
        "homepage": "http://example.com",
        "api": "http://example.com",
        "llms_txt": "http://example.com"
      },
      "contract_url": "http://example.com",
      "contract_detail": "string",
      "completion": "string",
      "blocked_scopes": [
        {
          "scope": "string",
          "state": "string"
        }
      ],
      "contract_gaps": [
        "string"
      ],
      "readiness": {
        "property1": {
          "state": "string",
          "scope": "string"
        },
        "property2": {
          "state": "string",
          "scope": "string"
        }
      },
      "next_call": {
        "method": "POST",
        "path": "/api/v1/fetch",
        "body": {},
        "fill": [
          "string"
        ]
      }
    }
  ],
  "omitted_results": 1
}

The weft-search-platform POST /v1/search response envelope.

Properties

Name Type Required Restrictions Description
querytraceid string(uuid) true none Opaque trace id for the served query, matching the platform
query_trace_id — and the search_id that re-reads it. Deliberately
the same id rather than a second handle: one serve, one name.
query string true none none
format string false none Which view this response carries, echoing the requested format.
json populates results and leaves markdown null; markdown
populates markdown and leaves results empty. Exactly one is
populated per response, never both — returning both eagerly would
double the payload.
markdown string¦null false none The flat comparison table, when format is markdown; null
otherwise. Rendered deterministically from the same stored result
the json view returns, so the two views of one search can never
disagree.
result_count integer false none How many (Provider + Capability) results the search produced. Read
THIS, not results.length, for the count: on a markdown response
results is empty by design, so result_count > 0 with an empty
results is a rendered table while result_count == 0 is a genuine
zero-result. On a compact view response it counts
compact_results; there, result_count == 0 with
omitted_results means every ranked result was too large to show.
served_from string false none live for a fresh serve; snapshot for an immutable replay of a
completed search. A re-read is a snapshot and says so — read it with
as_of and stale.
as_of string(date-time)¦null false none When the results were produced. Now on a live serve; on a
snapshot the ORIGINAL serve time, because a replay returns exactly
what was paid for, not current truth.
stale boolean false none Whether the active search index has changed since these results were
produced. true does not mean the results are wrong — it means they
are a snapshot of an index that has since moved. Always false on a
live serve.
payment_note string false none How payment works across the catalog, stated once for the whole
response rather than repeated in every endpoint's usage instructions.
applied_filters SearchFilterSpec false none The FilterSpec actually applied to recall, echoed back so the
caller sees exactly what constrained the results. In the current
contract this is the caller's filters verbatim (empty object when
none were sent).
decomposition_source string false none Origin of applied_filters; always CALLER.
embedder_model string true none none
candidates_considered integer true none none
warnings [object] true none none
» code string true none none
» message string true none none
» cause string¦null false none Typed cause for codes that carry one. Null otherwise.
» context object¦null false none Structured context for the warning. Null when the code carries none.
match_quality string false none Calibrated confidence in this result set — read this instead of
thresholding a raw similarity score. strong: the top match is
confidently on-intent, proceed. weak: above the relevance floor
but inside the band where plausible-but-wrong matches live, verify
the result before paying. none: nothing cleared the floor —
results is empty and reason / suggestion say why. Results
below the floor are never returned as near-misses.
reason string¦null false none Machine-readable cause of an empty result set, non-null exactly when
match_quality is none. below_relevance_floor: candidates ranked
but the best scored under the floor. filter_collapsed_pool: a caller
filter cut the pool before ranking and nothing relevant survived —
relax the filter. no_catalog_coverage: recall returned no candidates
at all on an unfiltered query. unsupported_filter_value: a
CATEGORICAL filter value (type / protocol) matches zero stored
values, so it could never have matched — categorical only, since a
continuous bound like price that matches nothing is reported as
filter_collapsed_pool instead (the bound needs raising, the
dimension is not unsupported). index_unavailable: no active index
— an operational fault, paired with the EMPTY_INDEX warning.
suggestion string¦null false none Human/agent-readable explanation of reason, carrying the concrete
numbers behind it (pool sizes, the best discarded score against the
floor, the values actually stored for a filter). Non-null exactly
when reason is.
results [SearchResult] true none Ranked (Provider + Capability) results; empty when the index is
empty or nothing cleared the relevance floor. Results BELOW the floor
are never returned — an empty list plus a reason is the honest
answer, not a list of near-misses in the same shape as a genuine
match. Empty on a compact view response; read compact_results.
view string false none The view this response carries. Present as compact when the
request asked for view: "compact"; absent means full.
compact_results [SearchCompactResult] false none Ranked compact results, present only on a compact view response.
result_count is their count. They are a separate field so that
typed clients keep the full SearchResult shape for results.
omitted_results integer false none Compact view only: how many ranked results were left out because
even their minimum summary does not fit the per-result budget.
Absent when none were left out.

Enumerated Values

Property Value
format json
format markdown
served_from live
served_from snapshot
decomposition_source CALLER
match_quality strong
match_quality weak
match_quality none
reason belowrelevancefloor
reason filtercollapsedpool
reason nocatalogcoverage
reason unsupportedfiltervalue
reason index_unavailable
view full
view compact

SearchCompactResult

{
  "provider": {
    "id": "string",
    "name": "string"
  },
  "operation": {
    "id": "string",
    "name": "string",
    "description": "string"
  },
  "inputs": {},
  "request": {},
  "example": null,
  "access": {
    "id": "string",
    "protocol": "string",
    "weft_fetch": {},
    "price": {
      "kind": "string",
      "indexed_usd": "string",
      "unit": "string",
      "hint": "string"
    }
  },
  "attribution": {
    "search_id": "d5826b15-4ef0-45f4-80df-3b8d5f941dd6",
    "operation_id": "string",
    "access_method_id": "string"
  },
  "output": {},
  "docs": {
    "website": "http://example.com",
    "homepage": "http://example.com",
    "api": "http://example.com",
    "llms_txt": "http://example.com"
  },
  "contract_url": "http://example.com",
  "contract_detail": "string",
  "completion": "string",
  "blocked_scopes": [
    {
      "scope": "string",
      "state": "string"
    }
  ],
  "contract_gaps": [
    "string"
  ],
  "readiness": {
    "property1": {
      "state": "string",
      "scope": "string"
    },
    "property2": {
      "state": "string",
      "scope": "string"
    }
  },
  "next_call": {
    "method": "POST",
    "path": "/api/v1/fetch",
    "body": {},
    "fill": [
      "string"
    ]
  }
}

One row of the compact agent view: the minimum contract for the next paid call, below 2,000 JSON bytes. It is the hosted MCP weft_search projection with REST references: contract_url replaces the MCP weft_contract call, and next_call is a POST /api/v1/fetch request instead of an MCP weft_fetch call. To stay in the budget, the row drops optional fields in a fixed order (optional inputs, helper docs, the example, the description, then summaries) and contract_detail says what is left out. In the last resort the row keeps the operation id, readiness states, the weft_fetch state, contract_url and the search id, and can lose the input names, the request recipe and price. The full contract at contract_url is always complete. The search id is the envelope query_trace_id; each row also carries it in attribution or in next_call.body.

Properties

Name Type Required Restrictions Description
provider object false none none
» id string false none none
» name string false none none
operation object true none none
» id string true none Catalog operation id. Send it as operation_id to POST /api/v1/fetch.
» name string false none none
» description string false none none
inputs object false none Typed business inputs (a bounded JSON schema), or the names and
locations of the required inputs when the full schema does not
fit. Read the full contract before you send an input not listed.
request object false none The request recipe: method, canonical url, and, when known,
the path, query, header and JSON body bindings of each input.
example any false none A bounded documented request example, when the catalog has one.
access SearchCompactAccess true none The recommended access method for this operation.
attribution object false none Labels to send with the paid fetch so the purchase links to this
search. Left out when next_call.body already carries them.
» search_id string(uuid) false none none
» operation_id string false none none
» accessmethodid string false none none
output object false none Media type, execution mode, a bounded output summary and, for async work, the poll workflow.
docs SearchHelperDocs false none Free helper links for the upstream provider. GET these URLs.
Do not send them through weft_fetch.
contract_url string(uri) true none Content-addressed full Weft contract. GET it with your Weft
credential (a buyer account key, an OAuth token with the search
scope, or a claimed wbt_* bootstrap bearer) before you build a
request the summary does not fully describe. A pending bootstrap
bearer gets 401 until a human approves the account.
contract_detail string true none What this summary leaves out of the full contract.
completion string false none Completion guidance when the completion rules did not fit inline.
blocked_scopes [object] false none none
» scope string false none none
» state string false none none
contract_gaps [string] false none Contract fields that the review did not complete.
readiness object true none Independent readiness claims (research, contract, runtime,
paid_terminal), each with a state and, when it fits, a scope.
» additionalProperties object false none none
»» state string false none none
»» scope string false none none
next_call SearchCompactNextCall false none A ready paid call, present when the request is determined and the
Weft fetch runtime can pay the access method. Replace each {name}
listed in fill in body (and add max_cost_usd or body when they
are listed), then send body as the JSON body of POST /api/v1/fetch
with an Idempotency-Key header. body uses the wire field names
(max_cost_usd, search_id); an SDK fetch call may name them
differently, so map each field and keep the attribution fields.

SearchCompactAccess

{
  "id": "string",
  "protocol": "string",
  "weft_fetch": {},
  "price": {
    "kind": "string",
    "indexed_usd": "string",
    "unit": "string",
    "hint": "string"
  }
}

The recommended access method for this operation.

Properties

Name Type Required Restrictions Description
id string false none The access_method_id to send to POST /api/v1/fetch.
protocol string false none none
weft_fetch object false none Whether the Weft fetch runtime can pay this access method (state, and reason and coverage when they fit).
price object false none none
» kind string false none Price kind, such as fixed, dynamic, free or unknown.
» indexed_usd string¦null false none Indexed USD price. A dynamic price is not a cap.
» unit string¦null false none none
» hint string false none none

SearchCompactNextCall

{
  "method": "POST",
  "path": "/api/v1/fetch",
  "body": {},
  "fill": [
    "string"
  ]
}

A ready paid call, present when the request is determined and the Weft fetch runtime can pay the access method. Replace each {name} listed in fill in body (and add max_cost_usd or body when they are listed), then send body as the JSON body of POST /api/v1/fetch with an Idempotency-Key header. body uses the wire field names (max_cost_usd, search_id); an SDK fetch call may name them differently, so map each field and keep the attribution fields.

Properties

Name Type Required Restrictions Description
method string true none none
path string true none none
body object true none A FetchRequest with documented example values and {name} placeholders.
fill [string] true none Names to replace before you send the request.

Enumerated Values

Property Value
method POST
path /api/v1/fetch

SearchResult

{
  "provider": {
    "provider_id": "string",
    "display_name": "string",
    "origin_domains": [
      "string"
    ]
  },
  "capability": {
    "capability_id": "string",
    "capability_type": "string"
  },
  "endpoints": [
    {
      "endpoint_id": "string",
      "url": "string",
      "resource_type": "string",
      "primary_protocol": "string",
      "call": {
        "method": "string",
        "input_schema": {},
        "example_request": {},
        "example_response": null
      },
      "price": {
        "indexed_usd": "string",
        "atomic": 0,
        "source": "probe",
        "last_observed_at": "2019-08-24T14:15:22Z",
        "live_verified": true
      },
      "payment": [
        {
          "protocol": "string",
          "scheme": "string",
          "network": "string",
          "asset": "string",
          "amount": "string",
          "pay_to": "string",
          "max_timeout_seconds": 0,
          "facilitator": "string"
        }
      ],
      "access_methods": [
        {
          "access_method_id": "string",
          "protocol": "x402",
          "scheme": "string",
          "network": "string",
          "asset": "string",
          "asset_decimals": 0,
          "price": {},
          "merchant": {},
          "terms": {},
          "status": "listed",
          "weft_fetch": {
            "state": "supported",
            "reason": "string",
            "contract_version": 0,
            "coverage": "terminal_response"
          }
        }
      ],
      "service": {
        "id": "string",
        "name": "string"
      },
      "operation": {
        "id": "string",
        "name": "string",
        "description": "string"
      },
      "docs": {
        "website": "http://example.com",
        "homepage": "http://example.com",
        "api": "http://example.com",
        "llms_txt": "http://example.com"
      },
      "contract_url": "http://example.com",
      "output_schema": {},
      "output": {},
      "execution": {
        "mode": "sync"
      },
      "callability": {
        "state": "complete",
        "missing": [
          "string"
        ]
      },
      "compatibility": {},
      "source": {
        "catalog": "curated_marketplace",
        "snapshot_version": 0,
        "captured_at": "2019-08-24T14:15:22Z"
      },
      "operator_type": "first_party",
      "operated_by_id": "string",
      "settled_via_facilitator_id": "string",
      "settlements": 0,
      "last_verified_at": "2019-08-24T14:15:22Z",
      "latency_p50_ms": 0
    }
  ],
  "score": 0
}

Properties

Name Type Required Restrictions Description
provider SearchProviderRef true none none
capability SearchCapabilityRef true none none
endpoints [SearchEndpointHit] true none none
score number(double) true none none

SearchProviderRef

{
  "provider_id": "string",
  "display_name": "string",
  "origin_domains": [
    "string"
  ]
}

Properties

Name Type Required Restrictions Description
provider_id string false none none
display_name string¦null false none none
origin_domains [string] false none none

SearchCapabilityRef

{
  "capability_id": "string",
  "capability_type": "string"
}

Properties

Name Type Required Restrictions Description
capability_id string false none none
capability_type string¦null false none none

SearchEndpointHit

{
  "endpoint_id": "string",
  "url": "string",
  "resource_type": "string",
  "primary_protocol": "string",
  "call": {
    "method": "string",
    "input_schema": {},
    "example_request": {},
    "example_response": null
  },
  "price": {
    "indexed_usd": "string",
    "atomic": 0,
    "source": "probe",
    "last_observed_at": "2019-08-24T14:15:22Z",
    "live_verified": true
  },
  "payment": [
    {
      "protocol": "string",
      "scheme": "string",
      "network": "string",
      "asset": "string",
      "amount": "string",
      "pay_to": "string",
      "max_timeout_seconds": 0,
      "facilitator": "string"
    }
  ],
  "access_methods": [
    {
      "access_method_id": "string",
      "protocol": "x402",
      "scheme": "string",
      "network": "string",
      "asset": "string",
      "asset_decimals": 0,
      "price": {},
      "merchant": {},
      "terms": {},
      "status": "listed",
      "weft_fetch": {
        "state": "supported",
        "reason": "string",
        "contract_version": 0,
        "coverage": "terminal_response"
      }
    }
  ],
  "service": {
    "id": "string",
    "name": "string"
  },
  "operation": {
    "id": "string",
    "name": "string",
    "description": "string"
  },
  "docs": {
    "website": "http://example.com",
    "homepage": "http://example.com",
    "api": "http://example.com",
    "llms_txt": "http://example.com"
  },
  "contract_url": "http://example.com",
  "output_schema": {},
  "output": {},
  "execution": {
    "mode": "sync"
  },
  "callability": {
    "state": "complete",
    "missing": [
      "string"
    ]
  },
  "compatibility": {},
  "source": {
    "catalog": "curated_marketplace",
    "snapshot_version": 0,
    "captured_at": "2019-08-24T14:15:22Z"
  },
  "operator_type": "first_party",
  "operated_by_id": "string",
  "settled_via_facilitator_id": "string",
  "settlements": 0,
  "last_verified_at": "2019-08-24T14:15:22Z",
  "latency_p50_ms": 0
}

Properties

Name Type Required Restrictions Description
endpoint_id string false none none
url string¦null false none none
resource_type string¦null false none none
primary_protocol string¦null false none none
call SearchEndpointCall false none The machine-readable call contract for this endpoint: the verb, the
provider-declared argument schema, and the worked examples. Always
present; an endpoint whose provider declares nothing carries an empty
method and null members rather than an absent block, so a caller can
always read input_schema without a presence check. Combine with the
hit's url to construct the request.
price SearchEndpointPrice false none Price + provenance + freshness for this (endpoint × capability) pairing.
Always present; an unpriced endpoint carries null amounts rather than an
absent block, so a caller never has to distinguish "free" from "we do not
know".
payment [SearchPaymentOffer] false none The settlement routes this endpoint's own 402 challenge published —
one entry per rail × network × asset × payee it accepts. Sibling of
call: that block says how to shape the request, this says how to
pay for it, so a caller can settle with its OWN x402/mpp SDK instead
of guessing. A list because rails are irreducibly plural. Order is
the provider's own preference order. Honest-empty when the pipeline
observed no challenge.
access_methods [SearchAccessMethod] false none none
service SearchCuratedService false none none
operation SearchCuratedOperation false none none
docs SearchHelperDocs false none Free helper links for the upstream provider. GET these URLs.
Do not send them through weft_fetch.
contract_url string(uri) false none Content-addressed Weft contract for the complete operation,
alternatives, evidence, and known gaps. Authenticated GET.
output_schema object¦null false none none
output object¦null false none none
execution SearchCuratedExecution false none none
callability SearchCuratedCallability false none none
compatibility object¦null false none none
source SearchCuratedSource false none none
operator_type string¦null false none Who you are actually paying. first_party = operated by the provider
that makes the capability; reseller = resold, so the price carries
someone else's margin; gateway = an intermediary routing the provider's
capability. Null until the platform resolves the operator.
operatedbyid string¦null false none none
settledviafacilitator_id string¦null false none none
settlements integer¦null false none Count of payments observed settling against this endpoint by ANYONE
(chain-indexed), not just by Weft — the reliability signal a caller
can act on. Null when unknown.
lastverifiedat string(date-time)¦null false none When Weft last CONFIRMED this endpoint answers — the most recent
conclusive probe. Null when never probed, or when the latest probe
errored: an endpoint we last failed to reach has no current
verification.
latencyp50ms integer¦null false none Median time-to-first-byte in ms across the endpoint's probe call set.
First-byte latency, not full-response time. Null when unmeasured
(never 0).

Enumerated Values

Property Value
operator_type first_party
operator_type reseller
operator_type gateway

SearchEndpointCall

{
  "method": "string",
  "input_schema": {},
  "example_request": {},
  "example_response": null
}

The machine-readable call contract for this endpoint: the verb, the provider-declared argument schema, and the worked examples. Always present; an endpoint whose provider declares nothing carries an empty method and null members rather than an absent block, so a caller can always read input_schema without a presence check. Combine with the hit's url to construct the request.

Properties

Name Type Required Restrictions Description
method string false none The HTTP verb to send. Empty string when neither the index nor the
provider's own 402 challenge / OpenAPI spec declares one.
input_schema object,boolean,null false none The request JSON Schema, including boolean true/false schemas.
Reviewed versioned contracts preserve the provider schema and apply
separately authored client scope constraints in this projection.
Null when no body schema is declared; query/path/header/cookie
bindings remain in the full contract. Retrieve contract_url before
constructing requests for versioned contracts.
example_request object¦null false none A worked set of arguments grouped by slot (query / body / path).
Every value is one the PROVIDER published; never synthesized.
example_response any false none The provider's own worked response body — what you get for your money,
before paying. Carried verbatim, never synthesized.

SearchEndpointPrice

{
  "indexed_usd": "string",
  "atomic": 0,
  "source": "probe",
  "last_observed_at": "2019-08-24T14:15:22Z",
  "live_verified": true
}

Price + provenance + freshness for this (endpoint × capability) pairing. Always present; an unpriced endpoint carries null amounts rather than an absent block, so a caller never has to distinguish "free" from "we do not know".

Properties

Name Type Required Restrictions Description
indexed_usd string¦null false none The indexed price in USD as a decimal string (e.g. "0.008") — the
dollar value people and agents reason in. A decimal string, never a
float; trailing zeros trimmed. Null when unpriced.
atomic integer¦null false none The same price in integer micro-USD — the settlement grain, exact.
Null exactly when indexed_usd is. Use this for settlement.
source string¦null false none Where the amount came from. probe = observed live in the endpoint's
own 402 payment-required challenge — an observation, the strongest
evidence we hold. inferred = derived from a spec (OpenAPI) or a
resale edge by the extraction pipeline, so it can lag a provider's
re-pricing. Null when the endpoint carries no price.
lastobservedat string(date-time)¦null false none When the amount was observed. Null when unrecorded.
live_verified boolean false none Whether this amount was confirmed against a live 402 challenge for
THIS response. Search does not issue a payment-required probe at
query time, so this is false today — treat an unflagged price as
indexed, not verified.

Enumerated Values

Property Value
source probe
source inferred

SearchPaymentOffer

{
  "protocol": "string",
  "scheme": "string",
  "network": "string",
  "asset": "string",
  "amount": "string",
  "pay_to": "string",
  "max_timeout_seconds": 0,
  "facilitator": "string"
}

One settlement route the endpoint's own 402 challenge published — a (rail × network × asset × payee) tuple a caller can settle against directly with its own SDK.

Properties

Name Type Required Restrictions Description
protocol string true none The payment rail (e.g. x402, mpp).
scheme string¦null false none none
network string¦null false none none
asset string¦null false none none
amount string¦null false none none
pay_to string¦null false none none
maxtimeoutseconds integer¦null false none none
facilitator string¦null false none none

SearchAccessMethod

{
  "access_method_id": "string",
  "protocol": "x402",
  "scheme": "string",
  "network": "string",
  "asset": "string",
  "asset_decimals": 0,
  "price": {},
  "merchant": {},
  "terms": {},
  "status": "listed",
  "weft_fetch": {
    "state": "supported",
    "reason": "string",
    "contract_version": 0,
    "coverage": "terminal_response"
  }
}

Properties

Name Type Required Restrictions Description
accessmethodid string true none none
protocol string true none none
scheme string¦null false none none
network string¦null false none none
asset string¦null false none none
asset_decimals integer¦null false none none
price object true none none
merchant object false none none
terms object false none none
status string false none none
weft_fetch SearchWeftFetchCompatibility true none none

Enumerated Values

Property Value
protocol x402
protocol mpp
protocol free
status listed
status observed
status unavailable

SearchWeftFetchCompatibility

{
  "state": "supported",
  "reason": "string",
  "contract_version": 0,
  "coverage": "terminal_response"
}

Properties

Name Type Required Restrictions Description
state string true none none
reason string true none none
contract_version integer true none none
coverage string false none Extent of the operation covered by weftfetch. `terminalresponse<br>covers the terminal result;submission_onlycovers submission but<br>not completion or retrieval of the result;none` means no coverage.
When absent, coverage is unknown, not terminal. Do not infer terminal
coverage from synchronous execution mode alone.

Enumerated Values

Property Value
state supported
state unsupported
state unknown
coverage terminal_response
coverage submission_only
coverage none

SearchHelperDocs

{
  "website": "http://example.com",
  "homepage": "http://example.com",
  "api": "http://example.com",
  "llms_txt": "http://example.com"
}

Free helper links for the upstream provider. GET these URLs. Do not send them through weft_fetch.

Properties

Name Type Required Restrictions Description
website string(uri) false none none
homepage string(uri) false none none
api string(uri) false none none
llms_txt string(uri) false none none

SearchCuratedService

{
  "id": "string",
  "name": "string"
}

Properties

Name Type Required Restrictions Description
id string true none none
name string true none none

SearchCuratedOperation

{
  "id": "string",
  "name": "string",
  "description": "string"
}

Properties

Name Type Required Restrictions Description
id string true none none
name string true none none
description string¦null false none none

SearchCuratedExecution

{
  "mode": "sync"
}

Properties

Name Type Required Restrictions Description
mode string¦null false none none

Enumerated Values

Property Value
mode sync
mode async
mode stream

SearchCuratedCallability

{
  "state": "complete",
  "missing": [
    "string"
  ]
}

Properties

Name Type Required Restrictions Description
state string true none none
missing [string] true none none

Enumerated Values

Property Value
state complete
state incomplete

SearchCuratedSource

{
  "catalog": "curated_marketplace",
  "snapshot_version": 0,
  "captured_at": "2019-08-24T14:15:22Z"
}

Properties

Name Type Required Restrictions Description
catalog string true none none
snapshot_version integer true none none
captured_at string(date-time) true none none

Enumerated Values

Property Value
catalog curated_marketplace

SearchErrorResponse

{
  "error": "INVALID_QUERY",
  "details": {}
}

Bespoke error envelope returned by /api/v1/search for 422, 502, and 500 responses. It differs from the standard ErrorResponse envelope (no nested code/message/request_id); SDK clients should handle both shapes for this endpoint until the controller is migrated to the standard envelope.

Properties

Name Type Required Restrictions Description
error string true none Stable error code.
details object false none Optional context. Shape varies by error code.

Enumerated Values

Property Value
error INVALID_QUERY
error INVALIDMAXRESULTS
error INVALID_FILTERS
error INVALID_VIEW
error UNKNOWN_PARAMETER
error SEARCHUPSTREAMERROR
error SEARCHBACKENDMISCONFIGURED

FetchRequest

{
  "url": "https://x402.api.agentmail.to/v0/inboxes",
  "max_cost_usd": "0.05",
  "allow_tempo_refill": false,
  "max_total_cost_usd": "0.05",
  "method": "GET",
  "body": "string",
  "headers": {
    "Accept": "application/json",
    "User-Agent": "my-agent/1.0"
  },
  "search_id": "11111111-1111-4111-8111-111111111111",
  "operation_id": "string",
  "access_method_id": "string"
}

Properties

Name Type Required Restrictions Description
url string(uri) true none Target URL. Must pass Weft's URL safety check (no SSRF / private IP ranges).
maxcostusd string false none Merchant-principal ceiling, excluding gas, provider fees and prerequisites. Defaults to 0.10 USD; use max_total_cost_usd for an all-in bound.
allowtemporefill boolean false none Whether this request may create, adopt, or enqueue a Base-to-Tempo
refill. Only JSON booleans are accepted. Omission allows legacy
refill behavior unless max_total_cost_usd is supplied, in which
case refill is disabled. False leaves unrelated bridges and jobs
unchanged and reports an unfunded Tempo pocket as
INSUFFICIENT_BALANCE. This does not select a rail or bound fees.
maxtotalcost_usd string false none Optional all-in buyer-debit ceiling in USD, including principal,
gas, provider fees and prerequisite operations. Requires a binding
upstream upper bound before any payment effect. Current integrations
have no such guarantee, so requests requiring wallet signing or
payment fail closed with TOTAL_COST_UNVERIFIABLE, including
recovery and replay of previous payments. No positive paid route
is currently admitted in this mode. Estimates, expected sponsorship
and receipts are not authority. Implies no refill; explicit
allow_tempo_refill: true is invalid. Omission preserves legacy behavior.
method string false none HTTP method to use against the upstream.
body any false none Request body forwarded to the upstream. Pass null for GET.

oneOf

Name Type Required Restrictions Description
» anonymous string false none none

xor

Name Type Required Restrictions Description
» anonymous object false none none

xor

Name Type Required Restrictions Description
» anonymous null false none none

continued

Name Type Required Restrictions Description
headers object false none Headers forwarded to the upstream. Up to 32 headers, 4 KB
total. The following are silently stripped: host,
authorization, cookie, proxy-authorization,
x-forwarded-*, x-real-ip, x-payment, connection,
upgrade.
» additionalProperties string false none none
search_id string(uuid) false none The query_trace_id from the POST /api/v1/search response that
surfaced this URL. Optional and advisory: it attributes the purchase
to the search that found it, and is used only for measurement.

It never affects payment, authorization, idempotency, or the
response body — the buyer is always resolved from the credential,
never from this field. A value that is not a well-formed handle is
ignored rather than rejected, so an analytics mistake can never cost
a fetch.
operation_id string false none Advisory operation id returned by search.
accessmethodid string false none Advisory access-method id returned by search; does not enforce a payment rail.

Enumerated Values

Property Value
method GET
method POST
method PUT
method PATCH
method DELETE
method HEAD
method OPTIONS

FetchResponse

{
  "status": 200,
  "headers": {
    "property1": "string",
    "property2": "string"
  },
  "body_base64": "string",
  "paid_usd": "0.002",
  "held_usd": "0.002",
  "payment_status": "pending",
  "tx_hash": "string",
  "protocol": "x402",
  "artifact_id": 0,
  "purchase_id": "pur_4V3n9mQ0b7XyK2sLpR8tWc1d"
}

Successful fetch envelope. body_base64 is the upstream artifact bytes, base64-encoded. paid_usd, held_usd, payment_status, tx_hash, and protocol describe the payment and settlement state. purchase_id names the payment for a later status read.

To retrieve a SIWX-protected result, use HTTPS GET with max_cost_usd: "0". Weft signs a fresh, resource-bound challenge with the same buyer wallet. Retrieval never falls back to payment and returns not_required, zero paid amount, and null held amount and transaction hash. Polls are fresh, including with repeated idempotency keys. A rejected or unsafe challenge returns SIWX_RETRIEVAL_FAILED. Providers must support smart-wallet signatures. Auth-only challenges also use this path; positive-budget purchases retain payment behavior.

paid_usd is "0.00" (never the nominal charge amount) until the charge is CONFIRMED settled on-chain — a signed-but-unsettled hold reports its amount in held_usd instead. This is a deliberate honesty fix: earlier versions of this endpoint returned the nominal amount in paid_usd unconditionally, even when the charge never settled.

Money string format. Every USD amount on this surface is exact to the micro-dollar and never narrower than two decimals: a whole-cent amount renders "0.50", a sub-cent amount keeps its real precision ("0.000892"), and zero renders "0.00". Amounts are never rounded — an agent reconciling its own spend reads the truth, not a display value. Parse these as decimals; do NOT compare them as strings against a bare zero literal.

Properties

Name Type Required Restrictions Description
status integer true none HTTP status returned by the upstream after the payment or SIWX authentication retry.
headers object true none Response headers from the upstream.
» additionalProperties string false none none
body_base64 string true none Base64-encoded response body. Empty string for empty bodies.
paid_usd string,null¦null true none USD amount actually settled on-chain. "0.00" for any charge that
hasn't (yet, or ever) settled — a signed hold is not yet spend.
See held_usd for the nominal amount in that case. Exact to the
micro-dollar, minimum two decimals; parse as a decimal rather than
string-comparing against a bare zero literal.
held_usd string,null¦null true none The nominal charge amount when paid_usd is "0.00" — a hold
awaiting settlement, or a charge that failed/expired without ever
settling. null once paid_usd reflects the real settlement.
Same format as paid_usd: exact to the micro-dollar, minimum two
decimals.
payment_status string true none Agent-facing settlement status. not_required means SIWX wallet
authentication returned the response without payment. pending = signed, no refusal
signal yet (settlement may still land, e.g. x402's async
facilitator webhook). declined-pending = the merchant refused
but the authorization isn't provably dead yet. declined /
expired / reverted are terminal — the money never moved (or,
for reverted, moved and then reversed on-chain) and never will
for this charge.
tx_hash string,null¦null true none Settlement transaction hash. Null until a settlement hash has been reported.
protocol string true none Payment protocol selected for this fetch.
artifact_id integer,null¦null true none Internal artifact identifier if the response was persisted; null otherwise.
purchase_id string,null¦null false none The buyer purchase that paid for this fetch: an opaque id that
GET /api/v1/purchases/{id} accepts and that purchase rows carry
as purchase_id. It is not the sequential Purchase.id; do not
parse or order by it. That purchase reports its
own status, not payment_status: signed while the payment is
pending, then settled (charged its amount_usd, which can be
less than held_usd) or declined, locked, expired, or
reverted (not charged). A settled purchase with
failure_reason: merchant_delivery_failed was charged, but no
successful paid response was delivered. An idempotent
replay returns the same id, so bill at most once for each id.
null when no payment was made (payment_status: not_required).

The lookup needs purchase-history access: a wk_* key, a claimed
wbt_* bearer, or a REST OAuth token with the balance scope. An
OAuth token issued for the MCP server cannot call this endpoint.
Current servers always send this field. It is optional in this
schema so that a client also accepts a response from an older
server.

Enumerated Values

Property Value
payment_status settled
payment_status pending
payment_status declined-pending
payment_status declined
payment_status expired
payment_status reverted
payment_status not_required
protocol x402
protocol mpp

FetchErrorResponse

{
  "error": "EXCEEDED_MAX_COST",
  "details": {},
  "policy": {
    "max_tx_usd": "1.00",
    "daily_limit_usd": "10.00",
    "weekly_limit_usd": "50.00"
  },
  "balance": {
    "promo_usd": "0.00",
    "wallet_usdc": "12.34",
    "total_usd": "12.34",
    "spent_today_usd": "0.42",
    "policy_used_today_usd": "0.72"
  },
  "dashboard_url": "http://example.com"
}

Bespoke error envelope for /api/v1/fetch. Every error carries the buyer's current policy, balance, and a dashboard_url so a CLI can render an actionable message without a second round-trip.

error values include the fixed codes listed below plus the POLICY_VIOLATION_<REASON> family, where <REASON> is the violated policy field (MAX_TX, DAILY, or WEEKLY — see PolicyViolation::REASONS).

Properties

Name Type Required Restrictions Description
error string true none Stable error code.
details object true none Optional context. Shape varies by error code.

purchase_id (opaque string) is present when the failure follows a
payment row for this request — a new, resumed, or replayed payment.
It is the id that GET /api/v1/purchases/{id} accepts: read that
purchase to learn whether the charge settled, instead of assuming
either outcome. It is absent when the request was refused before
any payment row existed.
policy SpendingPolicy true none none
balance FetchBalanceSnapshot true none Compact balance snapshot returned inside FetchErrorResponse. Less
rich than BalanceResponse — just the fields a CLI needs to explain
why a fetch failed.
dashboard_url string(uri) true none Deep-link to the dashboard's policy page.

Enumerated Values

Property Value
error INVALID_REQUEST
error UNKNOWN_PARAMETER
error INVALID_URL
error INVALIDMAXCOST_USD
error INVALIDALLOWTEMPO_REFILL
error INVALIDMAXTOTALCOSTUSD
error INCOMPATIBLEFETCHCONTROLS
error UNSUPPORTED_METHOD
error INVALID_BODY
error INVALID_HEADERS
error INVALIDIDEMPOTENCYKEY
error IDEMPOTENCY_CONFLICT
error ACCOUNT_CLOSING
error EXCEEDEDMAXCOST
error TOTALCOSTUNVERIFIABLE
error FUNDING_PENDING
error INSUFFICIENT_BALANCE
error PAYMENTAUTHORIZATIONREQUIRED
error WALLETSETUPINCOMPLETE
error MERCHANTRETURNEDNON_402
error MERCHANT_TIMEOUT
error MERCHANTCONNECTIONFAILED
error PAIDDELIVERYFAILED
error DELIVERYREPLAYUNAVAILABLE
error ARTIFACTTOOLARGE
error DENYLISTED_RECIPIENT
error WALLETENVIRONMENTMISMATCH
error UNSUPPORTED_ASSET
error UNSUPPORTEDPAYMENTMETHOD
error SETTLEMENT_FAILED
error SETTLEMENT_PENDING
error POLICYVIOLATIONMAX_TX
error POLICYVIOLATIONDAILY
error POLICYVIOLATIONWEEKLY

FetchBalanceSnapshot

{
  "promo_usd": "0.00",
  "wallet_usdc": "12.34",
  "total_usd": "12.34",
  "spent_today_usd": "0.42",
  "policy_used_today_usd": "0.72"
}

Compact balance snapshot returned inside FetchErrorResponse. Less rich than BalanceResponse — just the fields a CLI needs to explain why a fetch failed.

Properties

Name Type Required Restrictions Description
promo_usd string true none none
wallet_usdc string¦null true none Live Base USDC balance read server-side through Crossmint. Null when Crossmint is unavailable; never treat null as zero.
total_usd string¦null true none Aggregated USD balance across Base USDC and Tempo dollar tokens, exact to the micro-dollar. Null when either pocket is unreachable.
spenttodayusd string true none Settled USD spend in the current calendar day (UTC).
policyusedtoday_usd string true none USD counted against today's policy limit, including pending authorizations and settled spend.