Make a verified payout

Use verified payouts to ensure you know who you are paying, based on bank account data.

Verified Payouts enables you to pay out to a known, verified beneficiary. For example, you may want to verify the account holder name or whether the end user has made a specific debit card transaction before initiating the payout. This can reduce costs and reduce the risk of fraudulent payouts whilst keeping your business compliant.

There are two different ways to use verified payouts:

  • Account name check: verifies that the name on file for an end user matches the name on the bank account
  • Transaction detection: verifies that a specific debit card deposit was made into the bank account being verified.

To use each of these, you need to set different parameters.

📘

This feature is UK only

Before you start

Enable the correct scopes

To integrate with verified payouts, contact us to enable these scopes:

Allowlist your redirect URI

Once a payout is created, redirect your user to the hosted page, and specify a return_uri as a parameter, to tell us where they want to redirect the end-user once the authorisation flow for the payout is completed.

The return_uri must be on the allowlist of redirect URIs for your client ID. You must also set your return_uri in Console.

To do this, contact us.

1. Create a payout including a verification object

First, initiate a Create Payout request.

  • Set the beneficiary type to user_determined.
  • You must also include a verification object. This object represents the type of verification that it's intended to run as part of the payout flow. Within this object, specify which value you want to verify and what you expect to see for that value.

Name only

If you are doing an account name check, specify a verification object as follows. Within the verification object, include a verify_name field and set its value to true.

In addition, include a user object with a name and either email or phone inside. These should be set to what you would expect from your user.

{
  // ... Other payout fields ...
  
  "beneficiary": {
    "type": "user_determined",
    "reference": "a-sample-reference",
    "user": {
        "id": "72485646-ca59-43f7-8788-bb974d44ef72", // optional
        "name": "John Doe", // full name, required, as expected by the merchant
        "email": "[email protected]", // either email or phone is required
        "phone": "+447012345678" 
     },
    "verification": {
      "verify_name": true // this verification uses what's declared in user.name
    },
    "provider_selection": { 
      "type": "user_selected"
    }
  }
}

Transaction verification

Optionally, you may also want to check that a card is linked to the bank account you expect.

If you are using transaction detection, you need to include additional information. The transaction_search_criteria object contains the information that you are using to search for a specific transaction. Ideally, this specific transaction should be the first one that was made with

Within this object, include an array of tokens such as a reference or company name. The array can include between 1 and 5 tokens.

You must also perform a name verification check when you perform transaction verification.

"transaction_search_criteria": {
  ...
  "tokens": [
    "18db38",
    "Betropolis LTD",
    "LC Betropolis"
  ],
  ...
}

The transaction description must contain an exact match of at least one of the tokens submitted. More than one matching transaction in a single account is acceptable.

You must also include an amount, currency and creation date for the transaction. We search within 7 days after the created_at date. For example, if the created_at date is 1 June 2024 (01-06-24), then all transactions from 1 June 2024 to 7 June 2024 may match. This also includes weekends and holidays.

This means that a full beneficiary object, with transaction verification, looks like this:

{
  ... Other payout fields ...
  
  "beneficiary": {
    "type": "user_determined",
    "user": {
        "id": "72485646-ca59-43f7-8788-bb974d44ef72", // optional
        "name": "John Doe", // full name, required, as expected by the merchant
        "email": "[email protected]", // either email or phone is required
        "phone": "+447012345678" 
     }
    "reference": "a-sample-reference",
    "verification": {
      "verify_name": true,
      "transaction_search_criteria": {
        "tokens": ["18db38", "Betropolis LTD", "LC Betropolis"],
        "amount_in_minor": 1000,
        "currency": "GBP",
        "created_at": "2025-05-07"
      }
    },
    "provider_selection": {
      "type": "preselected",
      "provider_id": "ob-barclays"
    }
  }
}

Example response

If the request succeeds, you receive a response that looks like this:

{
  "id": "0cd1b0f7-71bc-4d24-b209-95259dadcc20",
  "status": "authorization_required",
  "resource_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
  "user": {
	  "id": "1e1e7bb6-6592-40cc-aaa1-ae1b45d8cbd1"
  }
}

This response contains:

  • a payout id
  • an object indicating that the payout has the authorization_required status
  • a user object with an id for that user
  • a resource_token for this specific payout, which you will use in the next step. Store this.

2. Create a link and send your user to the auth dialog

