Create a payment

Build an API call to initiate a payment in GBP or EUR.

Use this guide to configure a payment into an account that you choose. We recommend using a merchant account to receive payments, but you can also set an external account as the beneficiary.

Payments into a merchant account are also known as closed-loop pay-ins.

Payment overview

At a basic level, the process of creating, and then completing, a payment involves:

  1. Payment authentication: passing an access token and headers for signing and idempotency
  2. Payment configuration: setting up an API request with the details of the payment
  3. End-user authorisation: having your user give consent for the payment to be made
  4. Payment monitoring: using webhooks, alongside other tools, to track the progress of a payment

1. Authenticate a payment

To create a payment, you must first set up authentication. This ensures only you can create payments for your integration.

1.1 Generate an access_token

Generate an access_token with the payments scope. Include this as a bearer header with your request.

1.2 Include headers for signing and idempotency

Generate public and private keys and set up request signing, so you can include a Tl-Signature header with your requests.

Your requests to the payments API should also include an idempotency key, which you provide as a Idempotency-Key header. This ensures that you can safely retry requests without creating duplicate payments.

📘

Integration options

The examples on this page use HTTP. However, we also offer complete .NET and Java libraries you can use to integrate payment creation.

For more on authenticating a payment, see our section on request authentication.

2. Configure a payment

To create a payment, make a POST request to the /v3/payments endpoint, providing values for the parameters below. See the full API reference for more details.

2.1 Request parameters

This table contains an overview of all the parameters to specify to create a payment.

ParameterDescription
amount_in_minorThe amount in minor units.

Minor units are the smallest units of a currency, depending on the number of decimals. For example: 1 GBP = 100 pence.
currencyThe currency of the payment as an ISO 4217 code. TrueLayer supports GBP and EUR.

You cannot make a payment from GBP currency to a EUR account, specified in the payment_method.beneficiary.account_identifier object.
payment_method.typeThe payment method for the payment.

For a single payment, use bank_transfer.

For a VRPs, use mandate as the type.
payment_method.provider_selection.typeUse this parameter to choose how users can choose a provider. There are two methods you can choose between:

- user_selected: Enables the user to select a provider as part of the authorisation flow.
- preselected: Enables you to prepopulate the provide for the payment you create with a provider_id.Learn more about how to configure provider selection in a payment.
payment_method.provider_selection.filterThis parameter provides a variety of filters you can apply to a payment with user_selected provider selection. These filters change the banks available for the remitter to choose from.

The available filters include country, maturity of the bank's integration, segment that the bank serves, and provider ID.
payment_method.provider_selection.scheme_selectionUse this parameter to choose how users can choose a payment scheme .

There are four values you can choose from, which change in behaviour based on the accompanying type of provider selection you choose:

- instant_only: Only displays providers that support instant payment schemes.
- instant_preferred: Displays providers that support instant payment schemes, but allows a fall back to a non-instant scheme.
- user_selected: Enables the user to select the payment scheme if a provider supports both instant and non-instant payments.
- preselected: You provide the scheme_id for the required payment scheme so the user can't choose one. Only available in combination with preselected provider selection.Learn more about how to configure scheme selection in a payment .
payment_method.provider_selection.remitterUse this parameter to provide a remitter's banking details as part of a payment with preselected provider selection.

This simplifies the payment authorisation flow by ensuring the remitter's bank account is preselected when they authorise the payment with their bank.
payment_method.beneficiary.typeThis parameter lets you specify who the payment will be sent to, the beneficiary.

- merchant_account: Pay into your merchant account. This is required for closed-loop payments.

- external_account: Pay to an external account by providing an account identifier such as SCAN or IBAN.
payment_method.beneficiary.account_holder_nameThe name of the beneficiary. This is what displays as the beneficiary on the remitter's bank statement.

In a pay-in to a merchant account, this takes priority as the name the user sees on their statement. However, if omitted in a pay-in to a merchant account, the name associated with the merchant account is used by default.

Some providers have upper limits for this field. If you need to shorten a name to fit these limits, we recommend removing middle names first, then initialising the first name. For example:

Jonathan Alexander Doe > Jonathan Doe > J Doe
payment_method.beneficiary.account_identifierThe bank details that identify the beneficiary's account.

