Payout webhooks

Payout notifications sent to your webhook URI registered in Console, when a payout becomes executed or fails.

The Payments API sends webhooks for two of the statuses in the lifecycle of a payout: executed and failed. Learn about the other payout statuses, pending and authorized.

There are three different ways to specify the beneficiary of a payout: payouts to a payment source, payouts to an external account, and payouts to a business account. This guide includes webhook examples for payouts to each beneficiary type.

🚧

Validate webhooks

You must always verify the authenticity of incoming webhook requests. To do this, we recommend that you use the webhook signing library, allowing your application to confirm that the request originated from TrueLayer and has not been tampered with.

To allowlist TrueLayer calls, add a unique query parameter to your webhook URI for identification. For enhanced security, include a self-signed JWT token as a callback parameter, which you can then decode to verify its contents. For example: https://mywebhook.app?unique_param=x

Payout to payment source webhooks

Also called a closed-loop payout.

payout_executed

FieldTypeDescription
typestringType of the event. In this case, it would be: payout_executed
event_idstringThe UUID of that specific event.
event_versionnumberVersion of the event
payout_idstringUUID of the payout for which the webhook is being sent
executed_atstringTimestamp of the event, in ISO8601 format
beneficiary.typestringValue would be payment_source.

This indicates that the payout is made to the payment_source.
beneficiary.payment_source_idstringID of the external account which has become a payment source.
beneficiary.user_idstringID of the user that owns the external account.
scheme_idstringThe id of the scheme used to execute the payout. Values are:

- unknown
- faster_payments_service
- internal_transfer
- sepa_credit_transfer
- sepa_credit_transfer_instant
merchant_account_idstringThe merchant account the payout was made from.
current_balance_in_minornumberThe current balance of the merchant account in minor.
available_balance_in_minornumberThe available balance of the merchant account in minor.
metadatastringOptional field for adding custom key-value data to a resource. This object can contain a maximum of 10 key-value pairs, each with a maximum key length of 40 characters and a maximum value length of 500 characters.
{
  "type": "payout_executed",
  "event_version": 1,
  "event_id": "b8d4dda0-ff2c-4d77-a6da-4615e4bad941",
  "payout_id": "0cd1b0f7-71bc-4d24-b209-95259dadcc20",
  "executed_at": "2021-12-25T15:00:00.000Z",
  "beneficiary": {
    "type": "payment_source",
    "payment_source_id": "4a59c822-3bfb-42ba-9202-b6d89988a195",
    "user_id": "a0977be8-c406-4f75-bb81-b5ca0689b29b",
  },
  "scheme_id": "faster_payments_service",
}

payout_failed

FieldTypeDescription
typestringType of the event. In this case, it would be: payout_failed
event_idstringThe UUID of that specific event
event_versionnumberThe version of the event
payout_idstringUUID of the payout for which the webhook is being sent
failed_atstringTimestamp of the event, in ISO8601 format
failure_reasonstringThe reason of the payout failure
beneficiary.typestringValue would be payment_source.

This indicates that the payout is made to the payment_source.
beneficiary.payment_source_idstringID of the external account which has become a payment source.
beneficiary.user_idstringID of the user that owns the external account.
merchant_account_idstringThe merchant account the payout was made from.
current_balance_in_minornumberThe current balance of the merchant account in minor.
available_balance_in_minornumberThe available balance of the merchant account in minor.
metadatastringOptional field for adding custom key-value data to a resource. This object can contain a maximum of 10 key-value pairs, each with a maximum key length of 40 characters and a maximum value length of 500 characters.
{
  "type": "payout_failed",
  "event_version": 1,
  "event_id": "b8d4dda0-ff2c-4d77-a6da-4615e4bad941",
  "payout_id": "0cd1b0f7-71bc-4d24-b209-95259dadcc20",
  "failed_at": "2021-12-25T15:00:00.000Z",
  "failure_reason": "insufficient_funds",
  "beneficiary": {
    "type": "payment_source",
    "payment_source_id": "9ac7ab1f-6229-47db-9e17-81072d2dbdf3",
    "user_id": "9775a22c-23c7-41c8-9e7c-1508997db9c0",
  }
}

Payout to an external account webhooks

When you make a payout to an external account with its own specified account identifiers. This is also called an open-loop payout.

payout_executed

FieldTypeDescription
typestringType of the event. In this case, it would be: payout_executed
event_idstringThe UUID of that specific event
event_versionnumberThe version of the event
payout_idstringUUID of the payout for which the webhook is being sent
executed_atdatetimeTimestamp of the event, in ISO8601 format
beneficiary.typestringValue will be external_account
beneficiary.account_holder_name_verificationstringAn object that includes information about account holder verification performed on the beneficiary.

Only applicable in EUR payouts.
beneficiary.account_holder_name_verification.statusstringIncludes the result of the verification attempt, plus any other information. Can be completed or failed.
beneficiary.account_holder_name_verification.failure_reasonstringDetails about why account holder verification failed.

You only see this field alongside a status of failed.

