为 AI 代理代码设计的支付 API。
一个小型 REST API。签名 webhook。五种语言的官方 SDK。构建以便您的代理可以发送和结算 USDC,并在几行代码中验证付款。

Blockchain0x API 故意设计得很小。我们不希望您花一个小时阅读文档来进行第一次支付。我们希望您复制一段代码,粘贴您的 API 密钥,然后运行它。
一个小型表面,为代理代码构建。
支付形状的路由如下。Webhook、api-keys 和只读支出权限完善了表面;SDK 包装了所有内容。
/v1/payments从代理钱包发送 USDC 支付/v1/transactions/{id}获取交易的状态和哈希/v1/payment-requests/{id}/settle使用链上证明结算发票/v1/agents/{id}获取代理钱包/v1/agents创建一个代理钱包全部使用HMAC-SHA256签名。
签名在 X-Blockchain0x-Signature 头部。重放窗口为 5 分钟。每个 POST 上的幂等性密钥。
payment.receivedUSDC 已到账您的一个代理钱包
payment.sent来自您代理的出站支付在链上结算
wallet.deployed代理的智能钱包已部署
webhook.test您从仪表板触发的测试交付
从您的代理钱包发送 USDC。
from blockchain0x import Client
client = Client(api_key="sk_test_...") # sk_test_ testnet, sk_live_ mainnet
tx = client.payments.create(body={
"agentId": "agt_123",
"to": "0xRecipient",
"amountWei": "10000", # USDC base units (6 decimals): 0.01 USDC
})
print(tx) # may return 503 until the chain adapter is wired for your networkTypeScript 和 Python 的类型化客户端。
npm install @blockchain0x/node与 Node 18+ 兼容。原生 TypeScript 类型。
pip install blockchain0xPython 3.9+。同步和异步客户端。
SDK 包装的请求主体。
这些是每条路由的验证输入。响应在这里简要显示;完整的类型形状在 SDK 和 API 参考中。金额为 USDC 基础单位(6 位小数)。
/v1/payments发送 USDC 支付 (payments.create)。amountWei 是 USDC 基本单位(6 位小数)。在链适配器连接之前可能会返回 503。
{
"agentId": "agt_123",
"to": "0xRecipient",
"amountWei": "10000",
"metadata": { "reason": "Research report" }
}{
"txHash": "0xff5...e12"
}/v1/payment-requests/{id}/settle结算在仪表板中创建的支付请求(发票),并提供链上证明 (paymentRequests.settle)。没有创建路由 - 仅结算。
{
"txHash": "0xff5...e12",
"payerAddress": "0xBuyer...",
"amountUsdcVerified": "0.10"
}{
"txHash": "0xff5...e12"
}/v1/transactions/{id}按 ID 获取单个交易(transactions.get)。
(no body){
"id": "tx_01J9...",
"txHash": "0xff5...e12"
}/v1/agents/{id}获取代理钱包 (agents.get)。其公共页面位于 wallet.blockchain0x.com/a/{slug}。
(no body){
"id": "agt_01J9QKE...",
"name": "research-bot",
"public_url": "https://wallet.blockchain0x.com/a/research-bot"
}/v1/agents/{id}/spend-permissions读取代理的支出权限。通过 API 只读 - 创建和更改仅限于仪表板。
(no body){
"allowance_wei": "5000000",
"per_tx_wei": "1000000",
"period_seconds": 86400,
"start_at": "2026-05-15T00:00:00Z",
"revoked_at": null
}在信任负载之前,请始终验证签名。
任何人都可以向您的回调URL发送POST请求。签名证明事件确实来自我们。
每个交付都带有一个 X-Blockchain0x-Signature 头部 (t=<unix>,v1=<hex>) - 对字符串 `${t}.${rawBody}` 使用您的 webhook 密钥进行 HMAC-SHA256,处于 5 分钟的重放窗口内。在 Node 中,来自 @blockchain0x/node 的 webhooks.verify 完成此操作并返回您分支的区分联合。在其他语言中,计算相同的 HMAC 并以恒定时间进行比较。读取原始主体,而不是解析的副本 - 重新序列化会破坏签名。
import express from "express";
import { webhooks } from "@blockchain0x/node";
const app = express();
// Capture the RAW body. The HMAC is over the exact bytes on the wire.
app.use(express.raw({ type: "application/json" }));
app.post("/webhooks/payment", (req, res) => {
const result = webhooks.verify({
headers: req.headers,
rawBody: req.body, // Buffer, raw bytes
secret: process.env.BLOCKCHAIN0X_WEBHOOK_SECRET!,
});
if (!result.ok) return res.status(400).json({ code: result.code });
// result.eventType is "payment.received" | "payment.sent" | ...
handleEvent(result);
res.status(200).send("ok");
});import hmac, hashlib, os, time
from flask import Flask, request, abort
app = Flask(__name__)
SECRET = os.environ["BLOCKCHAIN0X_WEBHOOK_SECRET"].encode()
@app.post("/webhooks/payment")
def receive():
raw = request.get_data() # RAW bytes - do not parse first
sig = request.headers.get("X-Blockchain0x-Signature", "")
ts = request.headers.get("X-Blockchain0x-Timestamp", "")
# Header is "t=<unix>,v1=<hex>"; some proxies send bare hex + the ts header.
parts = dict(p.split("=", 1) for p in sig.split(",") if "=" in p)
t, v1 = parts.get("t", ts), parts.get("v1", sig)
want = hmac.new(SECRET, t.encode() + b"." + raw, hashlib.sha256).hexdigest()
if not hmac.compare_digest(want, v1) or abs(time.time() - int(t)) > 300:
abort(401)
handle_event(request.headers.get("X-Blockchain0x-Event-Type"), request.get_json())
return "ok", 200webhook secret 会在你创建或轮换 webhook(webhooks.rotateSecret)时仅返回一次,而 BLOCKCHAIN0X_WEBHOOK_SECRET 就是你的 handler 读取它的位置。轮换会使旧 secret 失效,因此需要协调发布流程:先将新 secret 写入服务器环境变量,部署,然后再轮换。已提供的事件包括 payment.received、payment.sent、wallet.deployed 和 webhook.test - 请按 event type 分支处理,其余忽略。
安全重试。API 不会重复支付。
代理代码重试。网络断开连接。LLM决定调用工具两次。为了确保安全,发送一个Idempotency-Key POST 上的头部。SDK 中的 payments.create 为您自动铸造一个稳定的,因此重试的调用会合并为单个链上提交,而不是支付两次。当您希望在进程之间去重相同的逻辑操作时,请用您自己的密钥覆盖它。
curl -X POST https://api.blockchain0x.com/v1/payments \
-H "Authorization: Bearer $BLOCKCHAIN0X_API_KEY" \
-H "Idempotency-Key: 8e2c3a40-pay-vendor-once" \
-H "Content-Type: application/json" \
-d '{ "agentId": "agt_123", "to": "0xRecipient", "amountWei": "10000" }'- 首次调用: 提交支付,返回交易。
- 使用相同的密钥重试: 合并为一次链上提交,而不是重复支付。
- SDK 处理它: payments.create 自动铸造一个稳定的 Idempotency-Key,因此重试调用开箱即用是安全的。
- 覆盖它: 在您想要跨进程去重相同逻辑操作时传递您自己的密钥。
推荐的模式是在您的代理代码中为每个逻辑操作生成一个 UUID(例如,每个“为订单 Y 向供应商 X 付款”生成一个 UUID),并在重试期间重用它,直到操作成功。如果您未指定,官方 SDK 会为 payments.create 自动生成一个。
从响应中读取您的限制,而不是表格。
限制与您的计划规模相符。与其硬编码漂移的数字,不如每个响应告诉您当前状态,SDK会为您处理回退。
每个成功响应的头部
X-RateLimit-Limit: 您计划的稳定费率X-RateLimit-Remaining: 在此窗口中剩余多少次调用X-RateLimit-Reset: 窗口重置时的unix秒数
当您达到上限时 (HTTP 429)
- 响应包括
Retry-After以秒为单位 - 官方 SDK 在 429 和 5xx 上重试,采用指数退避,遵循 Retry-After
- 大多数代码从不手动处理429,因为SDK已经处理了。
流利地使用x402。没有它也能工作。
x402 是开放的 HTTP 原生支付协议。前提是:任何返回 402 Payment Required 的 API 都可以在响应中宣传支付要求,任何理解规范的客户端都可以支付和重试 - 无需注册,无需 API 密钥,无需带外协商。Blockchain0x 提供真实的 x402 包:一个支付端客户端和接收端服务器适配器。今天唯一的方案是在 Base 上的 exact-usdc。
HTTP/1.1 402 Payment Required
Content-Type: application/json
{
"version": 1,
"resource": "https://api.example.com/paid-endpoint",
"accepts": [
{ "scheme": "exact-usdc", "network": "eip155:8453" }
]
}代理调用者执行的操作
- 读取 402 body:version 1、resource,以及非空的 payment requirements accepts[](scheme exact-usdc,Base 的 network eip155:8453)。
- 构建一笔支付,并使用 X-Payment: exact-usdc:<base64(json)> 标头重新发送请求。
- 在支付侧,来自 @blockchain0x/x402 的 createX402Client({ sdk }) 会为您完成这些工作 - 它会自动响应 402。
- 你的服务器验证 X-Payment header 并完成原始请求。
双方,真实的包
在支付方面,createX402Client({ sdk }) 来自 @blockchain0x/x402 的封装 fetch 并自动回答 402。在接收端,createX402Plugin (Fastify) 和 createX402Middleware (Express) 自定义您的端点。或者跳过 x402,直接使用 REST API - 这两者可以组合,因此您可以在准备好时添加 x402。