Skip to main content

Overview

The procurement layer provides intelligent routing for x402 HTTP payments with:
  • Circuit breakers - Auto-disable failing providers
  • Quality scoring - Track success rates, latency, and response quality
  • Policy enforcement - Domain allowlists, spending caps, network restrictions
  • Automatic retries - Fallback to next-best candidate on failure

Runtime Spend Limit

Session-level guardrail to cap total x402 spending using Pinion runtime.

Get Spend Limit Status

curl -X GET https://api.example.com/x402/runtime-spend-limit
{
  "success": true,
  "status": {
    "active": true,
    "maxUsdc": "1.00",
    "spentUsdc": "0.15",
    "remainingUsdc": "0.85"
  }
}

Set Spend Limit

Requires admin authentication via x-admin-key header.
curl -X POST https://api.example.com/x402/runtime-spend-limit \
  -H "Content-Type: application/json" \
  -H "x-admin-key: your-admin-key" \
  -d '{
    "action": "set",
    "maxUsdc": "2.00"
  }'
action
string
required
Action to perform: set, clear, or status
maxUsdc
string
Maximum USDC spending limit (required for action: "set")
{
  "success": true,
  "status": {
    "active": true,
    "maxUsdc": "2.00",
    "spentUsdc": "0.15",
    "remainingUsdc": "1.85"
  }
}

Clear Spend Limit

curl -X POST https://api.example.com/x402/runtime-spend-limit \
  -H "Content-Type: application/json" \
  -H "x-admin-key: your-admin-key" \
  -d '{
    "action": "clear"
  }'

Rank Candidates

curl -X POST https://api.example.com/x402/procurement/rank \
  -H "Content-Type: application/json" \
  -d '{
    "intent": "fetch-oracle-price",
    "candidates": [
      {
        "id": "oracle-a",
        "url": "https://oracle-a.example.com/api/price",
        "method": "GET",
        "maxAmountAtomic": "10000"
      },
      {
        "id": "oracle-b",
        "url": "https://oracle-b.example.com/api/price",
        "method": "GET",
        "maxAmountAtomic": "15000"
      }
    ],
    "policy": {
      "maxAmountAtomic": "20000",
      "requireHttps": true,
      "requireX402": true
    }
  }'
Request Body
intent
string
required
Human-readable intent label (e.g., “fetch-oracle-price”, “query-chain-data”)
candidates
array
required
Array of candidate x402 endpoints
policy
object
Optional policy constraints
{
  "success": true,
  "intent": "fetch-oracle-price",
  "selected": {
    "id": "oracle-a",
    "url": "https://oracle-a.example.com/api/price",
    "score": 0.87
  },
  "ranked": [
    {
      "candidate": {
        "id": "oracle-a",
        "url": "https://oracle-a.example.com/api/price",
        "method": "GET",
        "maxAmountAtomic": "10000"
      },
      "allowed": true,
      "score": 0.87,
      "reasons": [],
      "metrics": {
        "successRate": 0.98,
        "schemaRate": 1.0,
        "qualityScoreAvg": 0.92,
        "avgLatencyMs": 150,
        "latencyScore": 0.975,
        "priceScore": 0.99,
        "circuitOpen": false
      }
    },
    {
      "candidate": {
        "id": "oracle-b",
        "url": "https://oracle-b.example.com/api/price",
        "method": "GET",
        "maxAmountAtomic": "15000"
      },
      "allowed": false,
      "score": 0.0,
      "reasons": ["Circuit breaker is open"],
      "metrics": {
        "successRate": 0.45,
        "schemaRate": 0.5,
        "qualityScoreAvg": 0.4,
        "avgLatencyMs": 3500,
        "latencyScore": 0.42,
        "priceScore": 0.985,
        "circuitOpen": true
      }
    }
  ]
}
Response Fields
success
boolean
required
Whether the request succeeded
intent
string
required
Echo of the request intent
selected
object
The highest-scoring allowed candidate (null if none passed)
ranked
array
required
All candidates sorted by score (highest first)
The rank endpoint does not execute calls—it only scores candidates. Use /x402/procurement/execute to actually invoke a service.

Execute Procurement

curl -X POST https://api.example.com/x402/procurement/execute \
  -H "x-admin-key: your-admin-key" \
  -H "Content-Type: application/json" \
  -d '{
    "intent": "fetch-oracle-price",
    "candidates": [
      {
        "id": "oracle-a",
        "url": "https://oracle-a.example.com/api/price?symbol=BTC",
        "method": "GET",
        "maxAmountAtomic": "10000",
        "expectedFields": ["price", "symbol"]
      }
    ],
    "policy": {
      "maxAmountAtomic": "20000",
      "requireX402": true,
      "maxAttempts": 2
    }
  }'
