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 make a payout to the same bank account previously used to make a deposit, even if the user initially paid with a debit card. This can reduce costs in a compliant way and reduce the risk of fraudulent payouts.
To do this, you can use our Verification API to verify a bank account is in the name of their user, and if so initiate a payout themselves via our Payouts API.
There are two different ways to use verified payouts:
- Account name check: verifies that the name on the gambling account matches the name on the bank account
- Transaction detection: verifies that a specific payment card deposit was made into the 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:
payments
info
accounts
transactions
, if you are using the Transaction detection use case
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
verification
objectFirst, 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 they intend to run as part of the payout.
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. Use the account_holder_name
field within the verification
object to
{
... Other payout fields ...
"beneficiary": {
"type": "user_determined",
"reference": "a-sample-reference",
"verification": {
"account_holder_name": "John Doe"
},
"provider_selection": {
"type": "user_selected"
}
}
}
Transaction verification
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. Within this object, include an array of tokens
such as a reference or beneficiary name. The array can include between 1 and 5 tokens.
"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 5 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 5 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",
"reference": "a-sample-reference",
"verification": {
"transaction_search_criteria": {
"tokens": [
"18db38",
"PoppyPower LTD",
"LC PoppyPower"
],
"amount_in_minor": 2000,
"currency": "GBP",
"created_at": "2024-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"
}
This response contains:
- a payout
id
- an object indicating that the payout has the
authorization_required
status - 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. To do this, you need to create a link,
- Create a link to the auth dialog. Include:
- The
payout_id
(this is theid
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
- 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.
- If the
provider_selection
object is set touser_selected
in the Create payout request, the provider selection screen displays. The user selects the account that they want to receive the payout. - The user is redirected to the bank’s website or app, where they can authenticate by logging into their account.
- 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 three failure reasons that can occur if verification fails:
Failure reason | When it happens |
---|---|
verification_name_mismatch | The account holder name does not match the one on file at the bank |
verification_transaction_not_found | There is no transaction that matches the details of the transaction search criteria |
account_not_valid | There are no, or more than one, current accounts associated with the AIS consent. |
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"
}
]
}
}
Mock user credentials
To test verified payouts in sandbox, use the following mock credentials:
Username Password john1 scan1 This set of credentials is configured with a matching IBAN and SCAN for testing.
Test verified payouts in sandbox
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 account_holder_name
inside the verification
object.
{
"merchant_account_id": "ae094a73-d874-4241-a65f-6dcda7ac07b1",
"amount_in_minor": 1,
"currency": "GBP",
"beneficiary": {
"type": "user_determined",
"reference": "a-reference",
"verification": {
"account_holder_name": "Transaction account 1"
},
"provider_selection": {
"type": "preselected",
"provider_id": "mock"
}
}
}
Failure — name mismatch
Provide any name that's obviously different from Transaction account 1
as the account_holder_name
.
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",
"reference": "a-reference", // whatever reference
"verification": {
"account_holder_name": "Transaction account 1"
"transaction_search_criteria": {
"tokens": ["18db38", "Betropolis LTD", "LC Betropolis"]
"amount_in_minor": 1000,
"currency": "GBP",
"created_at": "2024-05-07"
}
},
"provider_selection": { //can also be user_selected
"type": "preselected",
"provider_id": "mock"
}
}
}
The name mismatch and multiple accounts connected failure scenarios work the same way as they do for name verification.
Failure scenario 3 - No matching transaction found
To test this scenario, use the same john1/scan1
credentials on the mock provider, but send a random UUID as a token
in the transaction_search_criteria
object.
The amount_in_minor
must not be 1000
, but can be greater or less. The created_at
date must be 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",
"reference": "a-reference",
"verification": {
"account_holder_name": "Transaction account 1",
"transaction_search_criteria": {
"tokens": ["74832342-3c72-4694-9590-25e03255ecc0"],
"amount_in_minor": 1000,
"currency": "GBP",
"created_at": "2024-05-07"
}
},
"provider_selection": {
"type": "preselected",
"provider_id": "mock"
}
}
}
Sandbox test inputs
Account validation
Scenario | Account credentials | Provider |
---|---|---|
Success | john1/scan1 | mock |
Failed - Multiple current accounts | john/scan | mock |
Name verification
Scenario | Account holder name |
---|---|
Success | Transaction Account 1 |
Failed - Name mismatch | Anything obviously different to Transaction Account 1 |
Transaction verification
Scenario | Tokens | Date | Amount in minor | Currency |
---|---|---|---|---|
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 month | 1000 | GBP |
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 > 1000 | GBP |
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 account_holder_name
.
Updated 13 days ago