This can be sort_code_account_number, iban, bban or nrb.

Note that you cannot make payments from a GBP account to a EUR account, or the other way round.

If a payment is made into your merchant account's sort code and account number or IBAN instead of its merchant account id, you received the external_payment_received webhook.
payment_method.beneficiary.referenceThe reference for the payment that displays on the remitter's bank statement.

Some providers have character limits for this field. We recommend making your reference as short as possible, ideally under 18 characters.
userSome personal information about the user remitting funds, and an ID.

For a single payment, it's mandatory to include the payer's full name and one of their email address or phone number.

Some providers have upper limits for this field. If you need to shorten a name to fit these limits, we recommend removing middle names first, then initialising the first name. For example:

Jonathan Alexander Doe > Jonathan Doe > J Doe

Learn more about the user information to include in your payment requests.
metadataAn optional field to add custom data to a payment. This is saved on payment creation and returned on every payment retrieve.
related_productsEnables you to enable a related product for a payment. Currently, you can only enable SignUp+ by including an empty signup_plus object.
authorization_flowEnables you to start the authorisation flow as part of a direct API integration, where you build your own UI .

Providing this parameter removes the need for a subsequent request to the /v3/payments/{id}/authorization-flow endpoint after you create a payment.

The available authorisation actions you can provide in this parameter are provider selection, scheme selection, redirect, form, consent, and user account selection.

You don't need to use the authorization_flow parameter if you're using a TrueLayer web or mobile UI to authorise your payment.

2.2 Provider selection

Configure provider selection through the payment_method.bank_transfer.provider_selection parameter. There are two types of provider selection:

  • user_selected, where the user selects the banking provider to pay through.
  • Preselected, where you include a provider_id in your payment request.
    This is usually only used to simplify returning user payment flows.

Learn more about how to select a banking provider for a payment .

2.3 Scheme selection

Configure scheme selection through the payment_method.bank_transfer.provider_selection.scheme_selection parameter. This object controls which payment schemes payments move on, which are the infrastructure over which banks complete payments.

Behaviours for scheme selection vary, depending on the combination of provider and scheme selection you specify.

Learn more about how to select a scheme for a payment .

2.4 User information

You must provide user information in the user parameter as part of your payment creation requests. Some user information is mandatory in order to create a request, and other information is optional. However, we recommend that you include the optional information also in order to reduce the chance of us having to raise a RFI.

Using the user id in your payments is also useful as enables you to associate multiple payments with a single user so they can be retrieved easily. The user information you provide also enables better returning user experiences.

See what user information is needed for each payment type
Payment typeMandatory user informationRecommended user information to reduce number of RFIs
Merchant account pay-in- Name
At least one of:

- Email address
- Phone number
- Date of birth

- Address
External account payment- Name
At least one of:

- Email address
- Phone number
VRP mandate (merchant account beneficiary)- Name
At least one of:

- Email address
- Phone number
- Date of birth

- Address
VRP mandate (external account beneficiary)- Name
At least one of:

- Email address
- Phone number
Closed-loop payoutNone
Open-loop payoutNone (already collected by default)- Date of birth

- Address
RefundsNone

2.5 Optional metadata

You don't need to include any values for the metadata object. However, if your business needs to include extra metadata in your payout requests (for internal processes for example), you can choose to include up to 10 key value pairs.

To include metadata, provide key value pairs in the object in the format below:

{
//...
  "metadata": {
    "Metadata_key_1": "Metadata_value_1",
    "Metadata_key_2": "Metadata_value_2",
    "Metadata_key_3": "Metadata_value_3"
  }
}

Example payment requests

These are examples of payment creation requests in the sandbox environment. They include payments in the UK and France with a variety of user-selected and preselected provider and scheme selection options.

Note also that the preselected payment examples for the UK and France include the remitter parameter with SCANand IBANdetails respectively. This ensures that