This endpoint requires admin authentication via x-admin-key header.
Request Body Identical to /x402/procurement/rank (see above).
{
  "success": true,
  "ranking": {
    "intent": "fetch-oracle-price",
    "selected": {
      "id": "oracle-a",
      "url": "https://oracle-a.example.com/api/price?symbol=BTC",
      "score": 0.87
    },
    "ranked": [...]
  },
  "selected": {
    "id": "oracle-a",
    "url": "https://oracle-a.example.com/api/price?symbol=BTC",
    "score": 0.87
  },
  "receipt": {
    "id": "proc-1234567890-abc123",
    "intent": "fetch-oracle-price",
    "providerId": "oracle-a",
    "url": "https://oracle-a.example.com/api/price?symbol=BTC",
    "method": "GET",
    "status": 200,
    "paidAmountAtomic": "10000",
    "responseHash": "d4f3a2...",
    "latencyMs": 145,
    "success": true,
    "schemaOk": true,
    "score": 0.87,
    "txHash": "0xabc...",
    "payTo": "0x1234...",
    "attempt": 1,
    "error": null,
    "createdAt": "2026-03-03T10:30:00.000Z"
  },
  "schemaOk": true,
  "response": {
    "price": 65000.0,
    "symbol": "BTC"
  },
  "status": 200,
  "paidAmountAtomic": "10000"
}
Response Fields
success
boolean
required
Whether execution succeeded
ranking
object
required
Full ranking results (same as /rank endpoint)
selected
object
required
The candidate that was executed
receipt
object
required
Execution receipt with payment and performance data
response
any
required
The actual API response data
schemaOk
boolean
required
Whether response matched expected schema
status
number
required
HTTP response status code
paidAmountAtomic
string
required
Amount paid for the successful call

Get Procurement State

curl -X GET https://api.example.com/x402/procurement/state
Returns current provider performance stats and recent receipts.
{
  "success": true,
  "providers": [
    {
      "id": "oracle-a",
      "calls": 245,
      "successes": 240,
      "failures": 5,
      "avgLatencyMs": 150.5,
      "schemaPasses": 240,
      "qualityScoreAvg": 0.92,
      "consecutiveFailures": 0,
      "circuitOpenUntil": null,
      "lastStatus": 200,
      "lastError": null,
      "lastSeenAt": "2026-03-03T10:30:00.000Z",
      "updatedAt": "2026-03-03T10:30:00.000Z"
    },
    {
      "id": "oracle-b",
      "calls": 120,
      "successes": 85,
      "failures": 35,
      "avgLatencyMs": 3200.0,
      "schemaPasses": 80,
      "qualityScoreAvg": 0.45,
      "consecutiveFailures": 5,
      "circuitOpenUntil": "2026-03-03T10:35:00.000Z",
      "lastStatus": 500,
      "lastError": "Internal Server Error",
      "lastSeenAt": "2026-03-03T10:27:00.000Z",
      "updatedAt": "2026-03-03T10:27:00.000Z"
    }
  ],
  "receipts": [
    {
      "id": "proc-1234567890-abc123",
      "intent": "fetch-oracle-price",
      "providerId": "oracle-a",
      "status": 200,
      "success": true,
      "latencyMs": 145,
      "createdAt": "2026-03-03T10:30:00.000Z"
    }
  ],
  "hydrated": true
}
Response Fields
providers
array
required
All tracked providers with performance metrics
receipts
array
required
Recent execution receipts (last 100)
hydrated
boolean
required
Whether state has been loaded from database

Error Responses

{
  "success": false,
  "error": "candidates[] is required"
}
{
  "success": false,
  "error": "Unauthorized"
}
{
  "success": false,
  "error": "All procurement candidates failed. oracle-a: circuit breaker open | oracle-b: Domain blocked by policy: untrusted.com"
}

Circuit Breaker Logic

Providers are automatically disabled when:
  1. Consecutive failures >= X402_PROCUREMENT_CIRCUIT_FAIL_THRESHOLD (default: 3)
  2. Circuit opens for X402_PROCUREMENT_CIRCUIT_OPEN_MS (default: 180000ms = 3 minutes)
  3. During circuit open period, provider receives score of 0.0 and is skipped
Circuit breakers automatically reset after the timeout. No manual intervention required.

Scoring Algorithm

Composite score (0.0-1.0) is calculated as:
score = (0.35 × successRate)
      + (0.15 × schemaRate)
      + (0.20 × qualityScoreAvg)
      + (0.15 × latencyScore)
      + (0.15 × priceScore)
      - (1.0 if circuitOpen else 0.0)
Penalties:
  • Circuit open: -1.0 (forces score to 0)
  • Policy violations: score set to 0.0

Environment Variables

X402_PROCUREMENT_MAX_CANDIDATES
number
default:"8"
Maximum candidates per request
X402_PROCUREMENT_ALLOWED_DOMAINS
string
Comma-separated domain allowlist
X402_PROCUREMENT_BLOCKED_DOMAINS
string
Comma-separated domain blocklist
X402_PROCUREMENT_NETWORK_ALLOWLIST
string
Comma-separated network allowlist (e.g., “eip155:8453,eip155:84532”)
X402_PROCUREMENT_PAYTO_ALLOWLIST
string
Comma-separated address allowlist
X402_PROCUREMENT_MAX_AMOUNT_ATOMIC
string
Global payment cap in atomic units
X402_PROCUREMENT_REQUIRE_HTTPS
boolean
default:"true"
Require HTTPS for all endpoints
X402_PROCUREMENT_REQUIRE_X402
boolean
default:"true"
Require 402 Payment Required status
X402_PROCUREMENT_MAX_ATTEMPTS
number
default:"3"
Default max retry attempts
X402_PROCUREMENT_CIRCUIT_FAIL_THRESHOLD
number
default:"3"
Consecutive failures to open circuit
X402_PROCUREMENT_CIRCUIT_OPEN_MS
number
default:"180000"
Circuit breaker timeout in milliseconds

Build docs developers (and LLMs) love