Verification webhooks are real-time notifications that tell your systems whether an IBAN and account holder name match, with a result state of match, close_match, no_match, or verification_not_possible. The integration rule that matters most: acknowledge the request instantly, hand the payload to a background worker, then let your accounts-payable policy decide what happens next. Pay on exact match. Hold or escalate everything else.
TL;DR:
- Webhook payloads must include at least nine core fields, including event type, verification ID, payee ID, and timestamp, to ensure reliable processing.
- Use a fast, 2xx acknowledgment to prevent retries and decouple receiving events from processing actions through durable queues.
- Verification results trigger specific policies: auto-pay for match, review for close match, block for no match, and retry or verify further if not possible.
- Always test webhook integrations by simulating each status and intentionally causing delivery failures before going live.
- Rely on webhooks as signals but maintain fallback methods, such as polling, to handle possible delivery failures and ensure process resilience.
Table of Contents
- What Does a Verification Webhook Actually Send You?
- How Do You Build a Reliable Webhook Listener?
- What AP Policy Should Govern Match, Close Match, and No Match?
- How Do You Test a Webhook Integration Before Going Live?
- Your Launch Checklist for Webhook-Driven Verification
- How Does Vopify Handle Real-Time Payee Verification?
- When Should You Trust Webhooks Alone, and When Do You Need a Fallback?
- Get Started With Vopify for Webhook-Driven Verification
- Sources
What Does a Verification Webhook Actually Send You?
A verification webhook is only as useful as the fields it carries. Skimpy payloads force finance teams to log into a dashboard and manually cross-reference every flagged transaction, which defeats the point of real-time notification in the first place.
At minimum, your payload needs nine fields: event_type, verification_id, payee_id, provided_name, verified_name, status, close_match_detail (or a confidence score), original_request_id, and timestamp. That last field matters more than people assume. Without it, you cannot detect out-of-order deliveries or prove to an auditor when a decision was made relative to when the payment cleared.
Here's how the four result states typically look in practice:
| Status | Key fields present | What it tells AP |
|---|---|---|
MATCH | verified_name equals provided_name | Safe to pay automatically |
CLOSE_MATCH | close_match_detail (e.g., "Middle initial differs") | Needs human eyes before release |
NO_MATCH | verified_name differs materially | Block payment, contact payee |
VERIFICATION_NOT_POSSIBLE | reason code (bank unreachable, account closed) | Retry later or request alternate proof |
A CLOSE_MATCH payload, for example, should include something like "closeMatchDetail": "Provided name omits middle name found on account" so a reviewer isn't guessing at what triggered the flag.
Once the payload lands, map it to three places: your verification history table (keyed by verification_id), your payee master record (update last_verified_status), and an audit log that never gets overwritten. Your review UI should surface provided name next to verified name, side by side, with the timestamp and confidence detail visible without a click.
How Do You Build a Reliable Webhook Listener?
The single biggest mistake teams make is trying to do everything inside the webhook request. Verification providers, payment platforms, and card networks all expect a fast response, and if your handler is busy writing to three databases and sending a Slack alert, you're going to get retried, duplicated, or timed out.
Here's the pattern that actually holds up in production:
- Acknowledge in under a second. Return a 2xx status the moment you've confirmed the payload is well-formed. Nothing else happens synchronously. Stripe's own integration guidance makes this the first rule for a reason: providers retry aggressively on timeout, and retries on top of retries are how duplicate ledger entries happen.
- Push to a durable queue. A message queue (SQS, RabbitMQ, or even a Postgres-backed job table) decouples receipt from processing. If a worker crashes mid-run, the event isn't lost.
- Check idempotency before you act. Key on the event ID, not the payee ID. Stripe's webhook documentation recommends this exact approach, and it's cheap to implement as a fast cache lookup or a database upsert with a unique constraint.
- Handle out-of-order delivery. Providers don't guarantee sequence. Store the event timestamp and compare it against your last recorded state for that payee before overwriting anything; a
NO_MATCHthat arrives after aMATCHwas already actioned needs a reconciliation step, not a silent overwrite. - Instrument everything. Track delivery latency, retry counts, and failure rates as first-class metrics, not an afterthought. A quiet drop in delivery volume is often the first sign something upstream broke.
Pro Tip: Set your idempotency cache TTL to match your realistic duplicate-delivery window, usually a few days, not indefinite. An unbounded cache just becomes a slow memory leak nobody notices until the bill arrives.
What AP Policy Should Govern Match, Close Match, and No Match?
A webhook only delivers information. Someone still has to decide what the business does with a close_match at 4:45 PM on a Friday before a payment run.
The default policy structure that works for most AP teams looks like this:
- MATCH: Auto-eligible for payment. No human touch required, and this should be the majority of your volume once your supplier data is clean.
- CLOSE_MATCH: Route to a review queue with the provided name, verified name, and the specific discrepancy detail displayed together. Verification-of-payee systems generally treat close matches as a policy decision, not a code decision, which means someone has to actually read the mismatch before releasing funds.
- NO_MATCH: Block the payment outright and trigger outreach to the payee for confirmation or corrected details.
- VERIFICATION_NOT_POSSIBLE: Treat as pending, not as a green light. Retry the check or ask for alternate proof before moving forward.
Set a review SLA deemed appropriate for your business context, and name who owns escalation when the reviewer is unsure. For batch payment runs, don't let a delayed webhook silently fall through the cracks: mark payees as pending verification and re-run eligibility checks right before the batch settles, rather than trusting a status that was current an hour ago but stale by settlement time.
How Do You Test a Webhook Integration Before Going Live?
Nobody should discover their retry logic is broken during a live payment run. Test it first, in a sandbox, with every failure mode you can think of.
- Simulate each status. Use your provider's sandbox or a mock-event generator to trigger
match,close_match,no_match, andverification_not_possibledeliberately. PayPal's developer documentation describes this pattern well, including the practice of posting the exact raw payload back to a verification endpoint rather than a re-serialized copy. - Break delivery on purpose. Kill a webhook mid-flight, send a duplicate, and deliver two events out of sequence. Confirm your system recovers by falling back to a direct GET request against the verification endpoint rather than freezing.
- Watch four numbers in production. Delivery rate, average processing time, duplicate count, and error rate. A sudden spike in
no_matchevents, more than your historical baseline, deserves an alert, not a shrug.
Build a synthetic test payee dataset with fabricated names and IBANs, and if you must use production data for staging, redact the personally identifiable fields first.
Your Launch Checklist for Webhook-Driven Verification
Getting from zero to a production integration doesn't take long if you work through it in order:
- Register your webhook URL and the event types you want in the provider dashboard, and save the subscription ID somewhere your team can find it.
- Design your database schema so every verification record links back to a
payee_id, with a full history table, not just a "latest status" field. - Build the fast acknowledgment endpoint, the durable queue, and the idempotency store before writing any AP-facing logic.
- Write down your AP policy in plain language, build the review UI, wire up monitoring, and run a sandbox pilot before touching real payments.
How Does Vopify Handle Real-Time Payee Verification?
Vopify was built around the exact pattern this guide describes: instant name-and-IBAN matching that returns a result fast enough to slot into a webhook-driven workflow instead of forcing a manual lookup. The platform handles payee verifications with low latency, making real-time AP decisioning practical rather than aspirational.
For teams mapping Vopify into the patterns above:
- Single checks and bulk CSV uploads both feed into the same dashboard, so you're not maintaining two separate review paths for individual versus batch verification.
- Result states map directly onto the payload structure covered earlier, matching, close matching, and failing, which means your existing schema design doesn't need special-casing for Vopify specifically.
- Coverage spans SEPA countries plus India, Indonesia, South Korea, and Alipay accounts in China, detailed on the coverage page, which matters when you're deciding whether your webhook listener needs to handle multiple regional response formats.
- API access for high-volume programmatic verification is planned, giving developer teams a path beyond dashboard-only workflows once volume justifies it.
Close-match handling deserves special attention here: Vopify's approach to name matching is built to surface exactly the kind of discrepancy detail your review queue needs, rather than a bare pass/fail flag.
When Should You Trust Webhooks Alone, and When Do You Need a Fallback?