Possible failure reasons include:
Bank unable to match: The bank account is closed, or could not be found, or another similar error.
Party agent not part of scheme: This bank is not part of the verification scheme.
VoP scheme provider error: There's a failure with one of the providers in the scheme. (We recommend retrying when you receive this error.)
beneficiary.account_holder_name_verification.match_resultstringIf the match is completed, this object includes the result of the account holder verification check and any additional information.
beneficiary.account_holder_name_verification.match_result.typestringCan be:

- no_match
- full_match
- match_not_possible, where you also get a failure reason explaining what went wrong
- partial_match, where you also get the name that the bank expects to see
beneficiary.account_holder_name_verification.match_result.reasonstringThe reason that the account holder's name and details couldn't be verified.

You only see this field alongside a match result of match_not_possible
beneficiary.account_holder_name_verification.match_result.account_holder_namestringThe name that the bank expects to see, if the name that your user provided partially but not completely matches the name on file at the bank.

You only see this field alongside a match result of partial_match
scheme_idstringID representing the payment scheme that the payout was made on.

payout_failed

FieldTypeDescription
typestringType of the event. In this case, it would be: payout_failed
event_idstringThe UUID of that specific event
event_versionnumberThe version of the event
payout_idstringUUID of the payout for which the webhook is being sent
failed_atstringTimestamp of the event, in ISO8601 format
failure_reasonstringThe reason of the payout failure
beneficiary.typestringValue will be external_account
merchant_account_idstringThe merchant account the payout was made from.
current_balance_in_minornumberThe current balance of the merchant account in minor.
available_balance_in_minornumberThe available balance of the merchant account in minor.
metadatastringOptional field for adding custom key-value data to a resource. This object can contain a maximum of 10 key-value pairs, each with a maximum key length of 40 characters and a maximum value length of 500 characters.
{
  "type": "payout_executed",
  "event_version": 1,
  "beneficiary": {
    "type": "external_account",
    "account_holder_verification": {
      "status": "completed",
      "match_result": {
        "type": "match"
      }
    }
  },
  "executed_at": "2021-12-25T15:00:00.000Z",
  "scheme_id": "faster_payments_service",
  "payout_id": "0cd1b0f7-71bc-4d24-b209-95259dadcc20",
  "event_id": "b8d4dda0-ff2c-4d77-a6da-4615e4bad941"
}
{
  "type": "payout_failed",
  "event_version": 1,
  "event_id": "24089aed-4fd4-9e13-f8b2-f458f30c836c",
  "payout_id": "0a495e9f-2f41-4669-ba33-85407c0b26cb",
  "failed_at": "2024-01-12T14:56:05.117850644Z",
  "failure_reason": "insufficient_funds",
  "beneficiary": {
    "type": "external_account"
  }
}

Verified payout webhooks

Webhooks for a verified payout contain more information.

payout_executed

FieldTypeDescription
typestringType of the event. In this case, it would be: payout_executed
event_idstringThe UUID for that specific event
event_versionnumberVersion of the event
payout_idstringUUID of the payout for which the webhook is being sent
executed_atstringTimestamp of the event, in ISO8601 format
merchant_account_idstringThe merchant account the payout was made from.
current_balance_in_minornumberThe current balance of the merchant account in minor.
available_balance_in_minornumberThe available balance of the merchant account in minor.
metadatastringOptional field for adding custom key-value data to a resource. This object can contain a maximum of 10 key-value pairs, each with a maximum key length of 40 characters and a maximum value length of 500 characters.
beneficiary.typestringThe type of bank account you're paying out to. Can be external_account, payment_source, user_determined or business_account.
beneficiary.account_holder_name_verificationstringAn object that includes information about account holder verification performed on the beneficiary.
beneficiary.account_holder_name_verification.outcomestringAn object inside account_holder_name_verification that includes the result of the verification attempt, plus any other information.
beneficiary.account_holder_name_verification.outcome.typestringThe result of account holder name verification. Can be:

- no_match
- full_match
- match_not_possible, where you also get a failure reason explaining what went wrong
- partial_match, where you also get the name that the bank expects to see
beneficiary.account_holder_name_verification.outcome.namestringThe name that the bank expects to see, if the name that your user provided partially but not completely matches the name on file at the bank.

You only see this field alongside an outcome.type of partial_match
beneficiary.account_holder_name_verification.outcome.failure_reasonstringDetails about why account holder verification failed.

You only see this field alongside an outcome.type of match_not_possible.
beneficiary.user.idstringA UUID that represents the user.
beneficiary.provider_idstringThe provider_id that represents the bank the payout is being made to.
beneficiary.account_holder_namestringThe name of the beneficiary.
beneficiary.account_identifiers.typestringCan be sort_code_account_number or iban.
scheme_idstringThe id of the scheme used to execute the payout. Values are:

- unknown
- faster_payments_service
- internal_transfer
- sepa_credit_transfer
- sepa_credit_transfer_instant
{
  "type": "payout_executed",
  "event_version": 1,
  "beneficiary": {
    "type": "external_account",
    "account_holder_name_verification": {
      "outcome": {
        "type": "partial_match",
        "name": "John Sandbridge"
      }
    },
    "user_id": "string"
  },
  "metadata": {
    "prop1": "value1",
    "prop2": "value2"
  },
  "event_id": "b8d4dda0-ff2c-4d77-a6da-4615e4bad941",
  "payout_id": "0cd1b0f7-71bc-4d24-b209-95259dadcc20",
  "executed_at": "2021-12-25T15:00:00.000Z",
  "scheme_id": "faster_payments_service"
}

payout_failed

FieldTypeDescription
typestringType of the event. In this case, it would be: payout_failed
event_idstringThe UUID of that specific event
event_versionnumberVersion of the event
payout_idstringUUID of the payout for which the webhook is being sent
failed_atstringTimestamp of the event, in ISO8601 format
failure_reasonstringThe reason of the payout failure
merchant_account_idstringThe merchant account the payout was made from.
current_balance_in_minornumberThe current balance of the merchant account in minor.
available_balance_in_minornumberThe available balance of the merchant account in minor.
metadatastringOptional field for adding custom key-value data to a resource. This object can contain a maximum of 10 key-value pairs, each with a maximum key length of 40 characters and a maximum value length of 500 characters.
{
  "type": "payout_failed",
  "event_version": 1,
  "event_id": "f8a144dc-a550-4681-844b-4de231ec3764",
  "payout_id": "f8a144dc-a550-4681-844b-4de231ec3764",
  "failed_at": "2022-09-14T16:41:21.006718283Z",
  "failure_reason": "insufficient_funds",
  "beneficiary": {
    "type": "user_determined",
    "account_holder_name": "John Doe",
    "account_identifier": {
      "type": "sort_code_account_number",
      "sort_code": "040075",
      "account_number": "58114637"
    }
  },
  "merchant_account_id": "a1b2c3d4-e5f6-7890-abcd-1234567890ef",
  "current_balance_in_minor": 500000,
  "available_balance_in_minor": 450000,
  "metadata": {
    "order_id": "12345",
    "customer_id": "67890"
  }
}

Payout to a business account

When you make a payout to the linked business account you specified during your onboarding with TrueLayer.

payout_executed

FieldTypeDescription
typestringType of the event. In this case, it would be: payout_executed
event_idstringThe UUID of that specific event.
event_versionnumberVersion of the event
payout_idstringUUID of the payout for which the webhook is being sent
executed_atstringTimestamp of the event, in ISO8601 format
beneficiary.typestringValue would be business_account
scheme_idstringThe id of the scheme used to execute the payout. Values are:

- unknown
- faster_payments_service
- internal_transfer
- sepa_credit_transfer
- sepa_credit_transfer_instant
merchant_account_idstringThe merchant account the payout was made from.
current_balance_in_minornumberThe current balance of the merchant account in minor.
available_balance_in_minornumberThe avilable balance of the merchant account in minor.
metadatastringOptional field for adding custom key-value data to a resource. This object can contain a maximum of 10 key-value pairs, each with a maximum key length of 40 characters and a maximum value length of 500 characters.
{
  "type": "payout_executed",
  "event_version": 1,
  "event_id": "b8d4dda0-ff2c-4d77-a6da-4615e4bad941",
  "payout_id": "0cd1b0f7-71bc-4d24-b209-95259dadcc20",
  "executed_at": "2021-12-25T15:00:00.000Z",
  "beneficiary": {
    "type": "business_account"
  },
  "scheme_id": "faster_payments_service",
}

payout_failed

FieldTypeDescription
typestringType of the event. In this case, it would be: payout_failed
event_idstringThe UUID of that specific event.
event_versionnumberVersion of the event
payout_idstringUUID of the payout for which the webhook is being sent
failed_atstringTimestamp of the event, in ISO8601 format
beneficiary.typestringValue would be business_account.
merchant_account_idstringThe merchant account the payout was made from.
current_balance_in_minornumberThe current balance of the merchant account in minor.
available_balance_in_minornumberThe available balance of the merchant account in minor.
metadatastringOptional field for adding custom key-value data to a resource. This object can contain a maximum of 10 key-value pairs, each with a maximum key length of 40 characters and a maximum value length of 500 characters.
{
  "type": "payout_failed",
  "event_version": 1,
  "event_id": "b8d4dda0-ff2c-4d77-a6da-4615e4bad941",
  "payout_id": "0cd1b0f7-71bc-4d24-b209-95259dadcc20",
  "failed_at": "2021-12-25T15:00:00.000Z",
  "beneficiary": {
    "type": "business_account"
  }
}

{
  "type": "payout_failed",
  "event_version": 1,
  "event_id": "b8d4dda0-ff2c-4d77-a6da-4615e4bad941",
  "payout_id": "0cd1b0f7-71bc-4d24-b209-95259dadcc20",
  "failed_at": "2021-12-25T15:00:00.000Z",
  "beneficiary": {
    "type": "business_account"
  }
}