Pre-flight a bank transfer before an agent sends it

IBAN validity, bank and BIC, SEPA reachability, sanctions on the bank, its jurisdiction and the beneficiary name — one call, one verdict, and the reason behind it.

By Matthias Begot · · Updated

An agent about to move money has to clear four separate questions before it builds the payment instruction: is this IBAN real, which bank is behind it and can that bank actually be reached on the scheme I intend to use, is the bank or its country under sanctions, and is the beneficiary name on a designation list. GET /preflight/payment answers all four in one call and returns one verdictok, review, stop or insufficient_coverage — with every reason attached to the block and the dated source it came from. The rule that makes the verdict worth reading is the same one that governs its counterparty sibling: ok is impossible while any block is short of coverage. A check that did not happen never passes.

The question your bank’s Verification of Payee does not answer

Since 9 October 2025, payment service providers in euro-area member states must offer Verification of Payee free of charge on euro credit transfers, instant and standard alike, telling the payer whether the payee name matches the IBAN before the transfer is authorised (European Commission); PSPs outside the euro area follow in July 2027. That is a real improvement, and it makes one specific failure mode — a correct-looking name pointed at somebody else’s account — much harder.

It is also a different question from this one. VoP asks does this account belong to the party you named. It does not ask should you be sending money to that party at all, and it happens at the very end of the flow, inside your bank, after the agent has already decided who to pay. A designated entity that gives you its own genuine IBAN passes VoP cleanly.

The scale of what sits behind that gap is not speculative. Payment fraud across the EEA reached €4.2 billion in 2024, of which €2.2 billion on credit transfers, up 16% year on year — and payment service users, not their banks, bore roughly 85% of credit-transfer fraud losses, “mainly as a result of scams that tricked users into initiating fraudulent transactions” (joint EBA–ECB report on payment fraud, 15 December 2025). Those are authorised transfers. The control that would have caught them belongs before the instruction exists — which is exactly where an autonomous agent operates, and exactly where a pre-flight call fits.

One call, three checks, and the part you would otherwise write yourself

The endpoint runs the work of GET /iban/resolve, GET /iban/screen and GET /screen/entity in one round-trip and one x402 settlement. Each block keeps the exact shape of its standalone endpoint — nothing flattened, nothing summarised away — so the composite adds information rather than replacing it.

What it adds is the piece you would otherwise have to write and keep correct: the decision table that turns three independent answers into one verdict, including an explicit rule for what happens when a check could not run. The verdict is always exactly the maximum severity among the listed reasons, and every reason carries its block, a stable code from a closed set of ten, and its own severity. An agent can therefore recompute the verdict from the blocks instead of trusting it.

verdictWhat it means
stopInvalid IBAN, sanctioned bank or BIC, embargoed jurisdiction, or a hit on the beneficiary name
reviewBank unknown in a complete national registry, high-risk or monitored jurisdiction, or a weak name match
insufficient_coverageNo signal — but a check did not happen
okEvery check ran, and none of them raised a signal

A clean account at a clean bank can still be a stop

The case worth internalising is the one where the two easy checks pass and the transfer is still refused. Abridged from the production capture on the doc page:

{
  "verdict": "stop",
  "verdict_reasons": [
    { "block": "name_screening", "code": "NAME_HIT", "severity": "stop",
      "detail": "the beneficiary name matches a designated entity" }
  ],
  "iban": {
    "valid": true, "country": "DE", "coverage": "full",
    "bank": { "name": "Commerzbank", "bic": "COBADEFFXXX" }, "reachable": true
  },
  "bank_screening": {
    "coverage": "screened",
    "screening": { "risk": "clear", "bank_sanctioned": false,
                   "jurisdiction": { "level": "clear", "lists": [] }, "hits": [] }
  },
  "name_screening": {
    "coverage": "screened",
    "screening": {
      "verdict": "hit", "verdict_basis": ["exact", "exact_alias"],
      "hits": [
        { "id": "OFAC-SDN:25684", "list_source": "OFAC-SDN",
          "matched_name": "EUROPAISCH-IRANISCHE HANDELSBANK AG",
          "match_type": "exact", "programs": ["IFSR", "IRAN", "NPWMD"],
          "listed_on": "2018-11-05" },
        { "id": "EU:EU.13742.32", "list_source": "EU-FSF",
          "matched_name": "Europäisch-Iranische Handelsbank",
          "match_type": "exact_alias", "programs": ["IRN"],
          "listed_on": "2025-09-29" }
      ]
    }
  }
}