Webhook-first is the right default for most payment teams, but I'd push back on anyone treating a webhook delivery as gospel. Providers themselves frame it this way: verification results are best-effort signals, not guaranteed transmissions, so keeping a polling fallback for anything above a modest payment threshold isn't paranoia. It's basic resilience.
The organizations that get burned aren't the ones with bad code. They're the ones who never wrote down what a reviewer should do with a close_match, so three different AP staffers handle it three different ways. Document the policy, train reviewers on real examples, and set an SLA before your first live payment run, not after your first incident.
— David
Get Started With Vopify for Webhook-Driven Verification
If you're ready to move past manual lookups, the pilot path is short. Create a Vopify account, register your webhook endpoint, and run a batch of sandbox or mock events through each result state before touching a real supplier list.

From there, pilot on a small cohort, ten to twenty suppliers is enough to validate your review workflow without risking meaningful payment volume. You'll see the same sub-two-second response times and payload structure covered throughout this guide, whether you're checking one payee through the dashboard or running a bulk IBAN verification against a full supplier file. Check the coverage page to confirm your payee geography is supported, then head to Vopify to create your account and start the pilot.
Sources
- Building solid Stripe integrations — developers guide
- Stripe webhooks (docs)
- Verification of payee (Yapily docs)
- PayPal REST webhooks developer docs
