Hoe u betalingen aan uw AI-agent toevoegt.
Maak een agent aan met createClient van @blockchain0x/node (of de Python-client), stuur een USDC-betaling met payments.create en verifieer de ondertekende webhook met webhooks.verify. Uitgavencontrole is ingesteld in het dashboard en alleen-lezen via de API. De agent raakt nooit rechtstreeks privé-sleutels aan. Minder dan tien minuten van aanmelding tot je eerste USDC-betaling op Base, in TypeScript of Python.
Voordat je begint.
- Een Blockchain0x-account (gratis aanmelding).
- Een API-sleutel van het dashboard (gebruik een
sk_test_sleutel voor deze gids; u schakelt later over naarsk_live_). - Node.js 20+ of Python 3.11+ in je agent-runtime.
- Een agent gebouwd op elk framework - LangChain, CrewAI, AutoGen, LlamaIndex, OpenAI Agents SDK, MCP of gewone SDK-code. De instructies zijn framework-onafhankelijk.
- Een HTTPS-eindpunt dat bereikbaar is vanaf het openbare internet om webhooks te ontvangen (ngrok of een implementatiepreview is prima voor ontwikkeling).
Maak het agentprofiel aan.
Het agentprofiel is de adresseerbare identiteit achter elke betaling die je agent verzendt of ontvangt. Het bevat het walletadres, de openbare pagina, de verificatiebadges en (later) het uitgavenbeleid. Maak er één per logische agent.
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.
Stuur een betaling.
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 transferVerwerk de webhook.
Webhooks zijn hoe je erachter komt dat een betaling is afgehandeld. In Node doet webhooks.verify van @blockchain0x/node de HMAC-controle en retourneert een gediscrimineerde unie; in andere talen bereken je dezelfde HMAC over de ruwe body. Vertak op het type gebeurtenis (payment.received voor inkomend), reageer snel met 2xx, en zet alles zwaarder achter de 2xx in de wachtrij zodat de levering niet tijdslimiet.
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)Stel uitgavencontroles in het dashboard in.
Als je agent alleen ontvangt, kun je dit overslaan. Als het ook betaalt, stel dan een uitgavenvergunning in - een toelage per periode en een limiet per transactie - in het dashboard. Dit wordt afgedwongen door de backend bij elke betaling, zodat het promptinjectie overleeft op een manier waarop regels aan de agentzijde dat nooit kunnen. Er is geen API- of SDK-aanroep die een vergunning wijzigt (de eigen sleutel van de agent kan zijn limiet niet verbreden); de API is alleen-lezen, zodat je code de huidige waarden kan ophalen om weer te geven of om plannen te maken.
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
}Test de hele flow op Base Sepolia.
Voordat u overschakelt naar sk_live_ sleutels, voert u het volledige pad end-to-end uit met sk_test_. Een testsleutel houdt alles op Base Sepolia, waar u de portemonnee financiert vanuit de openbare kraan en de responsvormen overeenkomen met live. De sleutelprefix kiest het netwerk, zodat een testsleutel geen mainnet-fondsen kan verplaatsen.
Oefen drie scenario's: een happy-path betaling die payment.received activeert, een gemiste levering (wijs de webhook naar een dode URL, en reconcilieer door de transactie op te halen met transactions.get), en een webhook-herhaling (geef de eerste keer een 500 terug, 200 de tweede keer, en bevestig dat je handler idempotent is). Wanneer alle drie de tests slagen, wissel de sleutel en verzend.
Vijf fouten die teams een week kosten.
Webhook-handtekeningverificatie overslaan
Als je enige POST naar /webhooks/payment als autoritatief accepteert, kan een aanvaller valse betalingsevents creëren en je agent misleiden om gratis werk te leveren. Verifieer altijd HMAC met het webhook-geheim, met een constante tijdsvergelijking. De eerste compromittering is bijna altijd de ontbrekende verificatie.
Uitgaande van een afzonderlijk bevestigingsevenement
De verzonden evenementen zijn payment.received, payment.sent, wallet.deployed, en webhook.test - er is geen apart bevestigingsevenement. payment.received wordt geactiveerd wanneer de overdracht in een blok is. Voor het meeste werk is dat jouw signaal om te leveren. Voor iets duur of onomkeerbaar, poll de transactie met transactions.get en pas jouw eigen bevestigingsdrempel toe voordat je handelt; wacht niet op een evenement dat niet bestaat.
Geen idempotentie op webhook handlers
Webhooks proberen opnieuw bij niet-2xx-responsen, en hetzelfde evenement zal meerdere keren aankomen onder belasting. Je handler moet idempotent zijn: houd een kleine tabel bij van evenement-ID's die je al hebt verwerkt en sla duplicaten over. Anders zal een tijdelijke blip hetzelfde werk twee keer leveren en zul je uren besteden aan het debuggen van dubbele vervullingen.
Test- en live API-sleutels mengen
Test-sleutels (sk_test_) raken de sandbox en gebruiken Base Sepolia; live-sleutels (sk_live_) raken productie en gebruiken Base mainnet. Het door elkaar halen in omgevingsconfiguraties is de oorzaak van de meeste 'werkt in dev, faalt in prod'-tickets. Hard-fail bij opstarten als je runtime-omgeving en sleutelvoorvoegsel niet overeenkomen.
Een ontbrekende webhook behandelen als een mislukte betaling
Er is geen foutevenement, en een webhook kan gemist worden (jouw eindpunt was offline, een levering werd gemist). Laat de agent niet vastzitten in een 'wachten op fondsen'-lus. Reconcilie: haal de transactie op met transactions.get om de werkelijke staat te leren, en zet een time-out op elke wachtende flow zodat een verlaten betaling vastgehouden middelen vrijgeeft in plaats van voor altijd vast te hangen.
Zodra je je eerste betaling hebt.
Met basisbetalingen die werken, zijn de vervolgacties die het meest opleveren uitgavencontroles (zodat de agent niet met het budget kan weglopen), webhook-robustheid (zodat betalingen niet stilletjes onder belasting verdwijnen), en identiteitsverificatie (zodat tegenpartijen de openbare pagina van de agent vertrouwen).
Stel agent uitgavencontroles in die prompt-injectie overleven
De webhook-patronen waar ontwikkelaars het meest naar vragen
Verdien de GitHub- en domeinverificatiebadges
Volledige API-referentie bevindt zich op docs.blockchain0x.com. Productoppervlak voor dezelfde API's: Betalings-API.