The problem
You need to know when your agent's payments happen, when a payment lands in an agent's wallet, or when an agent makes one, so you can record it, react to it, or reconcile your books. But you have no reliable signal. Maybe you are polling and it feels wrong, maybe you set up a webhook but the events are not arriving or your verification keeps failing, or maybe you simply do not know how to wire payment notifications at all. Either way, payments are happening and your system is not learning about them cleanly.
This is the payment-webhook problem. The underlying need is a reliable, durable notification of payment events, and the friction is either not having one or having one that does not work. The symptom is uncertainty about payments, you cannot trust that you will hear about every settled payment, which undermines tracking, confirmation, and reconciliation. The fix is to set up the webhook correctly, with proper verification, so every payment event reaches you and you can trust it.
Why webhooks, not polling
Before the fix, it is worth saying why a webhook is the right tool rather than polling. Polling, repeatedly asking whether a payment happened, is wasteful and laggy: you either poll too often, burning calls, or too rarely, missing the moment, and there is no single list-all-transactions endpoint to poll anyway. Webhooks invert this: the platform pushes an event to your endpoint when a payment settles, so you learn about it promptly without asking, and you build your record from the stream.
This makes webhooks the backbone of payment handling for agents. They are how you durably know what settled, which underpins confirming payments, tracking spend, and reconciling revenue. A correctly wired webhook means every settled payment produces an event you receive, which is exactly the reliable signal the problem is missing. So the fix is not to poll harder but to set up webhooks properly, and the rest of this page is how to do that.
The fix
The fix is to create a webhook, subscribe to the payment events, and verify each delivery. Create a webhook pointing at your endpoint, and listen for payment.received, fired when a payment settles to an agent, and payment.sent, fired when an agent makes a payment. When a payment settles, your endpoint receives a delivery describing it. Before trusting that delivery, verify it with webhooks.verify, passing the request headers, the raw body, and your signing secret.
Verification is what makes the events trustworthy: it confirms the delivery genuinely came from the platform and was not forged or tampered with. With creation plus subscription plus verification in place, you have a reliable, secure stream of payment events, which is the durable signal you needed. The fix is precisely this trio, and getting the verification right, against the raw body, within the replay window, is the part that most often trips people up, covered next. Building a transaction record on this stream is in how-to-track-ai-agent-transactions.
How to set it up
Setting it up has a clear shape. First, create the webhook and store the signing secret it gives you. Second, expose a reachable HTTPS endpoint that accepts the delivery. Third, in your handler, verify before processing:
import { createClient } from "@blockchain0x/node";
const sdk = createClient({ apiKey: process.env.B0X_API_KEY! });
// In your endpoint handler, capture the RAW body (not parsed JSON):
const ok = sdk.webhooks.verify({ headers, rawBody, secret: process.env.WEBHOOK_SECRET! });
if (!ok) return reply.code(400).send(); // reject unverified
// Now trust the event: payment.received / payment.sent, etc.The signature is an HMAC-SHA256 over the timestamp and the raw body, delivered in the X-Blockchain0x-Signature header, and verification enforces a roughly 300-second replay window. Capture the raw body exactly as received before any JSON parsing, since that is what the signature is computed over. Once verification passes, handle the event, recording the payment, reacting, or reconciling. That is the full setup: create, expose, verify, handle.
Common pitfalls
A few pitfalls cause most webhook problems, so address them directly. The biggest is verifying against parsed JSON instead of the raw body. The signature is over the exact bytes delivered, so if your framework parses the body and you re-serialize it to verify, the bytes differ and verification fails even though the delivery is genuine. Capture and verify the raw body. A second pitfall is the wrong signing secret, double-check you are using the secret for this webhook, and rotate it with rotateSecret if it may be exposed.
A third is the replay window: deliveries outside roughly 300 seconds are rejected, so process promptly and do not depend on handling very delayed events. A fourth is an unreachable or slow endpoint, if your endpoint is down or too slow, deliveries fail, so keep it reachable and respond quickly, doing heavy work asynchronously after acknowledging. Getting these four right, raw body, correct secret, replay window, reachable endpoint, resolves the large majority of payment-webhook issues, including the not-verifying case in ai-agent-payment-not-confirming.
Test it
Do not wait for a real payment to find out your webhook works. Send a test event, the webhook.test event exists for this, and confirm your endpoint receives it and verification passes. That exercises the whole path, delivery, raw-body capture, signature verification, before any money is involved, so you catch a misconfiguration early rather than missing a real payment.
Test the failure path too: send a deliberately bad signature and confirm your handler rejects it, so you know verification is actually gating and not silently accepting everything. Once a test event verifies and a bad one is rejected, your webhook is correctly set up, and you can trust that real payment.received and payment.sent events will arrive and be handled. Testing this way turns webhook setup from a hope-it-works into a verified-it-works, which is what you want for the backbone of payment handling.
Handle deliveries idempotently
One more practice makes a payment webhook dependable: handle deliveries idempotently. A webhook may be delivered more than once, on a retry after your endpoint was briefly slow, for example, so your handler should be safe to run twice for the same event without double-counting a payment. Key your processing on the event's identifier and ignore an event you have already recorded, so a duplicate delivery is harmless.
This matters because payment events drive your records, and double-counting a payment, recording the same settlement twice, corrupts your accounting and any logic that reacts to it. Idempotent handling, recognize and skip duplicates, makes the stream reliable even when deliveries repeat. Combined with verifying the signature and acknowledging quickly, it gives you a webhook that is both secure and dependable: each genuine payment is recorded exactly once, no matter how the network behaves. Build the dedupe in from the start, because retrofitting it after a double-count incident is harder than designing your handler to be idempotent up front.
Related reading
If you need to handle agent payment webhooks, the adjacent material completes the picture. Building a durable transaction record from the event stream is in how-to-track-ai-agent-transactions, and the related not-confirming problem, often a webhook issue, is in ai-agent-payment-not-confirming. Together they take you from no reliable payment signal to a verified, trusted webhook stream. Pricing is on the pricing page.