Next, you need to authorise the payout.

  1. Create a link to the auth dialog. Include:
  • The payout_id (this is the id in the create payout response)
  • The resource_token for the payout
  • A return_uri where you want your user to be redirected.
https://app.truelayer.com/payouts#payout_id=92582476-69de-4ea8-baf2-e9a2972afbf9&resource_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c&return_uri=https://merchant-site.com/payout-return
  1. When they follow the link, the user lands on the auth dialog, which displays a consent screen first with copy indicating what the user is consenting to. This will always include their full name and their account identifiers (sort code and account number). If you are using transaction detection, this will also include transaction history.
An example of the auth dialog on web, including consent copy for transaction verification.

An example of the end user journey for transaction verified payouts.

  1. If the provider_selection object is set to user_selected in the Create payout request, the provider selection screen displays. The user selects the account that they want to receive the payout.
  2. The user is redirected to the bank’s website or app, where they can authenticate by logging into their account.
  3. The user is finally redirected to the return_uri that you specified earlier.

3. Wait for a verification result

When the user is redirected back to your site, the authorization process for the payout is already completed but the verification is typically still in progress. We recommend that you either wait for a payout webhook or poll the Get Payout endpoint using the id received as payout_id query parameter upon redirect.

4. Monitor a verified payout with webhooks

Terminal statuses for a payout are executed and failed. Learn more about payout statuses.. If a payout fails, use the contents of the failure_stage and failure_reason fields to display meaningful error messages to users.

There are four failure reasons that can occur if verification fails:

Failure reasonWhen it happens
verification_name_mismatchThe account holder name does not match the one on file at the bank
verification_transaction_not_foundThere is no transaction that matches the details of the transaction search criteria
account_not_validThere are no, or more than one, current accounts associated with the AIS consent.
expiredThe user took 10 minutes or more to authorise the payout.

Listen for webhooks to track the status of a verified payout. A successful payout results in a webhook like this:

{
    "type": "payout_executed",
    "event_id": "7183d229-f3c5-365f-6335-2be578a49cc3",
    "event_version": 1,
    "payout_id": "b0d2ab30-a9ef-4d8b-afea-0fd00cbb646e",
    "executed_at": "2025-05-20T10:16:11.517430Z",
    "beneficiary": {
      "type": "user_determined",
      "user": {
        "id": "755c1665-4916-439f-98af-024c7047e341"
      },
      "provider_id": "mock",
      "account_holder_name": "Transaction account 1", // This is usually a more significant AHN...
      "account_identifiers": [
        {
          "type": "sort_code_account_number",
          "sort_code": "040668",
          "account_number": "00003435"
        },
        {
          "type": "iban",
          "iban": "GB08CLRB04066800003435"
        }
      ]
    },
    "scheme_id": "faster_payments_service"
  }

The payout may fail at the verification stage, or it may pass verification but fail anyway. The differences between the webhooks are as follows:

{
   "type":"payout_failed",
   "event_id":"39d2377d-6d1d-327f-ac3c-7f96c0f145e6",
   "event_version":1,
   "payout_id":"e788dfe6-2dbc-4fad-9e0d-092f02726926",
   "failed_at":"2025-05-20T10:17:28.863946600Z",
   "failure_reason":"verification_name_mismatch",
   "beneficiary":{
      "type":"user_determined",
      "user":{
         "id":"8b178438-db0f-4807-a59f-6a432dc09fed"
      }
   }
}
{
    "type": "payout_failed",
    "event_id": "509aa1b4-f0b9-f8c7-0143-953dce019982",
    "event_version": 1,
    "payout_id": "570b4a2e-d393-446c-9aa5-2b9ebeff38b1",
    "failed_at": "2025-05-13T10:01:12.548168Z",
    "failure_reason": "insufficient_funds",
    "beneficiary": {
      "type": "user_determined",
      "user": {
        "id": "a5ae9bee-594f-432a-a4a9-23f1339bc59c"
      },
      "provider_id": "mock",
      "account_holder_name": "John Success",
      "account_identifiers": [
        {
          "type": "sort_code_account_number",
          "sort_code": "040668",
          "account_number": "00003435"
        },
        {
          "type": "iban",
          "iban": "GB08CLRB04066800003435"
        }
      ]
    }
  }

Test verified payouts in sandbox

Mock user credentials

To test verified payouts in sandbox, use the following mock credentials:

UsernamePassword
john1scan1

