Single immediate payments

This section describes how to setup, execute, and monitor progress of a Single Immediate Payment.

A single immediate payment is a one time payment, executed immediately, that requires the user to authenticate with their bank.

Below are instructions for how to:

  1. Build a provider selection screen for your users to select their bank
  2. Create a payment
  3. Redirect a user to authenticate
  4. Handle the user returning to your application
  5. Poll for payment status

Build a provider selection screen

The providers endpoint serves two purposes:

  1. Tells you which banks are active, if a bank isn't listed then we have deactivated it temporarily until its service is returned.
  2. Gives you the assets to build out a selection screen, for example, logos and icons.

When querying the endpoint, specify capability in the query string as SingleImmediatePayment.

Each bank available will have the following fields:

idstringThis is the provider ID that you will send us in the create payment request.
logostringThis is the address of the logo asset in SVG form.
iconstringThis is the address of the icon asset in SVG form.
displayable_namestringThis is a readable name for the provider.
main_bg_colorstringThis is a hexacode color that matches the background of the logo.
supports_app_to_appboolThis indicates whether the user will be redirected to the mobile banking app if using their mobile phone. In cases where this is false, the user authenticate in their browser.
divisionsstring arrayThis array includes all divisions that are available on this provider, for example, retail and business would indicate you can use this single provider to access both retail and business accounts.
stepsarrayThis array includes any extra steps in the authentication flow that you are required to send your end user through with some banks. The results of these steps will be used in your create payment request.

We do not recommend you to store the information from the /providers endpoint locally as you should expect TrueLayer to update the response returned by the endpoint from time to time. We anticipate updates to happen a few times every quarter.

• The steps parameter structure

titlestringFriendly name for this method within the provider
fieldsarrayArray of input fields
fields.typestringInput field type. Can be a Single Choice Input or a Free Input
fields.is_sensitivebooleanOPTIONAL: For Free Input Values, is set to true for sensitive information like passwords
fields.valuesarrayOPTIONAL: For Single Choice Input, an array of values
fields.values.valuestringOPTIONAL: For Single Choice Input, input field value
fields.values.display_namestringOPTIONAL: For Single Choice Input, friendly name for this input field value
fields.validationsarrayOPTIONAL: For Free Input Values, an array of RegEx validation rules that need to be satisfied to consider the input valid
fields.allowed_charactersstringOPTIONAL: For Free Input Values, character ranges allowed. can be alphanumeric or numeric
fields.idstringUnique id for this field within the method
fields.display_namestringFriendly name for this field within the method
fields.help_textstringInput help text for the end user
fields.mandatorybooleanIndicates whether the field is required
      "displayable_name":"Natwest Sandbox",

Create a payment

This method includes the following fields:

amountintMandatoryThe amount of money you are requesting in pennies.
currencystringMandatoryThe currency code of the payment in three characters. For example, GBP or EUR.
beneficiary_referencestringMandatoryThe reference that will appear on your bank statement. Note: this can only be 18 characters or less.
beneficiary_sort_codestringMandatoryThe sort code of the receiving account (your account) if the account is a UK account (see below for EU).
beneficiary_account_numberstringMandatoryThe account number of the receiving account (your account) if the account is a UK account (see below for EU).
beneficiary_iban stringConditionalIf making payments in Central European countries the beneficiary IBAN is a compulsory field and replaces the account number and sort code.
remitter_referencestringMandatoryThe reference that will appear on the sender's bank statement. Note: this can only be 18 characters or less.
beneficiary_namestringMandatoryThe name on the receiving account.
redirect_uristringMandatoryThe URL we will redirect the user to after authorising the payment.
remitter_provider_idstringOptional / ConditionalThe ID from the providers endpoint of the bank your user has chosen. If this isn't specified the user will be sent to TrueLayer to choose their bank in the UK. For banks outside of the UK, you will need to set this.
remitter_account_numberstringOptionalThe account number of the payer, specify this if you want to lock the account from which the payment is being made if the account is a UK account (see below for EU). This may be an AML requirement.
remitter_sort_codestringOptionalThe sort code of the payer, specify this if you want to lock the account from which the payment is being made if the account is a UK account (see below for EU). This may be an AML requirement.
remitter_iban stringConditionalIf making payments in Central European countries the remitter IBAN is a compulsory field.
direct_bank_linkboolOptional / ConditionalIf set to true, you will be returned a URI directly from the bank. !WARNING! If using this, you will skip all TrueLayer optimisation and conversion may be lower on desktop. You must specify remitter_provider_id for this request to succeed. This is a required field for European Banks.
webhook_uristringOptionalAn address to send payment webhooks to with the status of your payment. This has to be https.
auth_inputs dictionaryConditionalIf the providers endpoint returns you required steps you will need to list them and their answers here. For example, banks in France require you to specify the branch name.
curl -X POST \
     -H "Authorization: Bearer ${access_token}" \
     --data '{
  "amount": 120000,
  "currency": "GBP",
  "remitter_provider_id": "ob-bank",
  "remitter_name": "Mike Smith",
  "remitter_sort_code": "987654",
  "remitter_account_number": "98765432",
  "remitter_reference": "FS-1000001",
  "beneficiary_name": "Financial Services Ltd",
  "beneficiary_sort_code": "234567",
  "beneficiary_account_number": "23456789"
  "beneficiary_reference": "FinServ-1a2b3c4d",
  "redirect_uri": ""
}' \

