Verification of Payee API

Check the name before you pay.

Compare the beneficiary name in your payment instruction with the account-holder information from the bank. Add VoP alongside IBAN validation to help reduce misdirected payments and flag name mismatches before approval.

Prepaid add-on · Supported SEPA banks
Example check
IBAN
FR76 3000 6000 0112 3456 7890 189
Payee name
John Doe
MATCH
The payee name matches the account-holder information.

It works alongside standard IBAN validation to help reduce misdirected payments, fraud, and manual reconciliation issues. A successful API response means the check was completed; use the payee_name_match result to decide whether your payment workflow should continue, be reviewed, or be stopped.

VoP is powered by a partner certified by the European Payments Council that operates as a Routing and Verification Mechanism. Requests are routed to EU banks under the SEPA scheme in a fully compliant manner.

How it works

Send a POST request to the /v2/iban endpoint with the iban and payee_name fields in the JSON body. The response will include all the usual IBAN data plus a payee_name_match field with one of the following values:

  • MATCH – the name matches the account holder
  • CLOSE_MATCH – the name is similar but not an exact match (e.g. a typo or abbreviation)
  • NO_MATCH – the name does not match the account holder
  • NOT_APPLICABLE – the account does not exist or is explicitly excluded from VoP by the payment service provider
  • BANK_UNAVAILABLE – the bank has not implemented VoP services yet. Learn more

Example request

To verify the payee name for an IBAN, call /v2/iban with the POST method and include the iban and payee_name in the request body:

curl 'https://api.fincodesapi.com/v2/iban' \
    --request POST \
    --header 'X-Api-Key: your-api-key-here' \
    --header 'Accept: application/json' \
    --header 'Content-Type: application/json' \
    --data '{"iban":"DE75512108001245126199","payee_name":"John Doe"}'
# INSTALLATION
$ composer require guzzlehttp/guzzle
# REQUEST
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.fincodesapi.com/v2/iban', [
    'headers' => [
        'Accept' => 'application/json',
        'X-Api-Key' => 'your-api-key-here',
    ],
    'json' => [
        'iban' => 'DE75512108001245126199',
        'payee_name' => 'John Doe',
    ],
]);

echo $response->getBody();
# INSTALLATION
$ python -m pip install requests
# REQUEST
import requests

url = "https://api.fincodesapi.com/v2/iban"

headers = {
    "Accept": "application/json",
    "X-Api-Key": "your-api-key-here"
}

payload = {
    "iban": "DE75512108001245126199",
    "payee_name": "John Doe"
}
response = requests.request("POST", url, json=payload, headers=headers)

print(response.text)
# INSTALLATION
$ npm install node-fetch --save
// REQUEST
import fetch from 'node-fetch';

const url = 'https://api.fincodesapi.com/v2/iban';
const options = {
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'X-Api-Key': 'your-api-key-here',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    'iban': 'DE75512108001245126199',
    'payee_name': 'John Doe'
  })
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error('error:' + err));
const options = {
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'X-Api-Key': 'your-api-key-here',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    'iban': 'DE75512108001245126199',
    'payee_name': 'John Doe'
  })
};

fetch('https://api.fincodesapi.com/v2/iban', options)
  .then(response => response.json())
  .then(response => console.log(response))
  .catch(err => console.error(err));

The response includes the standard IBAN validation data with an additional payee_name_match field:

{
    "success": true,
    "data": {
        "id": "DE75512108001245126199",
        "account_number": "1245126199",
        "national_bank_code": "51210800",
        "national_branch_code": "",
        "payee_name_match": "MATCH",
        "bic": {
            "id": "SOGEDEFF",
            "address": "NEUE MAINZER STRASSE 46-50",
            "postcode": "60311",
            "branch_name": "SOGEBANK Frankfurt Main",
            "branch_code": "",
            "country": {
                "id": "DE",
                "name": "Germany"
            },
            "city": {
                "id": "c3eb05ae-2709-45c7-9799-d5e2fee08946",
                "country_id": "DE",
                "name": "Frankfurt Am Main"
            },
            "bank": {
                "id": "cfb1758f-1195-4be9-b981-3fc63da7306b",
                "country_id": "DE",
                "code": "SOGE",
                "name": "SOCIETE GENERALE S.A."
            }
        },
        "country": {
            "id": "DE",
            "name": "Germany"
        }
    }
}

Returning the matched payee name

Set include_matched_payee_name to true to receive the name supplied by the bank when the result is CLOSE_MATCH. The response then includes matched_payee_name. Because matched payee names are not stored by FinCodesAPI, a cached close match is checked with the bank again. Other cached match results are reused as usual.

{
    "iban": "DE75512108001245126199",
    "payee_name": "Jon Doe",
    "include_matched_payee_name": true
}
{
    "success": true,
    "data": {
        "id": "DE75512108001245126199",
        "account_number": "1245126199",
        "national_bank_code": "51210800",
        "national_branch_code": "",
        "payee_name_match": "CLOSE_MATCH",
        "matched_payee_name": "John Doe",
        "bic": {
            "id": "SOGEDEFF",
            "address": "NEUE MAINZER STRASSE 46-50",
            "postcode": "60311",
            "branch_name": "SOGEBANK Frankfurt Main",
            "branch_code": "",
            "country": {
                "id": "DE",
                "name": "Germany"
            },
            "city": {
                "id": "c3eb05ae-2709-45c7-9799-d5e2fee08946",
                "country_id": "DE",
                "name": "Frankfurt Am Main"
            },
            "bank": {
                "id": "cfb1758f-1195-4be9-b981-3fc63da7306b",
                "country_id": "DE",
                "code": "SOGE",
                "name": "SOCIETE GENERALE S.A."
            }
        },
        "country": {
            "id": "DE",
            "name": "Germany"
        }
    }
}

Supported countries

VoP is available for SEPA IBANs from the following countries:

limited coverage VoP is currently mandatory only for PSPs operating in SEPA countries that use the Euro. For EU member states that do not use the Euro, the implementation timeline has been extended, with a compliance deadline set for 9 July 2027. As a result, some banks in these countries have not yet implemented VoP services. In such cases, a BANK_UNAVAILABLE result is returned. Broader support is expected closer to the 2027 compliance deadline.

Testing

You can use the test IBAN DE75512108001245126199 with the following payee names to simulate different results without being charged:

Payee name Result
John Doe MATCH
Full Match MATCH
Close Match CLOSE_MATCH
Not Applicable NOT_APPLICABLE
Bank Unavailable BANK_UNAVAILABLE
Any other name NO_MATCH

Pricing

VoP is a pre-paid add-on. Each check costs $0.20 and is deducted from your VoP wallet balance. You can purchase checks from the billing page. Purchased checks do not expire.

You can find full API documentation here.

Need to validate multiple types of bank details? Explore our Bank Account Validation API.