POST /v3/payments HTTP/1.1
Content-Type: application/json
Idempotency-Key: {RANDOM_UUID}
Tl-Signature: {SIGNATURE}
Authorization: Bearer {ACCESS_TOKEN}
Host: api.truelayer-sandbox.com
{
    "amount_in_minor": 30000,
    "currency": "GBP",
    "payment_method": {
        "provider_selection": {
            "type": "user_selected",
            "scheme_selection": {
                "type": "user_selected",
                "allow_remitter_fee": false
            }
        },
        "type": "bank_transfer",
        "beneficiary": {
            "type": "merchant_account",
            "merchant_account_id": "200552da-13da-43c5-a9ba-04ee1502ac57"
        }
    },
    "user": {
        "id": "f61c0ec7-0f83-414e-8e5f-aace86e0ed35",
        "name": "Jonathan Sandbridge",
        "email": "[email protected]",
        "phone": "+447809123456",
        "date_of_birth": "1992-11-28",
        "address": {
            "address_line1": "40 Finsbury Square",
            "city": "London",
            "state": "London",
            "zip": "EC2a 1PX",
            "country_code": "GB"
        }
    }
}
POST /v3/payments HTTP/1.1
Content-Type: application/json
Idempotency-Key: {RANDOM_UUID}
Tl-Signature: {SIGNATURE}
Authorization: Bearer {ACCESS_TOKEN}
Host: api.truelayer-sandbox.com
{
    "amount_in_minor": 30000,
    "currency": "GBP",
    "payment_method": {
        "provider_selection": {
            "type": "preselected",
            "scheme_selection": {
                "type": "instant_preferred",
                "allow_remitter_fee": false
            },
            "provider_id": "mock-payments-gb-redirect",
            "remitter": {
                "account_holder_name": "John Sandbridge",
                "account_identifier": {
                    "type": "sort_code_account_number",
                    "sort_code": "040668",
                    "account_number": "00000871"
                }
            }
        },
        "type": "bank_transfer",
        "beneficiary": {
            "type": "merchant_account",
            "merchant_account_id": "200552da-13da-43c5-a9ba-04ee1502ac57"
        }
    },
    "user": {
        "id": "f61c0ec7-0f83-414e-8e5f-aace86e0ed35",
        "name": "Jonathan Sandbridge",
        "email": "[email protected]",
        "phone": "+447809123456",
        "date_of_birth": "1992-11-28",
        "address": {
            "address_line1": "40 Finsbury Square",
            "city": "London",
            "state": "London",
            "zip": "EC2a 1PX",
            "country_code": "GB"
        }
    }
}
POST /v3/payments HTTP/1.1
Content-Type: application/json
Idempotency-Key: {RANDOM_UUID}
Tl-Signature: {SIGNATURE}
Authorization: Bearer {ACCESS_TOKEN}
Host: api.truelayer-sandbox.com
{
    "amount_in_minor": 30000,
    "currency": "EUR",
    "payment_method": {
        "provider_selection": {
            "type": "user_selected",
            "scheme_selection": {
                "type": "user_selected",
                "allow_remitter_fee": false
            }
        },
        "type": "bank_transfer",
        "beneficiary": {
            "type": "merchant_account",
            "merchant_account_id": "2a485b0a-a29c-4aa2-bcef-b34d0f6f8d51"
        }
    },
    "user": {
        "id": "f61c0ec7-0f83-414e-8e5f-aace86e0ed35",
        "name": "Jonathan Sandbridge",
        "email": "[email protected]",
        "phone": "+44123456789",
        "date_of_birth": "1992-11-28",
        "address": {
            "address_line1": "1, Hardwick Street",
            "city": "London",
            "state": "London",
            "zip": "EC1R 4RB",
            "country_code": "GB"
        }
    }
}
POST /v3/payments HTTP/1.1
Content-Type: application/json
Idempotency-Key: {RANDOM_UUID}
Tl-Signature: {SIGNATURE}
Authorization: Bearer {ACCESS_TOKEN}
Host: api.truelayer-sandbox.com
{
    "amount_in_minor": 30000,
    "currency": "EUR",
    "payment_method": {
        "provider_selection": {
            "type": "preselected",
            "provider_id": "mock-payments-fr-redirect",
            "scheme_selection": {
                "type": "instant_preferred"
            },
            "remitter": {
                "account_holder_name": "John Sandbridge",
                "account_identifier": {
                    "type": "iban",
                    "iban": "FR5217569000506231212211X69"
                }
            }
        },
        "type": "bank_transfer",
        "beneficiary": {
            "type": "merchant_account",
            "merchant_account_id": "2a485b0a-a29c-4aa2-bcef-b34d0f6f8d51"
        }
    },
    "user": {
        "id": "f61c0ec7-0f83-414e-8e5f-aace86e0ed35",
        "name": "Jonathan Sandbridge",
        "email": "[email protected]",
        "phone": "+447809123456",
        "date_of_birth": "1992-11-28",
        "address": {
            "address_line1": "40 Finsbury Square",
            "city": "London",
            "state": "London",
            "zip": "EC2a 1PX",
            "country_code": "GB"
        }
    }
}