The request will return a simp_id that you should store as, after authorisation, the user will be redirected to your redirect_uri with this appended as payment_id.

Use the auth_uri to redirect your user to authorise the payment.

  "results": [
      "simp_id": "44708581-1967-4120-8f6a-1e532f1bf52a",
      "auth_uri": "",
      "created_at": "2018-10-01T17:00:00.0000000+00:00",
      "amount": 120000,
      "currency": "GBP",
      "remitter_provider_id": "ob-bank",
      "remitter_name": "Mike Smith",
      "remitter_sort_code": "987654",
      "remitter_account_number": "98765432",
      "remitter_reference": "FS-1000001",
      "beneficiary_name": "Financial Services Ltd",
      "beneficiary_sort_code": "234567",
      "beneficiary_account_number": "23456789",
      "beneficiary_reference": "FinServ-1a2b3c4d",
      "redirect_uri": "",
      "status": "new"

### Adapting an existing integration for EU payments (Private beta)

If you've already implemented the payments API and would now like to use our European payment capability, here are some key considerations to help you transition:

  1. Instead of account numbers and sort codes, you need to use our IBAN fields.
  2. Both the remitter and beneficiary IBANs are compulsory fields to create a payment with a European Bank in Euros.
  3. You'll need to change the currency code to EUR.
  4. European banks can only pay to European bank accounts.
  5. Some banks have additional steps required (these appear on their provider in the providers endpoint result you get back) and you'll need to complete these steps before creating the payment and pre-fill the auth_inputs field.
  6. The remitter provider ID is a compulsory field.
  7. direct_bank_link is a compulsory field.

Redirecting your user to the bank

After creating the payment, you need to redirect the user to the auth_uri.

If you did not specify the remitter_provider_id your user will be redirected to the TrueLayer Provider Selection screen and from there on to their bank.

Handling a returning user

Once the payment is authorised, the user will return to your redirect_uri. The URL will include a payment_id query parameter containing the simp_id from the payment creation response.

Managing payment status with webhooks

When the status of a payment changes, we send a single_immediate_payment_status_changed event to the uri that you specified when creating the payment.

In the header you will see the following fields:

X-TL-Webhook-Timestamptimestamptime that the webhook was sent to you. This will be in the following format 2020-05-18T10:17:47Z
Tl-SignaturestringJSON web signature with a detached payload of the form {HEADER}..{SIGNATURE}
X-Tl-SignaturestringLegacy JWS, verification using Tl-Signature should be preferred.

In the body you will see the following fields:

event_typestringdescribing which event is detailed. In this case the event will be single_immediate_payment_status_changed
event_bodyobjectcontaining both the payment_id as a string and the status as a string
Tl-Signature: "detached..jws"
X-TL-Webhook-Timestamp: 2020-05-18T10:17:52Z

  "event_type": "single_immediate_payment_status_changed",
  "event_body": {
    "payment_id": "77a75df0-af60-4785-8e91-809ac77ca8e3",
    "status": "executed"

Webhook Retry Policy

We consider a webhook as having been successfully delivered when we receive a success status code (2xx) from your webhook URI.

If we receive any other status code (for instance, if your API is temporarily unavailable), we will start retrying. Our retry policy is jittered exponential backoff. We will immediately perform some fast retries and then start waiting increasingly longer. We will keep retrying for up to 72 hours.

Validate the received webhook signature

We recommend developers to use our signing libraries to verify the Tl-Signature of the received webhooks.

E.g. Java com.truelayer.truelayer-signing


Polling for payment status

The application can poll the payment resource to see if the status has been modified. This allows the application to know if the payment was successful or not.

Note that if the remitter was specified, remitter details will also be included in the response.

The payment resource may exist in different states according to the progress of the transaction:

  • new: The payment resource has been created, but the payer has not yet authorised the payment. The initial API response will always have this status if the API call is successful.
  • authorised: The payer has successfully authorised the payment using the bank portal, but the payment has not yet been submitted for execution.
  • cancelled: The payer has cancelled the payment using the bank portal. This may also happen for some bank UIs if the payer clicks the “Back” button in their browser. This is a terminal state.
  • failed: The bank has failed to initiate a payment session, this happens after a bank has been selected but before redirecting the user to the bank UI. This is a terminal state.
  • rejected: The payer authorised the payment, but the bank rejected it after this. This is a terminal state.
  • submitted: TrueLayer has successfully submitted the authorised payment initiation request to the bank API.
  • executed: The funds have left the remitter’s account and will arrive in the beneficiary’s account. This is a terminal state.

The submitted and executed states are very close; in fact a bank may respond to the payment submission indicating the payment has already been executed. However, it is also possible for a payment to be queued within the bank for a short period of time; in that case, the payment status will initially be submitted, and then may be updated to executed after polling for a status check.

Note that after a payment has been executed, it may take some time for it to be settled, although for transactions executed via Faster Payments, this normally happens very quickly.

curl -H "Authorization: Bearer ${access_token}" \
  "results": [
      "simp_id": "c45d38a6-2384-49aa-98ab-60134a50a5d7",
      "created_at": "2018-10-01T16:00:00.0000000+00:00",
      "amount": 350,
      "currency": "GBP",
      "beneficiary_reference": "ecommerce-12345",
      "beneficiary_name": "Ecommerce Shop",
      "beneficiary_sort_code": "102030",
      "beneficiary_account_number": "88881234",
      "remitter_reference": "ECOM-12345-ABCD",
      "redirect_uri": "",
      "remitter_provider_id": "ob-lloyds",
      "status": "executed"

To see all known states of your payment and trace your payment with the timestamps, add /statuses to the end of the request.

curl -H "Authorization: Bearer ${access_token}" \
    "results": [
            "status": "New",
            "date": "2020-04-08T21:53:35.364038"
            "status": "Authorised",
            "date": "2020-04-08T21:54:17.690429"
            "status": "Submitted",
            "date": "2020-04-08T21:54:18.546706"
            "status": "Executed",
            "date": "2020-04-08T21:54:28.063325"
            "status": "Executed",
            "date": "2020-04-08T21:54:28.2761"
    "status": "queued"

Testing Guidelines

The following guidelines aim to provide practical guidance while testing the integration.

Before testing with live accounts, we recommend that you test your integration with the sandbox. The Payments Quick Start provides instructions on how to access the sandbox APIs.

When you transition to live testing in the production environment:

  1. Make sure you change all URIs to end with instead of
  2. Change from using your sandbox client_id_ and client_secret to your production client_id and client_secret. You can find your production client_id here: (you should have saved your production client_secret when you last reset it, or when you created your production account)
  3. Have a live bank account to hand which you own to make payments from, as well as one to make payments into. The payer (or remitter) bank account must be from one of the supported providers listed here

Bank Account Limits

Each bank has its own limits on how much money can be transferred using online banking, which also apply to their open banking payment APIs.

(click tab “Payment limits and timeframes”)
Bank of Scotland
(click tab FAQs)
Royal Bank of Scotland
HSBCFrom : “You can make payments of up to £25,000, per day via Online Banking if the funds are available, for larger amounts, you would need to visit an HSBC Branch with Identification and there may be a charge”
Danske Bank (see table on page 4 referencing Open Banking payment limits)
Post Office Bank (Bank of Ireland) (see item “How much money can I send?”
AIB (Allied Irish Bank)
First Trust Bank

Velocity Limits

All banks have controls in place to protect their end users from fraudulent withdrawals. One type of control is a velocity limit, which allows only a certain number of payments, or a maximum aggregate payment amount, per time period, for example, one hour, one day, and so on.

Banks will not publish these limits, as the information could be taken advantage of by fraudsters. Therefore, when testing:

  • Do not make an excessive number of payments from the same account within a short time period.
  • If it is not possible to make a successful payment, this will be visible in the bank’s authorisation user interface. At this point, it will be necessary to contact the specific bank’s end user support team to get the account unblocked.

Did this page help you?