Account holder verification
When you make a payout, an account holder verification check is performed on the beneficiary. In this process, the beneficiary’s name and account identifiers (sort code and account number) are checked against what is on file at the bank.
Make an account holder verification request
To verify a specific account holder, you need:
- An account holder name
- A sort code and account number, or an IBAN
- A valid access token with the scope
verification.
To enable the
verificationscope for account holder verification requests, contact us.
Make a POST request to the /v3/account-holder-verifications/requests endpoint with this information:
{
"account_holder_name": "John Doe",
"account_identifier": {
"type": "sort_code_account_number",
"sort_code": "123456",
"account_number": "12345678"
}
}{
"account_holder_name": "John Doe",
"account_identifier": {
"type": "iban",
"iban": "FR7630006000011234567890189"
}In the API response, you receive an id for the request.
{
"id": "550e8400-e29b-41d4-a716-446655440000"
}You do not receive any information on the status of the verification check in the response. To find out the result of the check, you need to make a GET request to the same endpoint, using the id you received in the response.
Monitor an account holder verification check
When you make an account holder verification check, it can have one of the following results:
- Account holder verification is complete and the result was
match - Account holder verification is complete and the result was
partial_match, which also includes the account holder name - Account holder verification is complete and the result was
no_match - Account holder verification is complete and the result was
match_not_possible, which also includes a failure reason in plain English - The verification attempt failed.
Normally, the verification process takes a few seconds.
GET account holder verification
To see the status of a particular check, you can make a GET request to the /v3/account-holder-verifications/requests/{id} endpoint (where id is the ID of the request that you created earlier).
{
"id": "550e8400-e29b-41d4-a716-446655440003",
"status": "pending"
}{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"match_result": {
"type": "match"
}
}{
"id": "550e8400-e29b-41d4-a716-446655440002",
"status": "completed",
"match_result": {
"type": "no_match"
}
}The response will contain:
- the
idof the verification request
You already submitted this in the previous step. - the
statusof the request
This can bepending,completeorfailed. - the
resultof the check, if the check is completed or failed
This can bematch,partial_match,no_matchormatch_not_possible.
If you receive a partial_match result, you also receive the account holder’s name in the response, so you can decide whether to move forward with the payout:
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"status": "completed",
"match_result": {
"type": "partial_match",
"account_holder_name": "Jean D."
}
}If you receive a match_not_possible or failed response, you also receive a failure reason with information on why verification failed:
{
"id": "550e8400-e29b-41d4-a716-446655440002",
"status": "completed",
"match_result": {
"type": "match_not_possible",
"failure_reason": "Bank unable to match"
}
}{
"id": "550e8400-e29b-41d4-a716-446655440004",
"status": "failed",
"failure_reason": "provider_error"
}If you receive a failed webhook or response to a GET request, we recommend retrying the check.
Webhooks
To set up webhooks for account holder verification, contact us. You won't be able to set up account holder verification webhooks in Console.
{
"type": "account_holder_verification_completed",
"event_version": 1,
"event_id": "b8d4dda0-ff2c-4d77-a6da-4615e4bad941",
"account_holder_verification_id": "550e8400-e29b-41d4-a716-446655440000",
"match_result": {
"type": "match"
}
}{
"type": "account_holder_verification_completed",
"event_version": 1,
"event_id": "e2g7ggc3-h25f-74g7-d049-7798h8e77263",
"account_holder_verification_id": "880h1733-h5ce-74h7-e049-7798h8e77263",
"match_result": {
"type": "no_match"
}
}{
"type": "account_holder_verification_completed",
"event_version": 1,
"event_id": "d1f6ffb2-g14e-63f6-c938-6687g7d66152",
"account_holder_verification_id": "770g0622-g4bd-63g6-d938-6687g7d66152",
"match_result": {
"type": "partial_match",
"account_holder_name": "J Smith"
}
}{
"type": "account_holder_verification_failed",
"event_version": 1,
"event_id": "c9e5eeb1-f03d-52e5-b827-5576f6c55041",
"account_holder_verification_id": "660f9511-f3ac-52f5-c827-5576f6c55041",
"failure_reason": "provider_error"
}{
"type": "account_holder_verification_completed",
"event_version": 1,
"event_id": "e2g7ggc3-h25f-74g7-d049-7798h8e77263",
"account_holder_verification_id": "880h1733-h5ce-74h7-e049-7798h8e77263",
"match_result": {
"type": "match_not_possible",
"failure_reason": "Bank unable to match"
}
}Pay out to a known payee even without a verification match
As part of the EPC regulations around verification of a payee, every payout to an external beneficiary account will undergo a name check. If the result is partial_match, no_match or match_not_possible, you will need to input on whether to progress with the payout as the payout will be failed.
For these situations, you can choose to push through with the payout anyway, using the beneficiary.type of verified_external_account. If you use this beneficiary type, you can also include two other fields:
account_holder_verification_id(required), which is a unique ID attached to that instance of account verificationoverride_bank_matched_name(optional), which in the case of apartial_matchindicates whether to use the account holder name on file at the bank or use the one you supplied in your verification check.
Below is an example Create Payout request, with the verified_external_account beneficiary type. In this case, the override_bank_matched_name value is set to true because the user wants to use the name on file at the bank, not the one supplied in the verification request.
{
"id": "0a495e9f-2f41-4669-ba33-85407c0b26cb",
"merchant_account_id": "24089aed-4fd4-9e13-f8b2-f458f30c836c",
"amount_in_minor": 100,
"currency": "EUR",
"beneficiary": {
"type": "verified_external_account",
"account_holder_verification_id": "f8c3a9e0-69ae-4918-b5b2-4d8f91e4e1af",
"override_bank_matched_name": true,
}
}
You can get the account_holder_verification_id from a previously executed/failed external_account payout (which included an account holder verification check). This ID appears in the following webhooks:
account_holder_verification_completedaccount_holder_verification_failed
You also receive this ID in successful responses from the Get Payout endpoint, inside the account_holder_verification object. Below is an example:
{
"id": "0cd1b0f7-71bc-4d24-b209-95259dadcc20",
"merchant_account_id": "ae094a73-d874-4241-a65f-6dcda7ac07b1",
"amount_in_minor": 100,
"currency": "EUR",
"beneficiary": {
"type": "external_account",
"reference": "a-reference",
"account_holder_name": "John Doe",
"account_identifiers": [
{
"type": "iban",
"iban": "FR1234567890123"
}
],
"account_holder_verification": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"match_result": {
"type": "match"
}
}
},
"scheme_id": "sepa_credit_transfer_instant",
"created_at": "2021-12-25T14:00:00.000Z",
"status": "executed",
"executed_at": "2021-12-25T15:00:00.000Z",
"metadata": {
"prop1": "value1",
"prop2": "value2"
}
}You can also get the account_holder_verification.id from webhooks. Allowing you to perform a name check on a customer’s account before initiating a payout by using the beneficiary type verified_external_account.
At minimum, you must be able to handle the
account_holder_verification.idfrom thepayout_failedandpayout_executedwebhooks.You must also be able to create payouts using the
beneficiary.typeofverified_external_account.
Test account holder verification in sandbox
We recommend that you test account holder verification endpoints in our sandbox environment (https://api.truelayer-sandbox.com) as part of your integration.
Use the data in the table below to test specific scenarios, including different failure reasons. Where you see ANY_IBAN for theiban value, substitute any valid IBAN.
For ANY_NAME, substitute any name except those that would produce a different, specific result (so don’t use John Doe, John partial, John impossiblematch or John pspfail for this field).
When you make a request to the POST endpoint, you receive an AHV_ID value. This is an identifier for the specific verification check that you've just done.
Then, to confirm the result of each of these test scenarios, call the GET account holder verification endpoint. Include the AHV_ID in the endpoint URL. Depending on the result of the verification check, you receive a different outcome when calling the GET endpoint.
POST Request endpoint: https://https://api.truelayer-sandbox.com/v3/account-holder-verifications/requests
GET Response endpoint: https://https://api.truelayer-sandbox.com/v3/account-holder-verifications/requests/{{AHV_ID}}
| POST Request body | Status of verification check | Match result received |
|---|---|---|
{ "account_holder_name": "John Doe", "account_identifier": { "type": "iban", "iban": "ANY_IBAN" } } | Completed | Match |
{ "account_holder_name": "ANY_NAME", "account_identifier": { "type": "iban", "iban": "ANY_IBAN" } } | Completed | No Match |
{ "account_holder_name": "John partial", "account_identifier": { "type": "iban", "iban": "ANY_IBAN" } } | Completed | Partial Match |
{ "account_holder_name": "John impossiblematch", "account_identifier": { "type": "iban", "iban": "ANY_IBAN" } } | Completed | Match Not Possible |
{ "account_holder_name": "John pspfail", "account_identifier": { "type": "iban", "iban": "ANY_IBAN" } } | Failed | N/A |
Below are the GET responses that you receive for each match result.
| Match result | GET response |
|---|---|
| Match | { "id": "4c7d28cb-20be-40a3-a952-07cdd6e628b2", "status": "completed", "match_result": { "type": "match" } } |
| No match | { "id": "38118169-8384-4091-9aef-c41127eead62", "status": "completed", "match_result": { "type": "no_match" } } |
| Partial match | { "id": "942e66b7-6e1a-4cbe-9a11-8d322ea1207b", "status": "completed", "match_result": { "type": "partial_match", "account_holder_name": "John Doe" } } |
| Match not possible | { "id": "ac0f5311-55ba-4284-8097-69ca58eaacd9", "status": "completed", "match_result": { "type": "match_not_possible", "reason": "Bank unable to match" } } |
| No match result, because the verification check failed | { "id": "408b1b61-dd41-432c-b480-c48f88186c4a", "status": "failed", "failure_reason": "VOP scheme provider error" } |