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 to perform: set, clear, or status
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
Human-readable intent label (e.g., “fetch-oracle-price”, “query-chain-data”)
Array of candidate x402 endpoints
Unique identifier for this provider
HTTP method (GET, POST, PUT, PATCH, DELETE). Default: GET
Request body for POST/PUT/PATCH requests
Custom request headers (payment headers are auto-added)
Maximum payment in atomic units (e.g., “10000” = $0.01 USDC)
Expected response fields for schema validation
Optional policy constraints
Domain allowlist (e.g., [“example.com”, “trusted.io”])
Maximum payment cap (overrides candidate limits)
Require HTTPS (default: true, except localhost)
Require 402 Payment Required status (default: true)
Allowed payment networks (e.g., [“eip155:8453”])
Allowed payment recipient addresses
Max retry attempts (1-10, default: 3)
{
"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
Whether the request succeeded
Echo of the request intent
The highest-scoring allowed candidate (null if none passed)
All candidates sorted by score (highest first)
Whether this candidate passed policy checks
Composite quality score (0.0-1.0)
Policy rejection reasons (empty if allowed)
Historical performance metrics
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
Whether execution succeeded
Full ranking results (same as /rank endpoint)
The candidate that was executed
Execution receipt with payment and performance data
Candidate ID that was executed
HTTP response status code
Amount paid in atomic units (e.g., “10000” = $0.01)
SHA-256 hash of response body
Round-trip time in milliseconds
Whether HTTP status was 2xx
Whether response matched expectedFields
Blockchain transaction hash (if found in response)
Payment recipient address
Which attempt succeeded (1-based)
Error message (null if success)
The actual API response data
Whether response matched expected schema
HTTP response status code
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
All tracked providers with performance metrics
Recent execution receipts (last 100)
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:
- Consecutive failures >=
X402_PROCUREMENT_CIRCUIT_FAIL_THRESHOLD (default: 3)
- Circuit opens for
X402_PROCUREMENT_CIRCUIT_OPEN_MS (default: 180000ms = 3 minutes)
- 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
Maximum candidates per request
X402_PROCUREMENT_ALLOWED_DOMAINS
Comma-separated domain allowlist
X402_PROCUREMENT_BLOCKED_DOMAINS
Comma-separated domain blocklist
X402_PROCUREMENT_NETWORK_ALLOWLIST
Comma-separated network allowlist (e.g., “eip155:8453,eip155:84532”)
X402_PROCUREMENT_PAYTO_ALLOWLIST
Comma-separated address allowlist
X402_PROCUREMENT_MAX_AMOUNT_ATOMIC
Global payment cap in atomic units
X402_PROCUREMENT_REQUIRE_HTTPS
Require HTTPS for all endpoints
X402_PROCUREMENT_REQUIRE_X402
Require 402 Payment Required status
X402_PROCUREMENT_MAX_ATTEMPTS
Default max retry attempts
X402_PROCUREMENT_CIRCUIT_FAIL_THRESHOLD
Consecutive failures to open circuit
X402_PROCUREMENT_CIRCUIT_OPEN_MS
Circuit breaker timeout in milliseconds