If the payment request is successful, you receive a response that contains the following fields:

FieldDescription
idThe ID for the created payment.
user.id An ID for the remitter.

An ID is generated automatically if you leave the user id blank when you create the payment.

If you use the same id as a previous payment, both payments will be associated with the ID.
resource_token A token used to authorise the created payment. Has a limited duration of 15 minutes.

The main purpose of this token is to authorise the frontend components of the authorisation flow, which must be completed for the payment to execute.

We recommend you authorise payments with TrueLayer's web or mobile UIs. However, you can use a direct API integration and build your own UI.
status The status of the payment.

🚧

Transfer limits

Be aware that some banks have limits on the amount that you can transfer in one payment. These are usually very high, but speak to us if you plan on making very high-value transactions.

EUR transfer limits tend to be higher than limits in GBP.

3. End-user payment authorisation

Your user must give consent for a payment to be made from their account successfully. They do this by choosing and confirming the bank, and sometimes the payment scheme, that the payment will use.

3.1 Select a UI

TrueLayer offers a range of out-of-the-box UIs which enable you to handle this immediately. These include the hosted payment page (HPP), embedded payment page (EPP) and native mobile SDKs. You can also configure your own authorisation flow by developing your own direct API integration.

To help decide which authorisation UI is ideal for your integration, you can use this decision tree. Start at the top and see which approach works best for you. Learn more about the options in our payment authorisation documentation.

This flow shows which authorisation UI you should use based on what integration options you support.

This flow shows which authorisation UI you should use based on what integration options you support.

The authorisation flow differs depending on the parameters you set for provider selection and scheme selection, along with other factors including the country that the payment is being made in. This is an example of what a user's first payment might look like:

3.2 Customise and integrate your UI

The steps for integrating each payment authorisation UI vary. For example with the HPP, you generate a URL and redirect your user to it. For the EPP or mobile SDKs, you configure and use an SDK.

Whatever solution you use, you can customise the look and feel of your UI. You can change aspects such as the primary, secondary, and tertiary colours. For some UIs, you can customise and preview them in Console.

For more information about how to integrate and customise your chosen UI, see our payment authorisation documentation.

4. Monitor the status of a payment

When you make a successful payment, you receive a webhook and a response which contains the id of the payment:

{
	"id": "b2c0a992-298f-4caf-99ee-b9e1e29570e1",
	"user": {
		"id": "f61c0ec7-0f83-414e-8e5f-aace86e0ed35"
	},
	"resource_token": "eyJhbGciOiJSUzUxMiIsImtpZCI6IkRCejExcEFuUGNXVndqaFBNWERuckNyQ0ZrT1p0Y2FqYWtjU21GNmJiVk0iLCJ0eXAiOiJKV1QifQ.eyJzY29wZSI6InBheW1lbnQiLCJjbGllbnRfaWQiOiJzYW5kYm94LXRvbXRlc3QtYTRkNDMyIiwianRpIjoiYjJjMGE5OTItMjk4Zi00Y2FmLTk5ZWUtYjllMWUyOTU3MGUxIiwibmJmIjoxNzEwMzMwMjAxLCJleHAiOjE3MTAzMzExMDEsImlzcyI6Imh0dHBzOi8vYXBpLnRydWVsYXllci1zYW5kYm94LmNvbS9wYXltZW50cy1nYXRld2F5IiwiYXVkIjoiaHR0cHM6Ly9hcGkudHJ1ZWxheWVyLXNhbmRib3guY29tIn0.KoRduyI0sBatLGpCrjO8rd0QqIkOsp-j_QKemkVh6OVXdOHU4Oyg-Wk2IvgJhReOWMc7e8W6llWkmCU-TQtpet6LfEZ6V6v8ItzFB8yRKN49RtYuhTCaL7k0YSJO3b5okaj5mYURDhVGN7Vs8kp2NIDVhm7hmvOvuXPp4EgUsGB-rtdGzAy21VldZJQ95B9wCdPloOr1T8pOEX3eBTrNjLlb7vDgXSt6C0TMXLSGAiCxVzZduneM375PTwbZsZSmSbO8KKBPc5nSpF5VxLnGVg9LQpYmrSSf8hupin0G3pCnAFp81ci_7OXIAR167uLKas8FN1iygV66Mq_A2hgZEA",
	"status": "authorization_required"
}

