W weft/api v1 v0.7.0

Weft API Reference

Agent onboarding flows, optimized for automated clients.

Quickstart

  1. Create an account and confirm email
  2. Sign in to get a session token
  3. Create an API key via the dashboard or POST /api/v1/api_keys
  4. Use your API key as a Bearer token to access the API
  5. List your payments, agents, and manage API keys

Base URLs

  • https://weft.network
  • https://staging.weft.network
  • http://localhost:3000

Authentication

Auth endpoints (sign up, sign in, etc.) do not require authentication.

All other endpoints require a Bearer token via Authorization: Bearer <token>. Use an API key (ax_live_*) obtained from the dashboard or the Create API Key endpoint.

SDKs

Install the SDK for your language:

# TypeScript / JavaScript
npm install @weft-labs/sdk

# Python
pip install weft-sdk

# Ruby
gem install weft-sdk

# Go
go get github.com/weft-labs/weft-sdk/go

TypeScript

import { Configuration, AuthApi, PaymentsApi, AgentsApi, APIKeysApi, AccountApi } from "@weft-labs/sdk";

// Auth endpoints (no token needed)
const auth = new AuthApi();

// Authenticated endpoints (API key required)
const config = new Configuration({
  accessToken: "ax_live_your_api_key_here",
});
const payments = new PaymentsApi(config);
const agents = new AgentsApi(config);
const apiKeys = new APIKeysApi(config);
const account = new AccountApi(config);

Python

import weft_sdk.generated
from weft_sdk.generated.api import payments_api, agents_api

configuration = weft_sdk.generated.Configuration(
    access_token = "ax_live_your_api_key_here"
)

with weft_sdk.generated.ApiClient(configuration) as api_client:
    payments = payments_api.PaymentsApi(api_client)
    agents = agents_api.AgentsApi(api_client)

Ruby

require 'weft-sdk'

Weft.configure do |config|
  config.access_token = 'ax_live_your_api_key_here'
end

payments = Weft::PaymentsApi.new
agents = Weft::AgentsApi.new

Go

import openapiclient "github.com/weft-labs/weft-sdk/go/generated"

configuration := openapiclient.NewConfiguration()
apiClient := openapiclient.NewAPIClient(configuration)

SDK examples are shown alongside each endpoint below. Use the language tabs to switch between implementations.