A valid German IBAN, a large clean bank, full registry coverage — and a stop on the beneficiary alone, sourced to two lists with their programmes and designation dates. Note that the two blocks that passed are still returned in full: the verdict never erases the evidence it was computed from.

Two distinctions that a naive aggregator collapses

A gap is not a pass. Omitting beneficiary_name is allowed, and it forbids ok — the name block comes back not_requested, which is a coverage gap, not a clearance. An ok there would read as a green light on a beneficiary nobody looked at. The same applies to an IBAN whose country no registry covers: the bank block is insufficient_coverage, its risk is "unknown", and unknown must never be read as clear. Absence of a hit is not evidence of absence when nothing was searched.

A gap is also not a signal. The invalid-IBAN case makes the difference concrete: change one digit and bank_screening.coverage becomes not_applicable — there is genuinely nothing to screen — yet the verdict is stop, not insufficient_coverage. The verdict is the maximum severity, and a structurally broken IBAN is a signal about the instruction, not a hole in the analysis.

Reachability is an operational answer, not a compliance one

The IBAN block carries per-scheme SEPA reachability from the EPC register — sct, sct_inst, sdd_core, sdd_b2b — and none of it moves the verdict. It answers a different failure: the transfer that is perfectly legitimate and simply will not execute the way the agent planned it. That matters more than it used to, now that instant euro transfers are a standing obligation rather than a premium option: an agent that assumes SCT Inst on an account reachable only for standard SCT has built an instruction its own bank will not run as intended.

include_weak is where your policy lives

Weak matches — a source-flagged weak alias, or partial token coverage — are always returned. The include_weak flag only decides whether they count towards the verdict. Left at its default, a weak name match is a review; set to true, the same call returns the same hits with a verdict of stop.

This is the one deliberately tunable line in the endpoint, and it is tunable in one direction only: the flag can make the service stricter, never blinder. A payout agent operating unattended can turn it on and treat review as a genuinely rare human escalation; a workflow with a reviewer in the loop can leave it off and read the hits itself.

The payment loop

  1. Call the pre-flight before you build the instruction, not after — the whole point is that it runs while a decision is still cheap to change.
  2. Always pass beneficiary_name. It is optional in the contract and mandatory in practice: without it, ok is unreachable and you have paid for an answer with a known hole in it.
  3. Pass country only as a declaration. It filters name candidates by the beneficiary’s declared country and can only remove candidates whose country the list published in comparable form — a designation that publishes no country stays a candidate.
  4. Branch on the verdict, not on a score. There is no numeric risk score to threshold, by design. stop and review are decisions; insufficient_coverage is a named open question, and it names which one.
  5. Persist the response, not a boolean. Every block carries the snapshot date it was answered from, and the root provenance deliberately reports the oldest of them — the honest freshness of the answer as a whole. Six months later, “why did the agent send this payment” is answerable from stored, dated facts.

The payment side of that loop is the ordinary discover → 402 → pay → replay cycle; the Quickstart walks it with runnable snippets, and For agents covers the discovery surfaces.

Billing: a refused transfer is a successful answer

The x402 golden rule is that the agent pays for the answer to its question, and here the mapping is unusually clean. “This IBAN fails its checksum” is a useful answer — HTTP 200 with a motivated stop, and it is billed. So are review and insufficient_coverage, because all three are answers. The 4xx range is reserved for requests the service cannot answer at all: a missing iban, or a beneficiary_name outside 2–200 characters.

This endpoint is not priced at the catalog’s flat per-call rate, and that is deliberate: one call runs three checks and the decision table over them, in one settlement. No price appears in this article — the gateway’s /catalog is the single source of truth for every amount and every accepted rail, the three unit endpoints included, so compare them there.

What it will not do

  • It is not Verification of Payee. The beneficiary name is compared against designation lists, never against the account holder’s name held by the beneficiary bank. “Is this account really theirs?” is your PSP’s question under the Instant Payments Regulation, and this endpoint does not answer it.
  • No company due diligence. Identity, insolvency, VAT status, e-invoicing reachability and control chain belong to GET /preflight/supplier — which will attach a whole payment pre-flight as its bank block when you pass it an iban.
  • No PEP screening, no adverse media, no transaction analysis. The name check covers the official designation lists in full — OFAC SDN and Consolidated, the EU financial sanctions list, the UN Security Council list — and nothing beyond them.
  • No risk score, and no payment instruction. Every response carries this verbatim in data.limits: the verdict is a control outcome, and the decision to pay remains the caller’s.

That scope sentence travels with every response rather than living in a footnote, so the agent and its auditor read the same statement. For the parameter contract, the full verdict and reason-code tables, the coverage states and the error codes, see the GET /preflight/payment documentation.