You can use this webhook and id to confirm whether your payout was successful, and take action if appropriate.

There are two ways that you can check the progress of your payout:

  • Check the webhooks sent to your webhook URI you have set in Console (recommended)
  • Make a GET request to the /v3/payments/{id} endpoint.

If you have a merchant account, you can also use the payments view in Console to see an overview of all transactions into and out of that account.

Payment webhooks

We recommend that you use webhooks to monitor all of the requests you make with the Payments API v3. You receive webhooks for all events in your integration.

Webhooks for your integration are sent to the Webhook URI you have set on the Payments > Settings page in Console. Ensure that you have set up request signing for your webhook notifications to ensure that they are reliable.

For a full list of payment webhooks, see Payment webhooks.

/v3/payments/{id} endpoint

You can use the payment id you received when you made the payment to get information about it.

To do so, make a POST request to the /v3/payments/{id} endpoint, including the payment id as a path parameter.

You receive a response in this format:

{
  "id": "0afd1f6a-f611-48ce-9488-321129bb3a70",
  "amount_in_minor": 0,
  "currency": "GBP",
  "user": {
    "id": "f9b48c9d-176b-46dd-b2da-fe1a2b77350c"
  },
  "payment_method": {
    "type": "bank_transfer",
    "provider_selection": {
      "type": "user_selected",
      "filter": {
        "countries": [
          "GB"
        ],
        "release_channel": "general_availability",
        "customer_segments": [
          "retail"
        ],
        "provider_ids": [
          "mock-payments-gb-redirect"
        ],
        "excludes": {
          "provider_ids": [
            "ob-exclude-this-bank"
          ]
        }
      },
      "scheme_selection": {
        "type": "instant_only",
        "allow_remitter_fee": false
      },
      "provider_id": "eg-provider",
      "scheme_id": "payment_scheme"
    },
    "beneficiary": {
      "type": "merchant_account",
      "merchant_account_id": "string",
      "account_holder_name": "string",
      "verification": {
        "type": "automated",
        "remitter_name": true,
        "remitter_date_of_birth": true
      }
    }
  },
  "created_at": "string",
  "metadata": {
    "prop1": "value1",
    "prop2": "value2"
  },
  "status": "authorization_required"
}

Learn more about how to get payment data with this endpoint.

Check payments in Console

In Console, you can see a list of recent transactions made to a merchant account on the Merchant account dashboard.

Alternatively, you can access more detail in the Console Payments view. Here, you can:

  • filter payments by a range of criteria.
  • view transactions for a custom period within a given month.
  • Export reports of transactions, with customisable fields.
  • Refund payments to your merchant account if you have permission.

Payment lifecycle

After you create a payment, it moves through a series of different states depending on its outcome. See the full list of payment statuses for more information.

This is the journey a payment usually follows:

  1. When a payout is first made, it has a status of authorization_required before it's sent to the payment scheme for authorisation.
  2. Once the payment has been authorised and is with the payment scheme for execution, it has a status of authorized.
    It usually takes just a few seconds for a successful payment to transition through the pending and authorized statuses.
  3. Depending on whether the payment scheme executes the payment, it transitions to:
    1. executed if the payment has been submitted to the bank successfully
    2. settled if the payment has arrived in your merchant account
    3. failed if the payment couldn't be executed.

📘

settled only applies to payments into a merchant account

Because we can guarantee that money has arrived into your merchant account, the settled payment status and webhook notification only appear if a payment is made into a merchant account.

executed and failed are the only terminal statuses for payments into an external account.

If a payment fails, the webhook contains a failure_reason that you can use to identify why it failed.