Payments v2 to v3: single immediate payments
Learn how to migrate payments from v2, so you can create, authorise, and monitor payments.
Step 1: Single immediate payment creation call
Initiate the Payments API call from the backend, including the Bearer access_token
we got in the authentication step.
Signing requests
It is now mandatory to sign all POST API requests, including both pay-ins and payouts. You must also include certain user data within payment creation requests.
Learn more about signing requests and get links to TrueLayer request signing libraries.
Using Payments v2, you created a pay-in into your account by making an API call request to the https://pay-api.truelayer.com/v2/single-immediate-payment-initiation-requests
endpoint.
In the v2 API call request body, these values were passed:
- a
single_immediate_payment_id
that had to be passed with auuid
value, representing then the payment_id of the payment. currency
- The end user's remitter
provider_id
. - a
beneficiary
object with all the beneficiary details - an
auth_flow
object, including both thetype
and thereturn_uri
values - the
webhook_uri
, with as a value the URL where TrueLayer would send the Payment's webhook notification.
Click on the Figma link above for the full screen.
As shown in the image above, you can make the equivalent Payment creation call in v3 by hitting the https://api.truelayer.com/payments
endpoint.
Payments v2 endpoint | Payments v3 endpoint |
---|---|
https://pay-api.truelayer.com/v2/single-immediate-payment-initiation-requests | https://api.truelayer.com/v3/payments |
Then, apply the following changes in the request body (see here for the API reference):
- The beneficiary account (where the money will be sent to) must be passed in the
beneficiary
object with:type
set toexternal account
- account details inside the
account_identifier
object reference
being a mandatory field
user
is a new dictionary object that includes multiple values. Learn more about user details in Payments v3.payment_method.type
needs to be specified asbank_transfer
value.single_immediate_payment_id
is no longer passed. TrueLayer will instead automatically generate one and return it in the response payload as anid
parameter.- With Payment V3, If and only if the
provider_selection.type
value has been passed aspreselected
, then, theprovider_selection.provider_id
is passed as part of theprovider_selection
object (representing the v3 equivalent of the v2 mandatoryprovider_id
field.
Here is an example where Remitter data is also being passed in the request API and the corresponding v3 version using the preselected
type value:
Important note
This specific example shows how to convert a Payment v2 single payment API call into a Payments v3 single payment call.
Some important notes on what changes in v3:
If you want to keep your custom provider selection flow and continue to follow the Payments V2 structure that requires you to pass the remitter provider_id
in the request, v3 fully supports this. You can continue to present white-labeled provider selection and consent pages to your users (and therefore, perform the payment creation API call after the provider has been selected and passed in the request).
The Providers Endpoint and provider_id
values
provider_id
valuesIf you are currently using the v2 /providers
endpoint to fetch the provider_id
, you can still keep this logic in your code. The provider_id
values can be used for the payment_method.provider_selection.provider_id
value for payments from a specific provider. However, the deposit.provider_id
(in v3, the payment_method.provider_selection.provider_id
) is no longer mandatory in v3.
If you are currently using the v2 /providers
endpoint to fetch the provider_id
, we have now released a new version of the providers endpoint. The new endpoint is /v3/payment-providers/search
.
The provider_id
values are not changing, but there are some differences in how the endpoint works, especially:
- Endpoint is now
/v3/payment-providers/search
. - The API call is now a POST (instead of a GET).
- Instead of passing your
client_id
, the request needs to be authenticated with a valid[access_token](https://docs.truelayer.com/docs/payment-authentication)
(the request doesn't have to be signed thou).
Please check the guide on how to use the new V3 providers endpoint, /v3/payment-providers/search
.
Also you can find the API reference for the new endpoint here, which should help you with the call body configuration, based on your needs.
For example, given a Payments V2 Providers endpoint:
[GET] https://pay-api.truelayer.com/v2/single-immediate-payments-providers?country=GB,ES&auth_flow_type=redirect&account_type=sort_code_account_number,iban¤cy=GBP,EUR&client_id=penny
The Payments V3 equivalent looks like:
[POST] https://api.truelayer.com/v3/payments-providers/search
{
"currencies": [
"GBP",
"EUR"
],
"countries": [
"GB",
"ES"
],
"customer_segments": [
"retail"
],
"authorization_flow": {
"configuration": {
"redirect": {}
}
}
}
See also in the documentation/resources links above the new /v3/payments-providers/search
responses body structure.
Payment creation call
As mentioned before, the Payments V2deposit.provider_id
, which in V3 is the payment_method.provider_selection.provider_id
, is no longer mandatory in /v3/payments
creation calls.
This means that you can also create a pay-in without specifying the provider_id
the payment is coming from. Instead, the user selects their provider in the next step (which will be the payment authorisation).
Now, if you would also like to benefit from v3's out-of-the-box payment authorisation Web authorisation UIs or Mobile authorisation UIs for handling bank selection, you also don't need to pass any remitter provider information at the payment creation stage.
This also applies to payment scheme selection. You do not need to provide a scheme.id
in the payment creation call. Instead, you can enable your user to select the payments rail they would like to use as part of the authorisation flow. See the scheme selection docs to explore V3 available payment scheme options.
The Payments V2 auth_flow
object, as you can see above, is not passed in V3 payment creation requests. It will be passed in the payment authorisation step, which happens after the payment creation.
With Payments APIs, after the payment creation request to https://pay-api.truelayer.com/v2/single-immediate-payment-initiation-requests
the API response includes a direct link to the provider specified in the request.
Instead, with Payments v3, the https://api.truelayer.com/payments
request will create a payment that will still have to be authorised. It will return an object including the following:
{
"id": "e9931912-da0b-4aa7-8209-357741836691",
"user":
{
"id": "f61c0ec7-0f83-414e-8e5f-aace86e0ed35"
},
"resource_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6InBheW1lbnQiLCJjbGllbnRfaWQiOiJzYW5kYm94LWRhcnlsdGVzdC03NmI5MDgiLCJqdGkiOiJlOTkzMTkxMi1kYTBiLTRhYTctODIwOS0zNTc3NDE4MzY2OTEiLCJuYmYiOjE2NjMxNzIwMzQsImV4cCI6MTY2MzE3MjkzNCwiaXNzIjoiaHR0cHM6Ly9hcGkudHJ1ZWxheWVyLXNhbmRib3guY29tIiwiYXVkIjoiaHR0cHM6Ly9hcGkudHJ1ZWxheWVyLXNhbmRib3guY29tIn0.yjQHGEASEJmvpl-PTxkngXWwVpzoWSWnuIQb_6bKaCU",
"status": "authorization_required"
}
Where:
id
is thepayment_id
(ordeposit_id
)user.id
is theuser.id
being passed in the request. If nouser.id
is passed in the request, TrueLayer will generate one and return it here. Eventually,user.id
should be uniquely associated to the PSU (end user) data that is doing the payment.resource_token
is the token that you use in payment authorisation if and only if you want to use TrueLayer UIs (HPP, EPP, SDK) for the payment authorisation flow.
Payments Resource tokens are valid for 15 minutes
After 15 minutes, the
resource_token
associated with the payment expires, causing the payment itself to fail.The status of the payment will move to
expired
, instead of remaining ininitiated
indefinitely.
The payment has now been created. Its status is authorization_required
.
In the next step, the payment will be authorised.
Step 2: Payment authorisation
Using Payments v3 UI/UX components [recommended]
In most circumstances, to authorise the payment, we recommend that you use the TrueLayer UI components (the hosted payment page, embedded payment page or mobile SDKs). These enable you to benefit from a smoother integration experience and better scalability as you expanding into new geographies. As TrueLayer UI components evolve, we support all possible different requirements from all supported providers (for example, additional screens for if you need to pass additional inputs such as branch name).
Important: If you are expanding in the EU, integration becomes more complex without using the embedded/hosted payment pages or SDKs. In some cases (German banks using embedded flows) they are actually mandatory if you are not regulated as a PISP (operating with TrueLayer certificates).
If you’d like to know more about how to use the TrueLayer UX/UI components for payment authorisation, see our docs.
Using Payments v3 direct API integration [not recommended]
If you are currently integrated with Payments v2, and especially if you are going to operate in the UK only, and need to keep your current white labeled frontend, you have the option of adopting a Direct API integration, handling payment authorisation using TrueLayer APIs from the backend.
In general, this is NOT the recommended approach, as we strongly recommend to use TrueLayer UI/UX components, which are designed to provide the best experience to your users, including handling all possible bank flows and an out of the box QR code (for UK) to otpimise conversion bringing the authorization process on mobile, leveraging the bank mobile app.
However, if you need to use a DirectAPI approach, keep reading.
As explained in the previous section, once the Payment is created, you will get in the response:
- The
payment_id
- The
user.id
To progress with payment authorisation, make an API call to a new endpoint:
https://api.truelayer.com/payments/<payment_id>/authorization-flow
.
This will return the return_uri
(which corresponds to the redirect_uri
in the PayDirect APIs).
The JSON body is:
{
"provider_selection": {},
"redirect": {
"return_uri": "{{RETURN_URI}}"
}
}
This is where auth flow information is passed.
In v3, the return_uri
corresponds to the auth_flow.return_uri
that was passed in the Payments v2 payment creation call.
The provider_id
is passed during payment creation, so the response now contains the direct link to the bank. The user needs to be directed to this link to authenticate and authorise the payment with their bank.
{
"status": "authorizing",
"authorization_flow": {
"actions": {
"next": {
"type": "redirect",
"uri": "https://pay-mock-connect.truelayer-sandbox.com/login/73b3a702-8441-44e4-baf0-462bb07f1d39#token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3M2IzYTcwMi04NDQxLTQ0ZTQtYmFmMC00NjJiYjA3ZjFkMzkiLCJzY29wZSI6InBheS1tb2NrLWNvbm5lY3QtYXBpIiwibmJmIjoxNjcxNDUxNDA4LCJleHAiOjE2NzE0NTUwMDgsImlzcyI6Imh0dHBzOi8vcGF5LW1vY2stY29ubmVjdC50cnVlbGF5ZXItc2FuZGJveC5jb20iLCJhdWQiOiJodHRwczovL3BheS1tb2NrLWNvbm5lY3QudHJ1ZWxheWVyLXNhbmRib3guY29tIn0.hTDULBpxulHeSEQd4lHb_xRTwQCTtlFTZPdILaSs98k"
}
}
}
}
If no
provider_selection.provider_id
was passed in payment creation, the response at this point would have been a list of providers to be presented to the end user.You will then need an additional
/submit-provider-selection
API call to submit the provider being selected.
Step 3: Consume webhooks and payment statuses
Once the payment authorisation process is complete, the user is redirected back to the return_uri
. Now you just have to display indications to the user based on the payment status received via webhooks.
With Payments API v3, these are the payment statuses to expect:
Below is an explanation of what each status means:
Status | Description | Notification method |
---|---|---|
authorization_required | The payment has been created successfully. No further action has been taken. | Status only via /GET /payments/{payment_id} |
authorizing | The end user has started the authorisation journey by interacting with the Hosted Payments Page or your UI. They have not completed the journey yet. | Status only via /GET /payments/{payment_id} |
authorized | The end user has completed the authorization journey. The payment has successfully completed its authorization flow. | Status only via /GET /payments/{payment_id} |
payment_executed | TrueLayer has successfully submitted the payment to the bank and the bank has confirmed it as accepted. This does not mean that the payment will settle in the creditor’s account. | Status via /GET /payments/{payment_id} Webhook sent to your endpoint |
payment_failed | The payment has failed to transition to the next status. Within this notification, TrueLayer will provide information to why the payment was not successful. The failure reason will be shared in the failure_reason field on the payment resource and the failure_stage field will share at which payment status the payment has transitioned to failed. This is a terminal status | Status via /GET /payments/{payment_id} Webhook sent to your endpoint |
We consider a webhook as 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. If we continue to receive any status codes besides 2xx ones after retrying for 72 hours, we will discard the webhook.
We apply this retry policy to payments, payment refunds, payouts, and mandates.
See the following sections for more detailed information about payments statuses in V3 and the possible payment failure_reasons
.
Payment webhook examples
We recommend that developers use our signing libraries to verify the
Tl-Signature
of the received webhooks.Add webhook URLs in the TrueLayer Console. See Setting up the TrueLayer Console.
{
"type": "payment_executed",
"event_version": 1,
"event_id": "ed5c3c60-6760-4830-86c3-bced4ce63f21",
"payment_id": "e9931912-da0b-4aa7-8209-357741836691",
"payment_method":
{
"type": "bank_transfer",
"provider_id": "mock-payments-gb-redirect",
"scheme_id": "faster_payments_service"
},
"executed_at": "2022-09-14T16:14:24.217Z",
"metadata":
{
"brand": "TL Casino"
}
}
{
"type": "payment_failed",
"event_version": 1,
"event_id": "8dfba42f-72db-4aa1-b573-e0602ca65506",
"payment_id": "09baadd0-499f-480f-a451-0ed6cd74593e",
"payment_method":
{
"type": "bank_transfer"
},
"failed_at": "2022-09-14T16:22:00.528Z",
"failure_stage": "authorizing",
"failure_reason": "canceled",
"metadata":
{
"brand": "TL Casino"
}
}
Add webhook URLs in the TrueLayer Console. See Setting up the TrueLayer Console.
{
"type": "payment_executed",
"event_version": 1,
"event_id": "ed5c3c60-6760-4830-86c3-bced4ce63f21",
"payment_id": "e9931912-da0b-4aa7-8209-357741836691",
"payment_method":
{
"type": "bank_transfer",
"provider_id": "mock-payments-gb-redirect",
"scheme_id": "faster_payments_service"
},
"executed_at": "2022-09-14T16:14:24.217Z",
"metadata":
{
"brand": "TL Casino"
}
}
{
"type": "payment_failed",
"event_version": 1,
"event_id": "8dfba42f-72db-4aa1-b573-e0602ca65506",
"payment_id": "09baadd0-499f-480f-a451-0ed6cd74593e",
"payment_method":
{
"type": "bank_transfer"
},
"failed_at": "2022-09-14T16:22:00.528Z",
"failure_stage": "authorizing",
"failure_reason": "canceled",
"metadata":
{
"brand": "TL Casino"
}
}
Updated 2 months ago