This set of credentials is configured with a matching IBAN and SCAN for testing.

Name verification

Success scenario

By using john1/scan1 credentials on the mock provider, you can connect one current account to their AIS consent.

The account holder name associated with that account is always named TRANSACTION ACCOUNT 1. So, to trigger a positive verification, pass TRANSACTION ACCOUNT 1 as the name inside the user object.

{
  "merchant_account_id": "ae094a73-d874-4241-a65f-6dcda7ac07b1",
  "amount_in_minor": 1,
  "currency": "GBP",
  "beneficiary": {
    "type": "user_determined",
    "user": {
        "name": "Transaction account 1",
        "email": "[email protected]",
        "phone": "+447012345678" 
    },
    "reference": "a-sample-reference",
    "verification": {
      "verify_name": true,
    },
    "provider_selection": {
      "type": "preselected",
      "provider_id": "mock"
    }
  }
}

Failure — name mismatch

Provide any name that's obviously different from Transaction account 1 as the name inside the user object.

Failure — Multiple current accounts connected

Use john/doe credentials to log in to the mock bank.

Transaction detection

Success scenario

Use the same john1/scan1 credentials on the mock provider and make a create payout request.

The amount_in_minor must be 1000 and the created_at date must be between the 1st and 7th of any month. You must use at least one of these tokens:

  • "18db38"
  • “Betropolis LTD"
  • "LC Betropolis”.
{
  "merchant_account_id": "ae094a73-d874-4241-a65f-6dcda7ac07b1",
  "amount_in_minor": 1,
  "currency": "GBP",
  "beneficiary": {
    "type": "user_determined",
    "user": {
        "name": "Transaction account 1",
        "email": "[email protected]",
        "phone": "+447012345678" 
     }
    "reference": "a-sample-reference",
    "verification": {
      "verify_name": true,
      "transaction_search_criteria": {
        "tokens": ["18db38", "Betropolis LTD", "LC Betropolis"],
        "amount_in_minor": 1000,
        "currency": "GBP",
        "created_at": "2025-05-07"
      }
    },
    "provider_selection": {
      "type": "preselected",
      "provider_id": "mock"
    }
  }
}

You can also test the name mismatch and multiple accounts connected failure scenarios for transaction verified payouts.

Failure — No matching transaction found

To test this scenario, do one or more of the following:

  • use the same john1/scan1 credentials on the mock provider, but send a random UUID as a token in the transaction_search_criteria object
  • use an amount_in_minor greater or less than 1000
  • use a created_at after the 7th of any month.

Use any tokens that do not match the tokens for the success case.

{
  "merchant_account_id": "ae094a73-d874-4241-a65f-6dcda7ac07b1",
  "amount_in_minor": 1,
  "currency": "GBP",
  "beneficiary": {
    "type": "user_determined",
    "user": {
        "name": "Transaction account 1",
        "email": "[email protected]",
        "phone": "+447012345678" 
     }
    "reference": "a-sample-reference",
    "verification": {
      "verify_name": true,
      "transaction_search_criteria": {
        "tokens": ["74832342-3c72-4694-9590-25e03255ecc0"], // non-matching token
        "amount_in_minor": 1000,
        "currency": "GBP",
        "created_at": "2025-05-07"
      }
    },
    "provider_selection": {
      "type": "preselected",
      "provider_id": "mock"
    }
  }
}

Sandbox test inputs

Account validation

ScenarioAccount credentialsProvider
Successjohn1/scan1mock
Failed - Multiple current accountsjohn/scanmock

Name verification

ScenarioAccount holder name
SuccessTransaction Account 1
Failed - Name mismatchAnything obviously different to Transaction Account 1

Transaction verification

ScenarioTokensDateAmount in minorCurrency
Success (tokens, date, amount and currency must match)Must contain at least one of the following tokens:

"18db38", “Betropolis LTD", "LC Betropolis”
1st - 7th day of any month1000GBP
Failed - Transaction not found (Any one of the properties does not match)Any token that does not match the success case> 7th day of any month<1000 or > 1000GBP

Note that for a successful transaction verified payout, both the name and transaction checks must be successful. This means that you must also use Transaction Account 1 as the name inside the user object.

📘

Bank exclusions

CashPlus and Santander do not support transactions in a pending state. This means that occasionally, some transactions (particularly very recent ones) may not be detected by transaction verification.

Verified Payouts currently does not support Chase.