Come aggiungere pagamenti al tuo agente AI.
Crea un agente con createClient da @blockchain0x/node (o il client Python), invia un pagamento USDC con payments.create e verifica il webhook firmato con webhooks.verify. I controlli di spesa sono impostati nel dashboard e in sola lettura tramite l'API. L'agente non tocca mai direttamente le chiavi private. Meno di dieci minuti dall'iscrizione al tuo primo pagamento USDC su Base, in TypeScript o Python.
Prima di iniziare.
- Un account Blockchain0x (registrazione gratuita).
- Una chiave API dal dashboard (usa una chiave
sk_test_per questa guida; passerai ask_live_più tardi). - Node.js 20+ o Python 3.11+ nel runtime del tuo agente.
- Un agente costruito su qualsiasi framework - LangChain, CrewAI, AutoGen, LlamaIndex, OpenAI Agents SDK, MCP, o codice SDK semplice. Le istruzioni sono indipendenti dal framework.
- Un endpoint HTTPS raggiungibile da Internet pubblico per ricevere webhook (ngrok o un'anteprima di distribuzione va bene per lo sviluppo).
Crea il profilo dell'agente.
Il profilo dell'agente è l'identità indirizzabile dietro ogni pagamento che il tuo agente invia o riceve. Contiene l'indirizzo del wallet, la pagina pubblica, i badge di verifica e (in seguito) la politica di spesa. Creane uno per ogni agente logico.
import { createClient } from "@blockchain0x/node";
const client = createClient({ apiKey: process.env.BLOCKCHAIN0X_API_KEY! }); // sk_test_ / sk_live_
const agent = await client.agents.create({ name: "research-bot" });
console.log(agent.id); // "agt_..."
// Public page: https://wallet.blockchain0x.com/a/{slug}from blockchain0x import Client
client = Client() # reads BLOCKCHAIN0X_API_KEY from the environment
agent = client.agents.create(body={"name": "research-bot"})
print(agent["id"]) # "agt_..."
# Public page: https://wallet.blockchain0x.com/a/{slug}After this call, the agent has a public page at https://wallet.blockchain0x.com/a/<slug> that any counterparty (human or agent) can hover for verification info. See the agent payment identity glossary entry for what that page exposes.
Invia un pagamento.
payments.create sends USDC from the agent wallet. amountWei is base units (USDC has 6 decimals), so 0.01 USDC is the string "10000". The SDK auto-stamps an Idempotency-Key, and the call can return 503 until the chain adapter is wired for your network. To RECEIVE instead, settle an invoice you created in the dashboard with paymentRequests.settle - see the payment API page.
// Send a USDC payment from the agent wallet. amountWei is base units
// (USDC has 6 decimals): "10000" is 0.01 USDC. payments.create auto-stamps an
// Idempotency-Key and can return 503 until the chain adapter is wired.
const tx = await client.payments.create({
agentId: agent.id,
to: "0xRecipient",
amountWei: "10000",
});
console.log(tx); // the submitted transfer# amountWei is USDC base units (6 decimals): "10000" is 0.01 USDC.
tx = client.payments.create(body={
"agentId": agent["id"],
"to": "0xRecipient",
"amountWei": "10000",
})
print(tx) # the submitted transferGestisci il webhook.
I webhook sono come scopri che un pagamento è stato regolato. In Node, webhooks.verify da @blockchain0x/node esegue il controllo HMAC e restituisce un'unione discriminata; in altre lingue, calcola lo stesso HMAC sul corpo grezzo. Dirama in base al tipo di evento (payment.received per in entrata), rispondi rapidamente con 2xx e metti in coda qualsiasi cosa più pesante dietro il 2xx in modo che la consegna non scada.
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 });
if (result.eventType === "payment.received") {
// USDC landed - deliver the work, fulfil the order, etc.
void deliver(result.eventId);
}
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 webhook():
raw = request.get_data() # RAW bytes - do not parse first
sig = request.headers.get("X-Blockchain0x-Signature", "")
ts = request.headers.get("X-Blockchain0x-Timestamp", "")
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)
if request.headers.get("X-Blockchain0x-Event-Type") == "payment.received":
deliver(request.get_json()) # USDC landed
return ("ok", 200)Imposta i controlli di spesa nel dashboard.
Se il tuo agente riceve solo, puoi saltare questo. Se paga anche, imposta un permesso di spesa - un'assegnazione per periodo e un limite per transazione - nella dashboard. Viene applicato dal backend su ogni pagamento, quindi resiste all'iniezione di prompt in un modo che le regole lato agente non possono mai fare. Non c'è nessuna chiamata API o SDK che modifica un permesso (la chiave del agente non può ampliare il suo limite); l'API è di sola lettura, quindi il tuo codice può recuperare i valori correnti da visualizzare o pianificare.
curl https://api.blockchain0x.com/v1/agents/agt_123/spend-permissions \
-H "Authorization: Bearer $BLOCKCHAIN0X_API_KEY"{
"allowance_wei": "5000000",
"per_tx_wei": "1000000",
"period_seconds": 86400,
"revoked_at": null
}Testa l'intero flusso su Base Sepolia.
Prima di passare a sk_live_ chiavi, esegui l'intero percorso end-to-end con sk_test_. Una chiave di test mantiene tutto su Base Sepolia, dove finanzi il portafoglio dal rubinetto pubblico e le forme di risposta corrispondono a quelle live. Il prefisso della chiave sceglie la rete, quindi una chiave di test non può muovere fondi di mainnet.
Esercita tre scenari: un pagamento a percorso felice che attiva payment.received, una consegna mancata (puntare il webhook a un URL non funzionante, quindi riconciliare recuperando la transazione con transactions.get), e un tentativo di webhook (restituire un 500 la prima volta, 200 la seconda, e confermare che il tuo gestore è idempotente). Quando tutti e tre superano il test, scambia la chiave e spediscila.
Cinque errori che costano una settimana ai team.
Saltando la verifica della firma del webhook
Se accetti qualsiasi POST a /webhooks/payment come autorevole, un attaccante può generare eventi di pagamento falsi e ingannare il tuo agente per consegnare lavoro gratuitamente. Verifica sempre con HMAC il segreto del webhook, utilizzando un confronto a tempo costante. Il primo compromesso è quasi sempre la mancanza di verifica.
Assumendo un evento di conferma separato
Gli eventi forniti sono payment.received, payment.sent, wallet.deployed e webhook.test - non esiste un evento di conferma separato. payment.received si attiva quando il trasferimento è in un blocco. Per la maggior parte del lavoro, questo è il tuo segnale per consegnare. Per qualcosa di costoso o irreversibile, interroga la transazione con transactions.get e applica la tua soglia di conferma prima di agire; non aspettare un evento che non esiste.
Nessuna idempotenza sui gestori webhook
I webhooks riprovano su risposte non 2xx, e lo stesso evento arriverà più volte sotto carico. Il tuo gestore deve essere idempotente: mantieni una piccola tabella degli ID degli eventi che hai già elaborato e salta i duplicati. Altrimenti, un'improvvisa interruzione consegnerà lo stesso lavoro due volte e passerai ore a debugare doppie soddisfazioni.
Mescolare chiavi API di test e live
Le chiavi di test (sk_test_) colpiscono la sandbox e utilizzano Base Sepolia; le chiavi live (sk_live_) colpiscono la produzione e utilizzano Base mainnet. Mescolare le configurazioni ambientali è la causa della maggior parte dei ticket 'funziona in dev, fallisce in prod'. Fallimento immediato all'avvio se l'ambiente di runtime e il prefisso della chiave non corrispondono.
Trattare un webhook mancante come un pagamento fallito
Non esiste un evento di fallimento, e un webhook può essere perso (il tuo endpoint era inattivo, una consegna è stata persa). Non lasciare l'agente bloccato in un ciclo di 'attesa di fondi'. Riconcilia: recupera la transazione con transactions.get per conoscere il vero stato e metti un timeout su qualsiasi flusso in attesa in modo che un pagamento abbandonato rilasci le risorse trattenute invece di rimanere bloccato per sempre.
Una volta che hai il tuo primo pagamento.
Con i pagamenti di base funzionanti, i seguiti che rendono di più sono i controlli di spesa (così l'agente non può scappare con il budget), la robustezza dei webhook (così i pagamenti non vengono silenziosamente persi sotto carico) e la verifica dell'identità (così le controparti si fidano della pagina pubblica dell'agente).
Imposta controlli di spesa per l'agente che sopravvivono all'iniezione di prompt
I modelli di webhook di cui i programmatori chiedono di più
Guadagna i badge di verifica di GitHub e del dominio
Il riferimento completo dell'API si trova su docs.blockchain0x.com. Superficie di prodotto per le stesse API: Payment API.