The Weft API is the buyer-runtime surface that powers the weft CLI, the hosted MCP server (weft.network/mcp), and any third-party agent that wants to discover and pay for paid resources on Weft. v1 covers five buyer concerns:

  1. Account onboarding (/api/v1/auth/*, /api/v1/me)
  2. CLI authentication (/api/v1/api_keys)
  3. Wallet visibility (/api/v1/balance)
  4. Discovery (/api/v1/search)
  5. Paid execution (/api/v1/fetch)
  6. Purchase history (/api/v1/payments)

Seller-side concerns (agent management, payout analytics, webhook delivery, the public storefront for data_api resources) live in the dashboard and are intentionally not documented here. They will be split out into a separate, dashboard-scoped spec when they need to be SDK-consumable.

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.

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

No authentication required

SDK

AuthResponse signUp(signUpRequest)

import {
  Configuration,
  AuthApi,
} from '@weft-labs/sdk';
import type { SignUpOperationRequest } from '@weft-labs/sdk';

const api = new AuthApi();

const body = {
  // SignUpRequest
  signUpRequest: ...,
} satisfies SignUpOperationRequest;

const data = await api.signUp(body);
console.log(data);

Parameters:

NameTypeDescriptionNotes
signUpRequestSignUpRequest

Returns: AuthResponse

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

SDK

AuthResponse confirmAccount(confirmRequest)

import {
  Configuration,
  AuthApi,
} from '@weft-labs/sdk';
import type { ConfirmAccountRequest } from '@weft-labs/sdk';

const api = new AuthApi();

const body = {
  // ConfirmRequest
  confirmRequest: ...,
} satisfies ConfirmAccountRequest;

const data = await api.confirmAccount(body);
console.log(data);

Parameters:

NameTypeDescriptionNotes
confirmRequestConfirmRequest

Returns: AuthResponse

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

SDK

MessageResponse resendConfirmation(resendConfirmationRequest)

import {
  Configuration,
  AuthApi,
} from '@weft-labs/sdk';
import type { ResendConfirmationOperationRequest } from '@weft-labs/sdk';

const api = new AuthApi();

const body = {
  // ResendConfirmationRequest
  resendConfirmationRequest: ...,
} satisfies ResendConfirmationOperationRequest;

const data = await api.resendConfirmation(body);
console.log(data);

Parameters:

NameTypeDescriptionNotes
resendConfirmationRequestResendConfirmationRequest

Returns: MessageResponse

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

SDK

AuthResponse signIn(signInRequest)

import {
  Configuration,
  AuthApi,
} from '@weft-labs/sdk';
import type { SignInOperationRequest } from '@weft-labs/sdk';

const api = new AuthApi();

const body = {
  // SignInRequest
  signInRequest: ...,
} satisfies SignInOperationRequest;

const data = await api.signIn(body);
console.log(data);

Parameters:

NameTypeDescriptionNotes
signInRequestSignInRequest

Returns: AuthResponse

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

SDK

MessageResponse requestPasswordReset(passwordResetRequest)

import {
  Configuration,
  AuthApi,
} from '@weft-labs/sdk';
import type { RequestPasswordResetRequest } from '@weft-labs/sdk';

const api = new AuthApi();

const body = {
  // PasswordResetRequest
  passwordResetRequest: ...,
} satisfies RequestPasswordResetRequest;

const data = await api.requestPasswordReset(body);
console.log(data);

Parameters:

NameTypeDescriptionNotes
passwordResetRequestPasswordResetRequest

Returns: MessageResponse

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

SDK

MessageResponse updatePassword(passwordUpdateRequest)

import {
  Configuration,
  AuthApi,
} from '@weft-labs/sdk';
import type { UpdatePasswordRequest } from '@weft-labs/sdk';

const api = new AuthApi();

const body = {
  // PasswordUpdateRequest
  passwordUpdateRequest: ...,
} satisfies UpdatePasswordRequest;

const data = await api.updatePassword(body);
console.log(data);

Parameters:

NameTypeDescriptionNotes
passwordUpdateRequestPasswordUpdateRequest

Returns: MessageResponse

Account

Current user account information.

Get current account

GET /api/v1/me

200 Response

{
  "data": {
    "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 user account MeResponse
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

SDK

MeResponse getMe()

import {
  Configuration,
  AccountApi,
} from '@weft-labs/sdk';
import type { GetMeRequest } from '@weft-labs/sdk';

const config = new Configuration({ 
  // Configure HTTP bearer authorization: bearerAuth
  accessToken: "YOUR BEARER TOKEN",
});
const api = new AccountApi(config);

const data = await api.getMe();
console.log(data);

Parameters: This endpoint does not need any parameter.

Returns: MeResponse

API Keys

Manage API keys used by the CLI and any direct HTTP caller.

List API keys

GET /api/v1/api_keys

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

SDK

ApiKeyListResponse listApiKeys()

import {
  Configuration,
  APIKeysApi,
} from '@weft-labs/sdk';
import type { ListApiKeysRequest } from '@weft-labs/sdk';

const config = new Configuration({ 
  // Configure HTTP bearer authorization: bearerAuth
  accessToken: "YOUR BEARER TOKEN",
});
const api = new APIKeysApi(config);

const data = await api.listApiKeys();
console.log(data);

Parameters: This endpoint does not need any parameter.

Returns: ApiKeyListResponse

Create an API key

POST /api/v1/api_keys

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

SDK

ApiKeyCreatedResponse createApiKey(createApiKeyRequest)

import {
  Configuration,
  APIKeysApi,
} from '@weft-labs/sdk';
import type { CreateApiKeyOperationRequest } from '@weft-labs/sdk';

const config = new Configuration({ 
  // Configure HTTP bearer authorization: bearerAuth
  accessToken: "YOUR BEARER TOKEN",
});
const api = new APIKeysApi(config);

const body = {
  // CreateApiKeyRequest
  createApiKeyRequest: ...,
} satisfies CreateApiKeyOperationRequest;

const data = await api.createApiKey(body);
console.log(data);

Parameters:

NameTypeDescriptionNotes
createApiKeyRequestCreateApiKeyRequest

Returns: ApiKeyCreatedResponse

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

SDK

MessageResponse revokeApiKey(id)

import {
  Configuration,
  APIKeysApi,
} from '@weft-labs/sdk';
import type { RevokeApiKeyRequest } from '@weft-labs/sdk';

const config = new Configuration({ 
  // Configure HTTP bearer authorization: bearerAuth
  accessToken: "YOUR BEARER TOKEN",
});
const api = new APIKeysApi(config);

const body = {
  // number | API key ID
  id: 56,
} satisfies RevokeApiKeyRequest;

const data = await api.revokeApiKey(body);
console.log(data);

Parameters:

NameTypeDescriptionNotes
idnumberAPI key ID[Defaults to undefined]

Returns: MessageResponse

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. wallet.balance_usdc is fetched live from Privy; if Privy is unreachable the field returns "0.00" rather than erroring the whole call.

Account-scoped: the bearer must be a buyer-scoped API key.

200 Response

{
  "promo": {
    "balance_usd": "0.00",
    "scope": "weft-search",
    "expires_at": "2019-08-24T14:15:22Z"
  },
  "wallet": {
    "address": "string",
    "balance_usdc": "12.34",
    "tempo_usd": "3.00",
    "total_usd": "15.34",
    "network": "string"
  },
  "spent_today_usd": "0.42",
  "spent_week_usd": "3.10",
  "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

SDK

BalanceResponse getBalance()

import {
  Configuration,
  BalanceApi,
} from '@weft-labs/sdk';
import type { GetBalanceRequest } from '@weft-labs/sdk';

const config = new Configuration({ 
  // Configure HTTP bearer authorization: bearerAuth
  accessToken: "YOUR BEARER TOKEN",
});
const api = new BalanceApi(config);

const data = await api.getBalance();
console.log(data);

Parameters: This endpoint does not need any parameter.

Returns: BalanceResponse

Search

Semantic search across the Weft index of paid agent resources. Returns A2A-shaped AgentCards with pricing, skills, ranking, and endpoints. The mock backend (default while the search-platform is unshipped) reads YAML fixtures from db/seeds/mock-search/; the platform backend proxies to the upstream search service. Both share the same response envelope.

Search the Weft index

POST /api/v1/search

Semantic search over the Weft index of paid agent resources. The request body carries a free-text query, an optional limit, and an optional filters object that narrows by price band, payment protocol, agent protocol, or domain tag. Filters are applied as a post-filter after the embedding score is computed.

Backend selection is server-side via the SEARCH_BACKEND env var: mock (default, reads YAML fixtures and sets _mock: true in the response) or platform (proxies to the upstream search service). Both backends return the same envelope.

Account-scoped: the bearer token must be a buyer-scoped API key. Free for authenticated buyers in v1; billing is planned for a later release.

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.

Request body

{
  "query": "send email from an agent",
  "limit": 10,
  "filters": {
    "min_price_usd": "0.01",
    "max_price_usd": "0.10",
    "payment_protocol": "x402",
    "agent_protocol": "a2a",
    "domain": "string"
  }
}

Parameters

Name In Type Required Description
body body SearchRequest true none

200 Response

{
  "results": [
    {
      "id": "string",
      "score": 1,
      "protocol": "a2a",
      "domain": [
        "string"
      ],
      "reseller": "string",
      "upstream": "string",
      "agent_card": {
        "name": "string",
        "description": "string",
        "url": "http://example.com",
        "version": "string",
        "protocolVersion": "string",
        "capabilities": {},
        "defaultInputModes": [
          "string"
        ],
        "defaultOutputModes": [
          "string"
        ],
        "skills": [
          {
            "id": "string",
            "name": "string",
            "description": "string",
            "tags": [
              "string"
            ],
            "examples": [
              "string"
            ],
            "inputModes": [
              "string"
            ],
            "outputModes": [
              "string"
            ],
            "streaming": true,
            "endpoint": {
              "method": "string",
              "path": "string"
            },
            "price_usd": "string"
          }
        ]
      },
      "pricing": {
        "protocol": "x402",
        "scheme": "per_call",
        "amount_usd": "string",
        "network": "string"
      },
      "ranking": {
        "popularity_score": 1,
        "settlement_count_30d": 0,
        "success_rate_30d": 1,
        "p50_latency_ms": 0,
        "first_seen_at": "2019-08-24T14:15:22Z"
      },
      "endpoints": {
        "a2a": "http://example.com",
        "mcp": "http://example.com",
        "openapi": "http://example.com",
        "weft_fetch_target": "http://example.com"
      }
    }
  ],
  "paid_usd": "string",
  "tx_hash": "string",
  "artifact_id": "string",
  "_mock": true
}

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| |422|Unprocessable Entity|Invalid query (empty/missing)|SearchErrorResponse| |500|Internal Server Error|Backend misconfigured (SEARCH_BACKEND unset or unknown)|SearchErrorResponse| |502|Bad Gateway|Upstream search backend error (platform backend only)|SearchErrorResponse|

Requires authentication: Bearer token

SDK

SearchResponse search(searchRequest)

import {
  Configuration,
  SearchApi,
} from '@weft-labs/sdk';
import type { SearchOperationRequest } from '@weft-labs/sdk';

const config = new Configuration({ 
  // Configure HTTP bearer authorization: bearerAuth
  accessToken: "YOUR BEARER TOKEN",
});
const api = new SearchApi(config);

const body = {
  // SearchRequest
  searchRequest: ...,
} satisfies SearchOperationRequest;

const data = await api.search(body);
console.log(data);

Parameters:

NameTypeDescriptionNotes
searchRequestSearchRequest

Returns: SearchResponse

Fetch

The universal x402 fetch proxy. POST any URL the agent wants to reach, with a max_cost_usd ceiling; Weft handles the 402 Payment Required challenge, signs the EIP-3009 payment from the buyer's wallet, 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 proxy)

POST /api/v1/fetch

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

  1. Issues the request.
  2. On 402 Payment Required, parses the merchant's challenge.
  3. Compares the asking price to max_cost_usd and the buyer's policy (max_tx_usd, daily/weekly limits).
  4. Signs an EIP-3009 transfer from the buyer's wallet.
  5. Replays the request with the X-Payment header.
  6. Streams the upstream artifact back, base64-encoded under body_base64, with paid_usd, tx_hash, and the merchant's reputation snapshot.

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.

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",
  "method": "GET",
  "body": "string",
  "headers": {
    "Accept": "application/json",
    "User-Agent": "my-agent/1.0"
  }
}

Parameters

Name In Type Required Description
body body FetchRequest true none

200 Response

{
  "status": 200,
  "headers": {
    "property1": "string",
    "property2": "string"
  },
  "body_base64": "string",
  "paid_usd": "0.002",
  "tx_hash": "string",
  "artifact_id": 0,
  "merchant": {
    "address": "string",
    "settlement_count": 0,
    "first_seen_at": "2019-08-24T14:15:22Z",
    "dispute_count": 0
  }
}

Responses

Status Meaning Description Schema
200 OK Fetch succeeded (or upstream was free); 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). Also CONVERSION_UNAVAILABLE — a cross-chain provision route is down while the buyer's funds are intact (details.venue, details.retryable: true); retry later, do NOT top up. All use FetchErrorResponse.|FetchErrorResponse| |403|Forbidden|Policy violation, 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 three 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| |413|Payload Too Large|Upstream artifact exceeded the proxy's size cap.|FetchErrorResponse| |422|Unprocessable Entity|Invalid request URL, or the merchant advertised a payment method Weft cannot sign.|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.|FetchErrorResponse| |502|Bad Gateway|Settlement signing failed on Weft's side (SETTLEMENT_FAILED).|FetchErrorResponse|

Response Schema

Enumerated Values

Property Value
error INVALID_URL
error EXCEEDEDMAXCOST
error INSUFFICIENT_BALANCE
error CONVERSION_UNAVAILABLE
error MERCHANTRETURNEDNON_402
error ARTIFACTTOOLARGE
error DENYLISTED_RECIPIENT
error WALLETENVIRONMENTMISMATCH
error SETTLEMENT_FAILED
error UNSUPPORTEDPAYMENTMETHOD
error POLICYVIOLATIONMAX_TX
error POLICYVIOLATIONDAILY
error POLICYVIOLATIONWEEKLY
error insufficient_scope

Requires authentication: Bearer token

SDK

FetchResponse fetch(fetchRequest)

import {
  Configuration,
  FetchApi,
} from '@weft-labs/sdk';
import type { FetchOperationRequest } from '@weft-labs/sdk';

const config = new Configuration({ 
  // Configure HTTP bearer authorization: bearerAuth
  accessToken: "YOUR BEARER TOKEN",
});
const api = new FetchApi(config);

const body = {
  // FetchRequest
  fetchRequest: ...,
} satisfies FetchOperationRequest;

const data = await api.fetch(body);
console.log(data);

Parameters:

NameTypeDescriptionNotes
fetchRequestFetchRequest

Returns: FetchResponse

Payments

Payment history and individual purchase details.

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",
      "fee_amount": 0,
      "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

SDK

PaymentListResponse listPayments(page, perPage)

import {
  Configuration,
  PaymentsApi,
} from '@weft-labs/sdk';
import type { ListPaymentsRequest } from '@weft-labs/sdk';

const config = new Configuration({ 
  // Configure HTTP bearer authorization: bearerAuth
  accessToken: "YOUR BEARER TOKEN",
});
const api = new PaymentsApi(config);

const body = {
  // number | Page number (optional)
  page: 56,
  // number | Items per page (optional)
  perPage: 56,
} satisfies ListPaymentsRequest;

const data = await api.listPayments(body);
console.log(data);

Parameters:

NameTypeDescriptionNotes
pagenumberPage number[Optional] [Defaults to 1]
perPagenumberItems per page[Optional] [Defaults to 25]

Returns: PaymentListResponse

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",
    "fee_amount": 0,
    "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

SDK

PaymentResponse getPayment(id)

import {
  Configuration,
  PaymentsApi,
} from '@weft-labs/sdk';
import type { GetPaymentRequest } from '@weft-labs/sdk';

const config = new Configuration({ 
  // Configure HTTP bearer authorization: bearerAuth
  accessToken: "YOUR BEARER TOKEN",
});
const api = new PaymentsApi(config);

const body = {
  // number | Payment ID
  id: 56,
} satisfies GetPaymentRequest;

const data = await api.getPayment(body);
console.log(data);

Parameters:

NameTypeDescriptionNotes
idnumberPayment ID[Defaults to undefined]

Returns: PaymentResponse

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

SDK

ResourceEnrollmentResponse enroll_resource(resource_enrollment_request)

import weft_sdk.generated
from weft_sdk.generated.models.resource_enrollment_request import ResourceEnrollmentRequest
from weft_sdk.generated.models.resource_enrollment_response import ResourceEnrollmentResponse
from weft_sdk.generated.rest import ApiException

configuration = weft_sdk.generated.Configuration(
)


# Enter a context with an instance of the API client
with weft_sdk.generated.ApiClient(configuration) as api_client:
    # Create an instance of the API class
    api_instance = weft_sdk.generated.ResourcesApi(api_client)
    resource_enrollment_request = weft_sdk.generated.ResourceEnrollmentRequest() # ResourceEnrollmentRequest | 

    try:
        # Self-enroll a ghost resource (public, no auth)
        api_response = api_instance.enroll_resource(resource_enrollment_request)
        print(api_response)
    except Exception as e:
        print("Exception when calling ResourcesApi->enroll_resource: %s\n" % e)

Schemas

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": {
    "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 AccountDetails true 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).

AccountDetails

{
  "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
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

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",
  "fee_amount": 0,
  "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
fee_amount integer 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",
      "fee_amount": 0,
      "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",
    "fee_amount": 0,
    "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

BalanceResponse

{
  "promo": {
    "balance_usd": "0.00",
    "scope": "weft-search",
    "expires_at": "2019-08-24T14:15:22Z"
  },
  "wallet": {
    "address": "string",
    "balance_usdc": "12.34",
    "tempo_usd": "3.00",
    "total_usd": "15.34",
    "network": "string"
  },
  "spent_today_usd": "0.42",
  "spent_week_usd": "3.10",
  "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), 2dp.
spentweekusd string true none USD spent in the current calendar week (UTC, Monday start), 2dp.
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

{
  "address": "string",
  "balance_usdc": "12.34",
  "tempo_usd": "3.00",
  "total_usd": "15.34",
  "network": "string"
}

Properties

Name Type Required Restrictions Description
address string¦null true none EVM address of the buyer's Privy-managed wallet. Null if no wallet provisioned.
balance_usdc string true none Live Base USDC balance, 2dp. Returns "0.00" if the upstream wallet provider is unreachable.
tempo_usd string¦null true none Aggregated USD value of the allowlisted Tempo TIP-20 dollar tokens on the wallet's paired Tempo chain, 2dp. null when the value is UNKNOWN — the Tempo RPC read failed, or no dollar token is allowlisted for that chain yet (e.g. Tempo mainnet pre-launch). A null here is never "0.00"; it means "we couldn't determine it", and total_usd then reflects the Base component only.
total_usd string¦null true none Single aggregated USD balance = Base USDC + Tempo dollar tokens, 2dp. When tempo_usd is null (unavailable/unallowlisted) this equals balance_usdc alone. Null when the Base USDC provider is unreachable, because the surface never claims zero for a component it could not read.
network string¦null true none Wallet network (e.g. base-sepolia).

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",
  "limit": 10,
  "filters": {
    "min_price_usd": "0.01",
    "max_price_usd": "0.10",
    "payment_protocol": "x402",
    "agent_protocol": "a2a",
    "domain": "string"
  }
}

Properties

Name Type Required Restrictions Description
query string true none Free-text query. Required and non-empty.
limit integer false none Max number of hits to return. Clamped to [1, 50].
filters SearchFilters false none Optional narrowing applied after the embedding score is computed.
Unknown keys are rejected. Price filters use the agent's cheapest
skill for max_price_usd and the most-expensive skill for
min_price_usd, so an agent stays in results as long as any one
of its skills satisfies the band.

SearchFilters

{
  "min_price_usd": "0.01",
  "max_price_usd": "0.10",
  "payment_protocol": "x402",
  "agent_protocol": "a2a",
  "domain": "string"
}

Optional narrowing applied after the embedding score is computed. Unknown keys are rejected. Price filters use the agent's cheapest skill for max_price_usd and the most-expensive skill for min_price_usd, so an agent stays in results as long as any one of its skills satisfies the band.

Properties

Name Type Required Restrictions Description
minpriceusd string false none Decimal USD floor; agent must have at least one skill priced at or above this.
maxpriceusd string false none Decimal USD ceiling; agent must have at least one skill priced at or below this.
payment_protocol string false none Payment protocol the agent settles on.
agent_protocol string false none Agent protocol surface (Agent-to-Agent, MCP, raw OpenAPI, or AgentNet).
domain string false none Substring match against any of the agent's declared domain tags
(e.g. email, sales, enrichment).

Enumerated Values

Property Value
payment_protocol x402
payment_protocol mpp
payment_protocol free
agent_protocol a2a
agent_protocol mcp
agent_protocol openapi
agent_protocol AgentNet

SearchResponse

{
  "results": [
    {
      "id": "string",
      "score": 1,
      "protocol": "a2a",
      "domain": [
        "string"
      ],
      "reseller": "string",
      "upstream": "string",
      "agent_card": {
        "name": "string",
        "description": "string",
        "url": "http://example.com",
        "version": "string",
        "protocolVersion": "string",
        "capabilities": {},
        "defaultInputModes": [
          "string"
        ],
        "defaultOutputModes": [
          "string"
        ],
        "skills": [
          {
            "id": "string",
            "name": "string",
            "description": "string",
            "tags": [
              "string"
            ],
            "examples": [
              "string"
            ],
            "inputModes": [
              "string"
            ],
            "outputModes": [
              "string"
            ],
            "streaming": true,
            "endpoint": {
              "method": "string",
              "path": "string"
            },
            "price_usd": "string"
          }
        ]
      },
      "pricing": {
        "protocol": "x402",
        "scheme": "per_call",
        "amount_usd": "string",
        "network": "string"
      },
      "ranking": {
        "popularity_score": 1,
        "settlement_count_30d": 0,
        "success_rate_30d": 1,
        "p50_latency_ms": 0,
        "first_seen_at": "2019-08-24T14:15:22Z"
      },
      "endpoints": {
        "a2a": "http://example.com",
        "mcp": "http://example.com",
        "openapi": "http://example.com",
        "weft_fetch_target": "http://example.com"
      }
    }
  ],
  "paid_usd": "string",
  "tx_hash": "string",
  "artifact_id": "string",
  "_mock": true
}

Spec-11 search envelope. paid_usd, tx_hash, and artifact_id are reserved for a later release that adds per-call billing and artifact persistence; they are always null in v1. _mock: true is set only by the mock backend.

Result rows: the mock backend (SEARCH_BACKEND=mock, the default while the real index is unshipped) emits the rich, SDK-facing SearchResult shape. The legacy platform backend proxies the upstream search service and passes its result rows through verbatim — Weft does not own or reshape that payload, so those rows are typed as a free-form object. SDK clients on v1 should treat unknown row shapes defensively until the platform backend is retrofitted to the SearchResult contract (specs 07 + 10).

Because the PlatformSearchResult branch is intentionally permissive (free-form, to admit the un-owned platform rows), the anyOf is satisfied by any object — so the committee response-validation gate does NOT strictly validate result-row shapes; the rich SearchResult contract is instead guarded by the /api/v1/search request spec.

Properties

Name Type Required Restrictions Description
results [anyOf] true none none

anyOf

Name Type Required Restrictions Description
» anonymous SearchResult false none none

or

Name Type Required Restrictions Description
» anonymous PlatformSearchResult false none A result row from the legacy platform search backend. The
/api/v1/search controller proxies the upstream search service and
passes its rows through verbatim, so Weft does not own or constrain
this shape. Documented as a free-form object purely so the canonical
spec stays truthful about both backends. SDK clients should prefer the
rich SearchResult shape and treat platform rows defensively.

continued

Name Type Required Restrictions Description
paid_usd string¦null false none Always null in v1.
tx_hash string¦null false none Always null in v1.
artifact_id string¦null false none Always null in v1.
_mock boolean false none Present and true only when served by the mock backend.

SearchResult

{
  "id": "string",
  "score": 1,
  "protocol": "a2a",
  "domain": [
    "string"
  ],
  "reseller": "string",
  "upstream": "string",
  "agent_card": {
    "name": "string",
    "description": "string",
    "url": "http://example.com",
    "version": "string",
    "protocolVersion": "string",
    "capabilities": {},
    "defaultInputModes": [
      "string"
    ],
    "defaultOutputModes": [
      "string"
    ],
    "skills": [
      {
        "id": "string",
        "name": "string",
        "description": "string",
        "tags": [
          "string"
        ],
        "examples": [
          "string"
        ],
        "inputModes": [
          "string"
        ],
        "outputModes": [
          "string"
        ],
        "streaming": true,
        "endpoint": {
          "method": "string",
          "path": "string"
        },
        "price_usd": "string"
      }
    ]
  },
  "pricing": {
    "protocol": "x402",
    "scheme": "per_call",
    "amount_usd": "string",
    "network": "string"
  },
  "ranking": {
    "popularity_score": 1,
    "settlement_count_30d": 0,
    "success_rate_30d": 1,
    "p50_latency_ms": 0,
    "first_seen_at": "2019-08-24T14:15:22Z"
  },
  "endpoints": {
    "a2a": "http://example.com",
    "mcp": "http://example.com",
    "openapi": "http://example.com",
    "weft_fetch_target": "http://example.com"
  }
}

Properties

Name Type Required Restrictions Description
id string true none Stable agent identifier (e.g. weft:agent:agentmail).
score number(double) true none Cosine similarity score, clipped to [0, 1].
protocol string true none Agent protocol surface.
domain [string] true none Domain tags declared by the agent.
reseller string¦null false none Reseller slug if this agent is fronted by an aggregator (e.g. locus).
upstream string¦null false none Upstream provider hostname when fronted by a reseller.
agent_card SearchAgentCard true none A2A-spec-shaped AgentCard. Free-form capabilities and per-skill
metadata follow the upstream A2A schema; documented here only at
the surface level Weft's index actually populates.
pricing SearchPricing true none Aggregate pricing at the agent level. recipient_address is
intentionally absent from the index — under x402 it is delivered
per-request in the 402 Payment Required challenge from the agent.
ranking SearchRanking true none none
endpoints SearchEndpoints true none Per-protocol entry points for the agent. Any field may be null
if the agent does not expose that protocol surface.

Enumerated Values

Property Value
protocol a2a
protocol mcp
protocol openapi
protocol AgentNet

PlatformSearchResult

{}

A result row from the legacy platform search backend. The /api/v1/search controller proxies the upstream search service and passes its rows through verbatim, so Weft does not own or constrain this shape. Documented as a free-form object purely so the canonical spec stays truthful about both backends. SDK clients should prefer the rich SearchResult shape and treat platform rows defensively.

Properties

None

SearchAgentCard

{
  "name": "string",
  "description": "string",
  "url": "http://example.com",
  "version": "string",
  "protocolVersion": "string",
  "capabilities": {},
  "defaultInputModes": [
    "string"
  ],
  "defaultOutputModes": [
    "string"
  ],
  "skills": [
    {
      "id": "string",
      "name": "string",
      "description": "string",
      "tags": [
        "string"
      ],
      "examples": [
        "string"
      ],
      "inputModes": [
        "string"
      ],
      "outputModes": [
        "string"
      ],
      "streaming": true,
      "endpoint": {
        "method": "string",
        "path": "string"
      },
      "price_usd": "string"
    }
  ]
}

A2A-spec-shaped AgentCard. Free-form capabilities and per-skill metadata follow the upstream A2A schema; documented here only at the surface level Weft's index actually populates.

Properties

Name Type Required Restrictions Description
name string false none none
description string false none none
url string(uri) false none none
version string false none none
protocolVersion string false none none
capabilities object false none none
defaultInputModes [string] false none none
defaultOutputModes [string] false none none
skills [SearchSkill] false none none

SearchSkill

{
  "id": "string",
  "name": "string",
  "description": "string",
  "tags": [
    "string"
  ],
  "examples": [
    "string"
  ],
  "inputModes": [
    "string"
  ],
  "outputModes": [
    "string"
  ],
  "streaming": true,
  "endpoint": {
    "method": "string",
    "path": "string"
  },
  "price_usd": "string"
}

Properties

Name Type Required Restrictions Description
id string false none none
name string false none none
description string false none none
tags [string] false none none
examples [string] false none none
inputModes [string] false none none
outputModes [string] false none none
streaming boolean false none True for skills that require streaming transport (e.g. websockets).
Streaming skills are filtered out of results by default so
non-streaming clients only see callable skills.
endpoint object false none none
» method string false none HTTP method or WEBSOCKET for streaming skills.
» path string false none none
price_usd string false none Per-call price in USD for this individual skill.

SearchPricing

{
  "protocol": "x402",
  "scheme": "per_call",
  "amount_usd": "string",
  "network": "string"
}

Aggregate pricing at the agent level. recipient_address is intentionally absent from the index — under x402 it is delivered per-request in the 402 Payment Required challenge from the agent.

Properties

Name Type Required Restrictions Description
protocol string false none none
scheme string false none none
amount_usd string false none Default per-call amount; individual skills may override via price_usd.
network string false none Settlement network (e.g. base-sepolia).

Enumerated Values

Property Value
protocol x402
protocol mpp
protocol free

SearchRanking

{
  "popularity_score": 1,
  "settlement_count_30d": 0,
  "success_rate_30d": 1,
  "p50_latency_ms": 0,
  "first_seen_at": "2019-08-24T14:15:22Z"
}

Properties

Name Type Required Restrictions Description
popularity_score number(double) false none none
settlementcount30d integer false none none
successrate30d number(double) false none none
p50latencyms integer false none none
firstseenat string(date-time) false none none

SearchEndpoints

{
  "a2a": "http://example.com",
  "mcp": "http://example.com",
  "openapi": "http://example.com",
  "weft_fetch_target": "http://example.com"
}

Per-protocol entry points for the agent. Any field may be null if the agent does not expose that protocol surface.

Properties

Name Type Required Restrictions Description
a2a string(uri)¦null false none none
mcp string(uri)¦null false none none
openapi string(uri)¦null false none URL to the agent's OpenAPI document.
weftfetchtarget string(uri)¦null false none Base URL the weft_fetch MCP tool should target for this agent.

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 SEARCHUPSTREAMERROR
error SEARCHBACKENDMISCONFIGURED

FetchRequest

{
  "url": "https://x402.api.agentmail.to/v0/inboxes",
  "max_cost_usd": "0.05",
  "method": "GET",
  "body": "string",
  "headers": {
    "Accept": "application/json",
    "User-Agent": "my-agent/1.0"
  }
}

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 Hard ceiling on what the buyer is willing to pay. Defaults to 0.10 USD.
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

Enumerated Values

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

FetchResponse

{
  "status": 200,
  "headers": {
    "property1": "string",
    "property2": "string"
  },
  "body_base64": "string",
  "paid_usd": "0.002",
  "tx_hash": "string",
  "artifact_id": 0,
  "merchant": {
    "address": "string",
    "settlement_count": 0,
    "first_seen_at": "2019-08-24T14:15:22Z",
    "dispute_count": 0
  }
}

Successful fetch envelope. body_base64 is the upstream artifact bytes, base64-encoded. paid_usd, tx_hash, and merchant are populated only when the upstream charged for the response.

Properties

Name Type Required Restrictions Description
status integer true none HTTP status returned by the upstream after the paid replay.
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 true none USD amount actually settled. Null for free upstreams.
tx_hash string¦null true none Settlement transaction hash. Null for free upstreams.
artifact_id integer¦null true none Internal artifact identifier if the response was persisted; null otherwise.
merchant Merchant¦null true none Merchant reputation snapshot. Null for free upstreams.

Merchant

{
  "address": "string",
  "settlement_count": 0,
  "first_seen_at": "2019-08-24T14:15:22Z",
  "dispute_count": 0
}

Properties

Name Type Required Restrictions Description
address string true none EVM address that received the payment.
settlement_count integer true none All-time settlement count for this merchant address.
firstseenat string(date-time)¦null true none First time Weft observed a payment to this address.
dispute_count integer true none All-time dispute count for this merchant address.

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",
    "tempo_usd": "3.00",
    "total_usd": "15.34",
    "spent_today_usd": "0.42"
  },
  "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.
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_URL
error EXCEEDEDMAXCOST
error INSUFFICIENT_BALANCE
error CONVERSION_UNAVAILABLE
error MERCHANTRETURNEDNON_402
error ARTIFACTTOOLARGE
error DENYLISTED_RECIPIENT
error WALLETENVIRONMENTMISMATCH
error SETTLEMENT_FAILED
error UNSUPPORTEDPAYMENTMETHOD
error POLICYVIOLATIONMAX_TX
error POLICYVIOLATIONDAILY
error POLICYVIOLATIONWEEKLY

FetchBalanceSnapshot

{
  "promo_usd": "0.00",
  "wallet_usdc": "12.34",
  "tempo_usd": "3.00",
  "total_usd": "15.34",
  "spent_today_usd": "0.42"
}

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 true none Live Base USDC balance.
tempo_usd string¦null true none Aggregated USD of allowlisted Tempo dollar tokens, 2dp. null when UNKNOWN (RPC read failed or no token allowlisted for the paired chain) — never "0.00" for an unread component.
total_usd string¦null true none Aggregated USD balance = Base USDC + Tempo dollar tokens, 2dp. Equals wallet_usdc alone when tempo_usd is null. Null when the Base USDC provider is unreachable.
spenttodayusd string true none none