Building a Verification-of-Payee Routing and Verification Mechanism Connection

The Verification of Payee obligation is not “check the name on the account.” It is “reach every counterparty payment service provider in the euro area, get an answer in a few seconds, and behave sensibly when you cannot.” Those are different engineering problems, and the second one is where builds fail.

Since 9 October 2025, credit institutions in the euro area have had to offer Verification of Payee (VoP) on outgoing credit transfers, under Regulation (EU) 2024/886 — the Instant Payments Regulation, which amends the SEPA Regulation (EU) No 260/2012. The consumer-facing description is simple: before a payment goes out, the payer’s bank checks that the name they typed matches the name behind the IBAN they typed, and warns them if it does not. The build behind that is not simple, and the part most teams underestimate is reachability — how you actually get a request to a bank you have no relationship with, and what you do in the roughly one call in a thousand where the answer does not come back in time.

Why you connect to a routing mechanism, not to banks

There are thousands of PSPs reachable for SEPA. You are not going to integrate bilaterally with each one — the combinatorics are absurd and the operational surface is unmanageable. The European Payments Council’s VoP scheme solves this with an intermediary layer: a Routing and/or Verification Mechanism (RVM). You connect to an RVM; it accepts your VoP Request as a Requesting PSP, routes it to the correct Responding PSP, and returns that PSP’s VoP Response to you unaltered. Discovery of which endpoint serves which BIC is handled through the EPC Directory Service (EDS), which the RVMs maintain on behalf of the PSPs they serve.

Free · 4 minutes

If your most senior engineer left tomorrow, would anyone still understand the system?

Fourteen questions on documentation, dependencies, and the gap between how the architecture works and how many people know it. Banded finding on screen, full sheet by email.

The dependency-mapping consequence is the point most architecture reviews miss. Your VoP capability now depends on a specific RVM, on the EDS, and on the reachability of the far-side PSP or its RVM. That is three failure domains you do not own, sitting directly in the critical path of a payment. Treat the RVM connection the way you would treat any single third-party dependency in a real-time flow: with a defined latency budget, an explicit failure policy, and — where the volume and risk justify it — a second reachability path so one RVM outage does not take your VoP capability with it. Reachability is a design property, not a checkbox, and it is the same discipline that governs charging parity and reachability for SEPA Instant more broadly.

The contract you are actually building against

The inter-PSP interface is a JSON-over-HTTPS API defined in the EPC’s VoP scheme specifications. You POST a request carrying the payee IBAN and the name (or organisation identifier) the payer supplied; you receive a structured response. There are four outcomes you must handle, and your user interface and payment logic have to treat each differently:

  • Match — the name behind the IBAN matches. Proceed.
  • Close match — near enough that the far side returns the actual registered name so the payer can decide. Surface it; do not silently pass.
  • No match — the name does not correspond. Warn clearly; the payer chooses whether to continue.
  • Verification not possible — the check could not be performed (unsupported account, unreachable PSP, timeout). This is not a “no match”, and conflating the two is a defect.

The scheme rulebook expects a VoP response within roughly five seconds, and preferably within one. That sits inside the wider ten-second execution expectation the Instant Payments Regulation places on the transfer itself, so the check cannot spend the whole budget. The matching itself — how a Responding PSP decides match from close match — is a separate build with its own tuning; I have covered that in architecture for sub-five-second name matching. This piece is about the connection and what happens when it does not answer.

Designing the client for the latency budget

The client is small. Getting the timeout and fallback semantics right is the whole job. A hard per-request deadline well inside the rulebook target; a single, well-defined degraded outcome on any failure; and no exception path that lets a routing problem masquerade as a name mismatch.

import asyncio
import httpx

# Deadline held deliberately under the ~5s rulebook target so the
# surrounding credit transfer stays inside its 10s execution window.
VOP_DEADLINE_S = 3.0

async def verify_payee(client, base_url, payee_iban, payee_name):
    """Call the RVM and always return one of four outcomes.

    Any transport failure -> VERIFICATION_NOT_POSSIBLE.
    A routing fault must never be reported as NO_MATCH.
    """
    payload = {
        "payee": {"iban": payee_iban, "name": payee_name},
    }
    try:
        resp = await client.post(
            f"{base_url}/vop/v1/verifications",
            json=payload,
            timeout=VOP_DEADLINE_S,
        )
        resp.raise_for_status()
        return resp.json()["verificationResult"]  # MTCH | CMTC | NMTC
    except (httpx.TimeoutException, httpx.TransportError, httpx.HTTPStatusError):
        # Degraded, not a mismatch. The UI must let the payer decide.
        return "NOAP"  # verification not possible

async def verify_with_fallback(payee_iban, payee_name, primary, secondary=None):
    """Try the primary RVM; fall back to a second reachability path once."""
    async with httpx.AsyncClient() as client:
        result = await verify_payee(client, primary, payee_iban, payee_name)
        if result == "NOAP" and secondary:
            result = await verify_payee(client, secondary, payee_iban, payee_name)
        return result

Three decisions in that snippet carry the design. The deadline is a hard constant held below the rulebook figure, not a hopeful default. Every failure — timeout, transport error, an HTTP 5xx from the RVM — collapses to a single “not possible” outcome rather than leaking an exception upward. And the fallback is one bounded retry against a distinct path, not an unbounded loop that would blow the payment’s own execution window.

Fallback: what “unavailable” is allowed to mean

Here is the governance question the code cannot answer for you: when verification is not possible, do you let the payment proceed? The regulation requires you to offer the check and to warn the payer of a detected discrepancy; it does not require you to block a payment merely because the far side was unreachable. So “verification not possible” must lead to an honest message — we could not check this payee — and a payer decision, not a silent pass dressed up as a match and not a hard block that strands legitimate payments every time an RVM has a bad minute. That policy is a board-level risk decision about liability and customer outcome, and it belongs in writing, not in a developer’s default branch.

The same architectural instinct applies to the controls sitting alongside VoP. Instant payments forced firms to move screening off the per-transaction critical path, which is exactly the re-architecture behind sanctions screening rebuilt for instant payments. VoP is the same lesson from a different angle: anything you place in a real-time payment flow has to degrade to a defined state, fast, without breaking the outer clock.

What your risk function will ask to see

When the review comes — internal audit, a supervisor, or your own second line — the questions are concrete. Which RVM do you route through, and what is your contingency if it is down? What is your measured p99 VoP latency against the budget, and what proportion of requests return “not possible”? What does the payer see, precisely, on close match versus no match versus not possible? And what is the documented policy on proceeding when the check fails? A capability that cannot answer those is not a control; it is a feature that happens to call an API.

Euro-area firms are live with this now. The obligation reaches PSPs in non-euro member states in 2027, and the reachability and connection design does not get easier for arriving later — the same routing-mechanism dependency, the same latency budget, the same fallback question, covered in the 2027 non-euro deadlines and what they trigger. Build the connection so that the day an RVM goes dark, your payments keep moving and your payers keep being told the truth. Everything else about VoP is name matching; this is the part that decides whether the obligation survives a bad afternoon.

Build and rescue work

Hands-on delivery of this kind is handled by Sixteen Pillars Studio.

Free interactive tool

Website compliance checklist

What your site has to do, based on what it actually does

Answer as much or as little as you like — the list builds as you go. Nothing is stored against your name and no email is required.

Can you trust the architecture you have?

Architecture diagrams rarely show the reality of how systems actually operate. An independent review establishes what is really there.