PHPackages                             truelayer/client - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Payment Processing](/categories/payments)
4. /
5. truelayer/client

ActiveLibrary[Payment Processing](/categories/payments)

truelayer/client
================

TrueLayer's payments platform client

v3.3.0(8mo ago)434.0k↓36.3%12[3 PRs](https://github.com/TrueLayer/truelayer-php/pulls)1MITPHPPHP ^8.1CI passing

Since May 4Pushed 7mo ago17 watchersCompare

[ Source](https://github.com/TrueLayer/truelayer-php)[ Packagist](https://packagist.org/packages/truelayer/client)[ RSS](/packages/truelayer-client/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (16)Versions (39)Used By (1)

Quick Links
-----------

[](#quick-links)

1. [Why use this package?](#why)
2. [Getting started](#getting-started)
3. [Caching](#caching)
4. [Converting to and from arrays](#arrays)
5. [Creating a payment](#creating-a-payment)
    1. [Creating a beneficiary](#creating-a-beneficiary)
    2. [Creating a user](#creating-a-user)
    3. [Creating a payment method](#creating-a-payment-method)
    4. [Creating the payment](#creating-the-payment)
    5. [Creating a payment from an array](#creating-a-payment-from-array)
    6. [Redirecting to the Hosted Payments Page](#redirect-to-hpp)
6. [Retrieving a payment's details](#retrieving-a-payment)
    1. [Get the user](#get-the-user)
    2. [Get the payment method and beneficiary](#get-the-payment-method)
    3. [Check a payment's status](#check-payment-status)
    4. [Working with status specific payment fields](#payment-status-specific-fields)
        1. [Authorization Required Status](#status-authorization-required)
        2. [Authorizing Status](#status-authorizing)
            1. [Provider selection action](#action-provider-selection)
            2. [Redirect action](#action-redirect)
            3. [Wait action](#action-wait)
        3. [Authorized Status](#status-authorized)
        4. [Executed Status](#status-executed)
        5. [Settled Status](#status-settled)
        6. [Failed Status](#status-failed)
        7. [Attempt Failed Status](#status-attempt-failed)
        8. [Authorization flow config](#auth-flow-config)
        9. [Source of funds](#source-of-funds)
7. [Cancel a payment](#payment-cancellation)
8. [Authorizing a payment](#authorizing-payment)
9. [Refunds](#refunds)
10. [Payouts](#payouts)
11. [Merchant accounts](#merchant-accounts)
12. [Account identifiers](#account-identifiers)
13. [SignUp Plus](#signup-plus)
14. [Receiving webhook notifications](#webhooks)
15. [Custom idempotency keys](#idempotency)
16. [Custom API calls](#custom-api-calls)
17. [Error Handling](#error-handling)

Why use this package?
---------------------

[](#why-use-this-package)

This package simplifies working with the TrueLayer API, by:

1. Handling authentication (including token expiry) and caching
2. Signing requests
3. Managing idempotency keys, including retrying on conflicts
4. Retrying failed requests, where it makes sense to do so
5. Providing type-hinted methods and classes to work with

Getting started
---------------

[](#getting-started)

### Installation

[](#installation)

The library will require an HTTP client that implements [PSR-18](https://www.php-fig.org/psr/psr-18/).

```
composer require truelayer/client

```

If a PSR-18 client isn't installed, Composer will let you know. You can simply require one, such as Guzzle:

```
composer require guzzlehttp/guzzle truelayer/client

```

### Initialisation

[](#initialisation)

You will need to go to the TrueLayer console and create your credentials which you can then provide to the Client configurator:

```
$client = \TrueLayer\Client::configure()
    ->clientId($clientId)
    ->clientSecret($clientSecret)
    ->keyId($kid)
    ->pemFile($pemFilePath) // Or ->pem($contents) Or ->pemBase64($contents)
    ->create();
```

By default, the client library will initialise in `sandbox` mode. To switch to production call `useProduction()`:

```
$client = \TrueLayer\Client::configure()
    ...
    ->useProduction() // optionally, pass a boolean flag to toggle between production/sandbox mode.
    ->create();
```

This library assumes that your client\_id is issued with the `payments` scope. Depending on your account type this may not be the case and the authentication server will return an `invalid_scope` error. You can override the scopes used by the library with the `scopes()` method:

```
$client = \TrueLayer\Client::configure()
    ...
    ->scopes('foo', 'bar')
    ->create();
```

If needed, you can also provide your own HTTP client instance:

```
$client = \TrueLayer\Client::configure()
    ...
    ->httpClient($myPSR18Client)
    ->create();
```

Caching
-------

[](#caching)

The client library supports caching the `client_credentials` grant access token needed to access, create and modify resources on TrueLayer's systems. In order to enable it, you need to provide an implementation of the [PSR-16](https://www.php-fig.org/psr/psr-16/) common caching interface and a 32-bytes encryption key.

You can generate a random encryption key by running `openssl rand -hex 32`. This key must be considered secret and stored next to the client secrets obtained from TrueLayer's console.

```
$client = \TrueLayer\Client::configure()
    ...
    ->cache($cacheImplementation, $encryptionKey)
    ->create();
```

A good example of a caching library that implements PSR-16 is [illuminate/cache](https://github.com/illuminate/cache).

Converting to and from arrays
-----------------------------

[](#converting-to-and-from-arrays)

If you want to skip calling each setter method, you can use arrays to create any resource:

```
$client->beneficiary()->fill($beneficiaryData);
$client->user()->fill($userData);
$client->payment()->fill($paymentData);
// etc...
```

You can also convert any resource to array. This can be convenient if you need to output it to json for example:

```
$paymentData = $client->getPayment($paymentId)->toArray();
```

Creating a payment
------------------

[](#creating-a-payment)

### 1. Creating a beneficiary

[](#1-creating-a-beneficiary)

*Merchant account beneficiary*

```
// If the merchant account id is known:
$beneficiary = $client->beneficiary()->merchantAccount()
    ->merchantAccountId('a2dcee6d-7a00-414d-a1e6-8a2b23169e00');

// Alternatively you can retrieve merchant accounts and use one of them directly:
$merchantAccounts = $client->getMerchantAccounts();

// Select the merchant account you need...
$merchantAccount = $merchantAccounts[0];

$beneficiary = $client->beneficiary()->merchantAccount($merchantAccount);
```

If your merchant account is configured for payment verification then you have the option to enable automated remitter verification for your Merchant Account payment:

```
$remitterVerification = $client
    ->remitterVerification()
    ->automated()
    ->remitterName(true)
    ->remitterDateOfBirth(true);

$beneficiary = $client->beneficiary()
    ->merchantAccount()
    ->merchantAccountId('a2dcee6d-7a00-414d-a1e6-8a2b23169e00')
    ->verification($remitterVerification);
```

For your *merchant account beneficiary* you can pass a statement reference that should be set on the end user's statement. Not all banks support setting such a reference, this value will be used wherever possible.

```
$beneficiary->statementReference('Statement reference.');
```

*External account beneficiary - Sort code &amp; account number*

```
$beneficiary = $client->beneficiary()->externalAccount()
    ->reference('Transaction reference')
    ->accountHolderName('John Doe')
    ->accountIdentifier(
        $client->accountIdentifier()->sortCodeAccountNumber()
            ->sortCode('010203')
            ->accountNumber('12345678')
    );
```

*External account beneficiary - IBAN*

```
$beneficiary = $client->beneficiary()->externalAccount()
    ->reference('Transaction reference')
    ->accountHolderName('John Doe')
    ->accountIdentifier(
        $client->accountIdentifier()->iban()
            ->iban('GB53CLRB04066200002723')
    );
```

### 2. Creating a user

[](#2-creating-a-user)

```
use TrueLayer\Constants\UserPoliticalExposures;

$user = $client->user()
    ->name('Jane Doe')
    ->phone('+44123456789')
    ->email('jane.doe@truelayer.com')
    ->dateOfBirth('2024-01-01');

// You can also set the user's political exposure field if you need to
$user->politicalExposure(UserPoliticalExposures::CURRENT);
```

You are also able to set the user's address:

```
$address = $client->user()
    ->address()
    ->addressLine1('The Gilbert')
    ->addressLine2('City of')
    ->city('London')
    ->state('London')
    ->zip('EC2A 1PX')
    ->countryCode('GB');
```

### 3. Creating a payment method

[](#3-creating-a-payment-method)

You can create a bank transfer payment method with minimal configuration:

```
$paymentMethod = $client->paymentMethod()->bankTransfer()
    ->beneficiary($beneficiary);
```

Optionally, you can filter the providers that will be returned in the authorisation flow:

```
use TrueLayer\Constants\Countries;
use TrueLayer\Constants\CustomerSegments;
use TrueLayer\Constants\ReleaseChannels;

// You can filter the providers that will be returned:
$filter = $client->providerFilter()
    ->countries([Countries::GB, Countries::ES])
    ->customerSegments([CustomerSegments::RETAIL, CustomerSegments::CORPORATE])
    ->releaseChannel(ReleaseChannels::PRIVATE_BETA)
    ->excludesProviderIds(['provider-id'])

// You can also filter providers by the schemes they support:
$schemeSelection = $client->schemeSelection()->userSelected(); // Let the user select. You must provide your own UI for this.
$schemeSelection = $client->schemeSelection()->instantOnly(); // Only allow providers that support instant payments
$schemeSelection = $client->schemeSelection()->instantPreferred(); // Prefer providers that allow instant payments, but allow defaulting back to non-instant payments if unavailable.

// For instant only and instant preferred, you can also allow or disallow remitter fees:
$schemeSelection->allowRemitterFee(true); // Unless explicitly set, this will default to false.

// Create the provider selection configuration
$providerSelection = $client->providerSelection()->userSelected()
    ->filter($filter)
    ->schemeSelection($schemeSelection);

// Create the payment method
$paymentMethod = $client->paymentMethod()->bankTransfer()
    ->providerSelection($providerSelection);
```

Alternatively, you can preselect the provider that is going to be used in the authorisation flow as well as the payment scheme that the payment is going to be sent on:

```
// Preselect the payment scheme
$schemeSelection = $client->schemeSelection()
    ->preselected()
    ->schemeId('faster_payments_service');

// Preselect the provider
$providerSelection = $client->providerSelection()
    ->preselected()
    ->providerId('mock-payments-gb-redirect')
    ->schemeSelection($schemeSelection);

// Create the payment method
$paymentMethod = $client->paymentMethod()->bankTransfer()
    ->providerSelection($providerSelection);
```

You can also enable payment retries, but make sure you can handle the `attempt_failed` payment status beforehand:

```
$paymentMethod = $client->paymentMethod()->bankTransfer()
    ->enablePaymentRetry()
    ->beneficiary($beneficiary);
```

### 4. Creating the payment

[](#4-creating-the-payment)

```
$payment = $client->payment()
    ->user($user)
    ->amountInMinor(1)
    ->currency(\TrueLayer\Constants\PaymentCurrencies::GBP) // You can use other currencies defined in this class.
    ->metadata([ // add custom key value pairs
        'key' => 'value'
    ])
    ->paymentMethod($paymentMethod)
    ->create();
```

You then get access to the following methods:

```
$payment->getId(); // The payment id
$payment->getResourceToken(); // The resource token
$payment->getDetails(); // Get the payment details, same as $client->getPayment($paymentId)
$payment->hostedPaymentsPage(); // Get the Hosted Payments Page helper, see below.
$payment->toArray(); // Convert to array
```

### 5. Creating a payment from an array

[](#5-creating-a-payment-from-an-array)

If you prefer, you can work directly with arrays by calling the `fill` method:

```
$paymentData = [
    'amount_in_minor' => 1,
    'currency' => PaymentCurrencies::GBP,
    'payment_method' => [
        'type' => PaymentMethods::BANK_TRANSFER,
        'beneficiary' => [
            'account_identifier' => [
                'account_number' => '12345678',
                'sort_code' => '010203',
                'type' => 'sort_code_account_number',
            ],
            'reference' => 'Transaction reference',
            'account_holder_name' => 'John Doe',
            'type' => 'external_account',
        ],
        'provider_selection' => [
            'type' => PaymentMethods::PROVIDER_TYPE_USER_SELECTION,
            'filter' => [
                'countries' => [
                    Countries::GB,
                ],
                'release_channel' => ReleaseChannels::PRIVATE_BETA,
                'customer_segments' => [
                    CustomerSegments::RETAIL,
                ],
                'provider_ids' => [
                    'mock-payments-gb-redirect',
                ],
                'excludes' => [
                    'provider_ids' => [],
                ],
            ],
        ],
    ],
];

$payment = $client->payment()->fill($paymentData)->create();
```

### 6. Redirecting to the Hosted Payments Page

[](#6-redirecting-to-the-hosted-payments-page)

TrueLayer's Hosted Payment Page provides a high-converting UI for payment authorization that supports, out of the box, all action types. You can easily get the URL to redirect to after creating your payment:

```
$url = $client->payment()
    ...
    ->create()
    ->hostedPaymentsPage()
    ->returnUri('http://www.mymerchantwebsite.com')
    ->primaryColour('#000000')
    ->secondaryColour('#e53935')
    ->tertiaryColour('#32329f')
    ->toUrl();
```

Retrieving a payment's details
==============================

[](#retrieving-a-payments-details)

```
$payment = $client->getPayment($paymentId);
$payment->getId();
$payment->getUserId();
$payment->getAmountInMinor();
$payment->getCreatedAt();
$payment->getCurrency();
$payment->getPaymentMethod();
$payment->getMetadata();
$payment->toArray();
```

Get the payment method and beneficiary
--------------------------------------

[](#get-the-payment-method-and-beneficiary)

```
use TrueLayer\Interfaces\PaymentMethod\BankTransferPaymentMethodInterface;
use TrueLayer\Interfaces\Payment\Beneficiary\ExternalAccountBeneficiaryInterface;
use TrueLayer\Interfaces\Payment\Beneficiary\MerchantBeneficiaryInterface;

$method = $client->getPayment($paymentId)->getPaymentMethod();

if ($method instanceof BankTransferPaymentMethodInterface) {
    $providerSelection = $method->getProviderSelection();
    $beneficiary = $method->getBeneficiary();
    $beneficiary->getAccountHolderName();

    if ($beneficiary instanceof ExternalAccountBeneficiaryInterface) {
        $beneficiary->getReference();
        $beneficiary->getAccountIdentifier(); // See account identifiers documentation
    }

    if ($beneficiary instanceof MerchantBeneficiaryInterface) {
        $beneficiary->getReference();
        $beneficiary->getMerchantAccountId();
    }
}
```

Check a payment's status
------------------------

[](#check-a-payments-status)

You can check for the status by using one of the following helper methods:

```
$payment = $client->getPayment($paymentId);
$payment->isAuthorizationRequired();
$payment->isAuthorizing();
$payment->isAuthorized(); // Will also return false when the payment has progressed to executed, failed or settled states.
$payment->isExecuted(); // Will also return false when the payment has progressed to failed or settled states.
$payment->isSettled();
$payment->isFailed(); // Payment has failed
$payment->isAttemptFailed(); // Payment attempt has failed, only available if payment retries are enabled.
```

Or you can get the status as a string and compare it to the provided constants in `PaymentStatus`:

```
$payment = $client->getPayment($paymentId);
$payment->getStatus() === \TrueLayer\Constants\PaymentStatus::AUTHORIZATION_REQUIRED;
```

Working with status specific payment fields
-------------------------------------------

[](#working-with-status-specific-payment-fields)

### Authorization Required Status

[](#authorization-required-status)

> Payment with this status is on its initial phase where no action beyond the creation of the payment was taken.

```
use TrueLayer\Interfaces\Payment\PaymentAuthorizationRequiredInterface;

if ($payment instanceof PaymentAuthorizationRequiredInterface) {
    // Your logic here, you would normally start the authorization process.
}
```

### Authorizing Status

[](#authorizing-status)

> Payment has its authorization\_flow started, but the authorization has not completed yet

A payment in `Authorizing` will expose 2 additional methods for retrieving:

- the [authorization flow config](#auth-flow-config)
- the next action in the payment authorization user journey

```
use TrueLayer\Interfaces\Payment\PaymentAuthorizingInterface;

if ($payment instanceof PaymentAuthorizingInterface) {
    $payment->getAuthorizationFlowConfig(); // see authorization flow config

    // Will return a \TrueLayer\Interfaces\Payment\AuthorizationFlow\Action\ActionInterface
    $payment->getAuthorizationFlowNextAction();
}
```

#### Provider selection action

[](#provider-selection-action)

This action indicates that the user needs to select a provider from the provided list. To render the provider list, each provider comes with helpful methods for retrieving the name, logo, id, etc.

```
use TrueLayer\Interfaces\Payment\AuthorizationFlow\Action\ProviderSelectionActionInterface;

$nextAction = $payment->getAuthorizationFlowNextAction();

if ($nextAction instanceof ProviderSelectionActionInterface) {
    foreach ($nextAction->getProviders() as $provider) {
        $provider->getId();
        $provider->getDisplayName();
        $provider->getCountryCode();
        $provider->getLogoUri();
        $provider->getIconUri();
        $provider->getBgColor();
    }
}
```

#### Redirect action

[](#redirect-action)

This action indicates that the user needs to be redirected to complete the authorization process.

```
use TrueLayer\Interfaces\Payment\AuthorizationFlow\Action\RedirectActionInterface;

$nextAction = $payment->getAuthorizationFlowNextAction();

if ($nextAction instanceof RedirectActionInterface) {
    $nextAction->getUri(); // The URL the end user must be redirected to
    $nextAction->getProvider(); // The provider object, see available methods above.
}
```

#### Wait action

[](#wait-action)

```
use TrueLayer\Interfaces\Payment\AuthorizationFlow\Action\WaitActionInterface;

$nextAction = $payment->getAuthorizationFlowNextAction();

if ($nextAction instanceof WaitActionInterface) {
    // your logic here
}
```

### Authorized Status

[](#authorized-status)

> Payment has successfully completed its authorization flow

```
use TrueLayer\Interfaces\Payment\PaymentAuthorizedInterface;

if ($payment instanceof PaymentAuthorizedInterface) {
    $payment->getAuthorizationFlowConfig(); // see authorization flow config
    $payment->getCreditableAt(); // The date and time that TrueLayer determined that the payment was ready to be credited.
}
```

### Executed Status

[](#executed-status)

> Payment has been accepted by the bank

```
use TrueLayer\Interfaces\Payment\PaymentExecutedInterface;

if ($payment instanceof PaymentExecutedInterface) {
    $payment->getExecutedAt(); // The date and time the payment was executed at
    $payment->getCreditableAt(); // The date and time that TrueLayer determined that the payment was ready to be credited.
    $payment->getAuthorizationFlowConfig(); // See authorization flow config
}
```

### Settled Status

[](#settled-status)

> Payment can transition into this state if the beneficiary account was a merchant account within Truelayer, and Truelayer has observed the money to be settled.

```
use TrueLayer\Interfaces\Payment\PaymentSettledInterface;

if ($payment instanceof PaymentSettledInterface) {
    $payment->getExecutedAt(); // The date and time the payment was executed at
    $payment->getSettledAt(); // The date and time the payment was settled at
    $payment->getAuthorizationFlowConfig(); // See authorization flow config
    $payment->getSourceOfFunds(); // See source of funds
    $payment->getCreditableAt(); // The date and time that TrueLayer determined that the payment was ready to be credited.
}
```

### Failed Status

[](#failed-status)

> Payment has failed. The reason for failure can be observed in failure\_reason field on the payment resource

```
use TrueLayer\Interfaces\Payment\PaymentFailedInterface;

if ($payment instanceof PaymentFailedInterface) {
    $payment->getFailedAt(); // The date and time the payment failed at
    $payment->getFailureStage(); // The status the payment was when it failed, one of `authorization_required`, `authorizing` or `authorized`
    $payment->getFailureReason(); // The reason the payment failed. Handle unexpected values gracefully as an unknown failure.
    $payment->getAuthorizationFlowConfig(); // see authorization flow config
    $payment->getCreditableAt(); // The date and time that TrueLayer determined that the payment was ready to be credited.
}
```

### Attempt Failed Status

[](#attempt-failed-status)

> Status only available when you enable payment retries.

```
use TrueLayer\Interfaces\Payment\PaymentAttemptFailedInterface;

if ($payment instanceof PaymentAttemptFailedInterface) {
    $payment->getFailedAt(); // The date and time the payment failed at
    $payment->getFailureStage(); // The status the payment was when it failed, one of `authorization_required`, `authorizing` or `authorized`
    $payment->getFailureReason(); // The reason the payment failed. Handle unexpected values gracefully as an unknown failure.
    $payment->getAuthorizationFlowConfig(); // see authorization flow config
}
```

### Authorization flow config

[](#authorization-flow-config)

This object provides information about the authorization flow the payment went through.

```
use TrueLayer\Interfaces\Payment\PaymentExecutedInterface;

if ($payment instanceof PaymentExecutedInterface) {
    $config = $payment->getAuthorizationFlowConfig();
    $config->isRedirectSupported() // Is redirect supported or not
    $config->getRedirectReturnUri(); // The URL the user will be redirected back once the flow on the third-party's website is completed
    $config->isProviderSelectionSupported(); // Is provider selection supported or not
}
```

### Source of funds

[](#source-of-funds)

```
use TrueLayer\Interfaces\Payment\PaymentExecutedInterface;
use TrueLayer\Interfaces\Payment\PaymentSettledInterface;
use TrueLayer\Interfaces\SchemeIdentifier\ScanDetailsInterface;
use TrueLayer\Interfaces\SchemeIdentifier\IbanDetailsInterface;
use TrueLayer\Interfaces\SchemeIdentifier\BbanDetailsInterface;
use TrueLayer\Interfaces\SchemeIdentifier\NrbDetailsInterface;

if ($payment instanceof PaymentExecutedInterface || $payment instanceof PaymentSettledInterface) {
    $paymentSource = $payment->getPaymentSource();
    $paymentSource->getAccountHolderName(); // The unique ID for the external account
    $paymentSource->getId();
    $paymentSource->toArray();

    foreach ($paymentSource->getAccountIdentifiers() as $accountIdentifier) {
       // See 'Account identifiers' for available methods.
    }
}
```

Cancel a payment
================

[](#cancel-a-payment)

You can cancel a retrieved payment as long as it's not been authorised yet. Please see our documentation on [payment cancellation](https://docs.truelayer.com/docs/cancel-a-payment) for further details.

> The `cancel` method returns a fresh version of the retrieved payment

```
$payment = $client->getPayment($paymentId);
$cancelledPayment = $payment->cancel();
```

Authorizing a payment
=====================

[](#authorizing-a-payment)

Using the Hosted Payments Page
------------------------------

[](#using-the-hosted-payments-page)

You are encouraged to use our [HPP](https://docs.truelayer.com/docs/hosted-payment-page) which collects all payment information required from your users and guides them through the payment authorisation journey. To do this simply redirect to the HPP after creating a payment. See [Redirecting to HPP](#redirect-to-hpp) to get started.

Manually starting the authorization flow
----------------------------------------

[](#manually-starting-the-authorization-flow)

In some cases you may want to start the authorization flow manually (for example if you want to render your own provider selection screen).

This library has incomplete support for the authorization flow. To complete the authorization flow, you will need to eventually redirect the user to the HPP or implement missing features using direct API calls ( see [Custom API calls](#custom-api-calls)).

```
use TrueLayer\Constants\FormInputTypes;

$payment = $client->payment()->create();

// If you are planning to start the authorization flow manually then hand over to the HPP:
$payment->authorizationFlow()
    ->returnUri($myReturnUri)
    ->useHPPCapabilities()
    ->start();

// If you are planning to build a fully custom UI, you need to manually specify which features your UI is able to support:
$payment->authorizationFlow()
    ->returnUri($myReturnUri)
    ->enableProviderSelection() // Can the UI render a provider selection screen?
    ->enableSchemeSelection() // Can the UI render a scheme selection screen?
    ->enableUserAccountSelection() // Can the UI render a user account selection screen?
    ->formInputTypes([FormInputTypes::TEXT, FormInputTypes::TEXT_WITH_IMAGE, FormInputTypes::SELECT]) // Can the UI render form inputs for the end user to interact with? Which input types can it handle?
    ->start();
```

Once the authorization flow has been started, refer to [Authorizing payments](#status-authorizing) to understand how to handle the returned actions.

### Submitting a provider

[](#submitting-a-provider)

If your payment requires selecting a provider as its next action, you can render the provider list and then submit the user selection using the `submitProvider` method:

```
$client->submitPaymentProvider($payment, $provider);
```

Refunds
=======

[](#refunds)

Refunds are only supported for settled merchant account payments.

Creating and retrieving refunds from the client
-----------------------------------------------

[](#creating-and-retrieving-refunds-from-the-client)

```
use TrueLayer\Interfaces\Payment\RefundRetrievedInterface;
use TrueLayer\Interfaces\Payment\RefundExecutedInterface;
use TrueLayer\Interfaces\Payment\RefundFailedInterface;

// Create and get the refund id
$refundId = $client->refund()
    ->payment($paymentId) // Payment ID, PaymentRetrievedInterface or PaymentCreatedInterface
    ->amountInMinor(1)
    ->reference('My reference')
    ->metadata([
        "foo" => "bar",
        "baz" => "qux",
    ])
    ->create()
    ->getId();

// Get a refund's details
$refund = $client->getRefund($paymentId, $refundId);

// Common refund methods
$refund->getId();
$refund->getAmountInMinor();
$refund->getCurrency();
$refund->getReference();
$refund->getMetadata();
$refund->getStatus();
$refund->getCreatedAt();
$refund->isPending();
$refund->isAuthorized();
$refund->isExecuted();
$refund->isFailed();

// Executed refunds
if ($refund instanceof RefundExecutedInterface) {
    $refund->getExecutedAt();
}

// Failed refunds
if ($refund instanceof RefundFailedInterface) {
    $refund->getFailureReason();
    $refund->getFailedAt();
}

// Get all refunds for a payment
$refunds = $client->getRefunds($paymentId); // RefundRetrievedInterface[]
```

Creating and retrieving refunds from a settled payment
------------------------------------------------------

[](#creating-and-retrieving-refunds-from-a-settled-payment)

Alternatively, if you already have a payment instance you can use the following convenience methods:

```
use TrueLayer\Interfaces\Payment\PaymentSettledInterface;

if ($payment instanceof PaymentSettledInterface) {
    // Create a refund
    $refundId = $payment->refund()
        ->amountInMinor(1)
        ->reference('My reference')
        ->metadata([
            "foo" => "bar",
            "baz" => "qux",
        ])
        ->create()
        ->getId();

    // Get a refund's details
    $payment->getRefund($refundId)

    // Get all refunds
    $payment->getRefunds();
}
```

Payouts
=======

[](#payouts)

Creating a payout to an external beneficiary
--------------------------------------------

[](#creating-a-payout-to-an-external-beneficiary)

```
$accountIdentifier = $client->accountIdentifier()
    ->iban()
    ->iban('GB29NWBK60161331926819');

$beneficiary = $client->payoutBeneficiary()->externalAccount()
    ->accountHolderName('John Doe')
    ->reference('My reference')
    ->accountIdentifier($accountIdentifier);

$payout = $client->payout()
    ->amountInMinor(1)
    ->beneficiary($beneficiary)
    ->currency(\TrueLayer\Constants\PayoutCurrencies::GBP)
    ->merchantAccountId($merchantAccount->getId())
    ->metadata([
        "foo" => "bar",
        "baz" => "qux",
    ])
    ->create();

$payout->getId();
```

Creating a payout to a payment source (refunds)
-----------------------------------------------

[](#creating-a-payout-to-a-payment-source-refunds)

```
$beneficiary = $client->payoutBeneficiary()->paymentSource()
    ->paymentSourceId($paymentSourceId)
    ->reference('My reference')
    ->userId($user->getId());

$payout = $client->payout()
    ->amountInMinor(1)
    ->beneficiary($beneficiary)
    ->currency(\TrueLayer\Constants\PayoutCurrencies::GBP)
    ->merchantAccountId($merchantAccount->getId())
    ->metadata([
        "foo" => "bar",
        "baz" => "qux",
    ])
    ->create();

$payout->getId();
```

Creating a payout to a preselected business account
---------------------------------------------------

[](#creating-a-payout-to-a-preselected-business-account)

```
$beneficiary = $client->payoutBeneficiary()
    ->businessAccount()
    ->reference('My reference');

$payout = $client->payout()
    ->amountInMinor(1)
    ->beneficiary($beneficiary)
    ->currency(\TrueLayer\Constants\PayoutCurrencies::GBP)
    ->merchantAccountId($merchantAccount->getId())
    ->metadata([
        "foo" => "bar",
        "baz" => "qux",
    ])
    ->create();

$payout->getId();
```

Specifying the payment scheme for a payout
------------------------------------------

[](#specifying-the-payment-scheme-for-a-payout)

You can optionally specify the payment scheme for a payout.

```
use \TrueLayer\Constants\SchemeIds;

$schemeSelection = $client->payoutSchemeSelection()->instantPreferred(); // Attempt to select a payment scheme that supports instant payments based on currency and geography, fallback to a non-instant scheme if instant payment is unavailable. This is used by default if no scheme selection is provided.
$schemeSelection = $client->payoutSchemeSelection()->instantOnly(); // Automatically select a payment scheme that supports instant payments based on currency and geography.
$schemeSelection = $client->payoutSchemeSelection()->preselected()->schemeId(SchemeIds::FASTER_PAYMENTS_SERVICE); // Set the scheme manually. Scheme ID is required.

$client->payout()
    ...
    ->schemeSelection($schemeSelection)
    ->create();
```

Retrieving a payout
-------------------

[](#retrieving-a-payout)

```
use TrueLayer\Interfaces\Payout\PayoutRetrievedInterface;
use TrueLayer\Interfaces\Payout\PayoutPendingInterface;
use TrueLayer\Interfaces\Payout\PayoutAuthorizedInterface;
use TrueLayer\Interfaces\Payout\PayoutExecutedInterface;
use TrueLayer\Interfaces\Payout\PayoutFailedInterface;
use TrueLayer\Constants\PayoutStatus;

$payout = $client->getPayout($payoutId);

// All payout statuses implement this common interface
if ($payout instanceof PayoutRetrievedInterface) {
    $payout->getId();
    $payout->getCurrency();
    $payout->getAmountInMinor();
    $payout->getMerchantAccountId();
    $payout->getStatus();
    $payout->getSchemeId();
    $payout->getBeneficiary();
    $payout->getMetadata();
    $payout->getCreatedAt();
}

// Pending payouts
if ($payout instanceof PayoutPendingInterface) {
    $payout->getStatus(); //PayoutStatus::PENDING
}

// Authorized payouts
if ($payout instanceof PayoutAuthorizedInterface) {
    $payout->getStatus(); //PayoutStatus::AUTHORIZED
}

// Executed payouts
if ($payout instanceof PayoutExecutedInterface) {
    $payout->getStatus(); //PayoutStatus::EXECUTED
    $payout->getExecutedAt();
}

// Failed payouts
if ($payout instanceof PayoutFailedInterface) {
    $payout->getStatus() // PayoutStatus::FAILED
    $payout->getFailedAt();
    $payout->getFailureReason();
}
```

Merchant accounts
=================

[](#merchant-accounts)

Listing all merchant accounts:

```
$merchantAccounts = $client->getMerchantAccounts(); // MerchantAccountInterface[]
```

Retrieving an account by id:

```
$merchantAccount = $client->getMerchantAccount('a2dcee6d-7a00-414d-a1e6-8a2b23169e00');

$merchantAccount->getAccountHolderName();
$merchantAccount->getAvailableBalanceInMinor();
$merchantAccount->getCurrentBalanceInMinor();
$merchantAccount->getCurrency();
$merchantAccount->getId();

foreach ($merchantAccount->getAccountIdentifiers() as $accountIdentifier) {
    // See 'Account identifiers' for available methods.
}
```

SignUp Plus
===========

[](#signup-plus)

Generating a SignUp Plus authentication link:

```
$client->signupPlus()
    ->authUri()
    ->paymentId('some_payment_id')
    ->state('some_state')
    ->create();
```

Retrieving user data:

```
$response = $client->signupPlus()
        ->userData()
        ->paymentId('fake_payment_id')
        ->retrieve(); // SignupPlusUserDataRetrievedInterface
```

Receiving webhook notifications
===============================

[](#receiving-webhook-notifications)

You can register to receive notifications about your payment or mandate statuses via webhooks. The URI endpoint for the webhook can be [configured in the Console](https://docs.truelayer.com/docs/set-up-truelayer-console-for-payments-v3)

> ⚠️ All incoming webhook requests must have their signatures verified, otherwise you run the risk of accepting fraudulent payment status events.

This library makes handling webhook events easy and secure. You do not need to manually verify the incoming request signature as it is done for you. You should add the code below to your webhook endpoint; Alternatively the webhook service can be configured in your IoC container and in your endpoint you can simply call `$webhook->execute()`.

Getting a webhook instance
--------------------------

[](#getting-a-webhook-instance)

If you already have access to a client instance, it's as easy as:

```
$webhook = $client->webhook();
```

Alternatively, you can also create an instance from scratch:

```
$webhook = \TrueLayer\Webhook::configure()
    ->httpClient($httpClient)
    ->cache($cacheImplementation, $encryptionKey)  // optional, but recommeded. See Caching
    ->useProduction($useProduction) // bool
    ->create();
```

Handling events
---------------

[](#handling-events)

You handle events by registering handlers (closures or invokable classes) for the event types you care about. You can have as many handlers as you wish, however please note the order of execution is not guaranteed.

Your handlers will only execute after the request signature is verified, and the incoming webhook type is matched to the interface you typehinted in your handler.

[Jump to supported event types](#webhook-types)

### Closure handlers

[](#closure-handlers)

```
use TrueLayer\Interfaces\Webhook;

$client->webhook()
    ->handler(function (Webhook\EventInterface $event) {
        // Do something on any event
    })
    ->handler(function (Webhook\PaymentEventInterface $event) {
        // Do something on any payment event
    })
    ->handler(function (Webhook\PaymentExecutedEventInterface $event) {
        // Do something on payment executed event only
    })
    ->execute();
```

### Invokable classes

[](#invokable-classes)

```
use TrueLayer\Interfaces\Webhook;

class LogEvents
{
    public function __invoke(Webhook\EventInterface $event)
    {
        // Log event
    }
}

class UpdateOrderStatus
{
    public function __invoke(Webhook\PaymentExecutedEventInterface $event)
    {
        // Update your order when the payment is executed
    }
}

// You can use ->handler()...
$client->webhook()
    ->handler(LogEvents::class)
    ->handler(UpdateOrderStatus::class)
    ->execute();

// Or you can use ->handlers()...
$client->webhook()
    ->handlers(
        LogEvents::class,
        UpdateOrderStatus::class
    )
    ->execute();

// If you need to, you can also provide instances:
$client->webhook()
    ->handlers(
        new LogEvents(),
        new UpdateOrderStatus()
    )
    ->execute();
```

Supported handler types
-----------------------

[](#supported-handler-types)

This library supports handlers for the following event types:

- payment\_authorized
- payment\_executed
- payment\_settled
- payment\_failed
- payment\_creditable
- payment\_settlement\_stalled
- refund\_executed
- refund\_failed
- payout\_executed
- payout\_failed

You can also handle other event types by typehinting `TrueLayer\Interfaces\Webhook\EventInterface`in your handler. You can then get the payload data by calling the `getBody()` method on your variable.

All events inherit from `EventInterface`.

```
use TrueLayer\Interfaces\Webhook;

$client->webhook()
    ->handler(function (Webhook\EventInterface $event) {
        // Handle any incoming event
        $event->getEventId();
        $event->getEventVersion();
        $event->getSignature();
        $event->getTimestamp();
        $event->getType();
        $event->getBody();
    })
    ->handler(function (Webhook\PaymentEventInterface $event) {
        // Handle any payment event
        // Inherits from EventInterface so provides same methods plus:
        $event->getPaymentId();
        $event->getMetadata();
    })
    ->handler(function (Webhook\PaymentAuthorizedEventInterface $event) {
        // Handle payment authorized
        // Note that this webhook is optional and disabled by default.
        // Contact us if you would like this webhook to be enabled.
        // Inherits from PaymentEventInterface so provides same methods plus:
        $event->getAuthorizedAt();
        $event->getPaymentMethod();
        $event->getPaymentSource();
    })
    ->handler(function (Webhook\PaymentExecutedEventInterface $event) {
        // Handle payment executed
        // Inherits from PaymentEventInterface so provides same methods plus:
        $event->getExecutedAt();
        $event->getSettlementRiskCategory();
        $event->getPaymentMethod();
        $event->getPaymentSource();
    })
    ->handler(function (Webhook\PaymentSettledEventInterface $event) {
        // Handle payment settled
        // Inherits from PaymentEventInterface so provides same methods plus:
        $event->getSettledAt();
        $event->getSettlementRiskCategory();
        $event->getPaymentMethod();
        $event->getPaymentSource();
    })
    ->handler(function (Webhook\PaymentFailedEventInterface $event) {
        // Handle payment failed
        // Inherits from PaymentEventInterface so provides same methods plus:
        $event->getFailedAt();
        $event->getFailureReason();
        $event->getFailureStage();
        $event->getPaymentMethod();
        $event->getPaymentSource();
    })
    ->handler(function (Webhook\PaymentCreditableEventInterface $event) {
        // Handle payment creditable
        // Inherits from PaymentEventInterface so provides same methods plus:
        $event->getCreditableAt();
    })
    ->handler(function (Webhook\PaymentSettlementStalledEventInterface $event) {
        // Handle payment settlement stalled
        // Note that this webhook is optional and disabled by default.
        // Contact us if you would like this webhook to be enabled.
        // Inherits from PaymentEventInterface so provides same methods plus:
        $event->getSettlementStalledAt();
    })
    ->handler(function (Webhook\RefundEventInterface $event) {
        // Handle any refund event
        $event->getPaymentId();
        $event->getRefundId();
        $event->getMetadata();
    })
    ->handler(function (Webhook\RefundExecutedEventInterface $event) {
        // Handle refund executed
        // Inherits from RefundEventInterface so provides same methods plus:
        $event->getExecutedAt();
        $event->getSchemeId();
    })
    ->handler(function (Webhook\RefundFailedEventInterface $event) {
        // Handle refund failed
        // Inherits from RefundEventInterface so provides same methods plus:
        $event->getFailedAt();
        $event->getFailureReason();
    })
    ->handler(function (Webhook\PayoutEventInterface $event) {
        // handle any payout event
        $event->getPayoutId();
        $event->getMetadata();
        $beneficiary = $event->getBeneficiary();
        $beneficiary->getType();

        if ($beneficiary instanceof Webhook\Beneficiary\BusinessAccountBeneficiaryInterface) {
            $beneficiary->getType();
        }

        if ($beneficiary instanceof Webhook\Beneficiary\PaymentSourceBeneficiaryInterface) {
            $beneficiary->getPaymentSourceId();
            $beneficiary->getUserId();
        }
    })
    ->handler(function (Webhook\PayoutExecutedEventInterface $event) {
        // handle payout executed
        // Inherits from PayoutEventInterface so provides same methods plus:
        $event->getExecutedAt();
    })
    ->handler(function (Webhook\PayoutFailedEventInterface $event) {
        // handle payout failed
        // Inherits from PayoutEventInterface so provides same methods plus:
        $event->getFailedAt();
        $event->getFailureReason();
    })
    ->execute();
```

Payment source
--------------

[](#payment-source)

PaymentAuthorizedEventInterface, PaymentExecutedEventInterface, PaymentSettledEventInterface, PaymentFailedEventInterface provide a method to get more information about the payment source:

```
$paymentSource = $event->getPaymentSource(); $paymentSource->getId(); $paymentSource->getAccountHolderName();
$paymentSource->getAccountIdentifiers(); // See Account Identifiers
```

### Payment method

[](#payment-method)

PaymentAuthorizedEventInterface, PaymentExecutedEventInterface, PaymentSettledEventInterface, PaymentFailedEventInterface provide a method to get more information about the payment method:

```
use TrueLayer\Interfaces\Webhook;

$paymentMethod = $event->getPaymentMethod();
$paymentMethod->getType();

if ($paymentMethod instanceof Webhook\PaymentMethod\BankTransferPaymentMethodInterface) {
    $paymentMethod->getProviderId();
    $paymentMethod->getSchemeId();
}

if ($paymentMethod instanceof Webhook\PaymentMethod\MandatePaymentMethodInterface) {
    $paymentMethod->getMandateId();
    $paymentMethod->getReference();
}
```

Overriding globals
------------------

[](#overriding-globals)

By default the webhook service will use php globals to read the endpoint path and request headers and body. This behaviour can be overriden if necessary (for example you may be calling `execute()` in a queued job.):

```
    $client->webhook()
        ->handlers(...)
        ->path('/my/custom/path')
        ->headers($headers) // flat key-value array
        ->body($body) // the raw request body string
        ->execute();
```

Signature verification failure
------------------------------

[](#signature-verification-failure)

If the webhook signature cannot be verified, a \\TrueLayer\\Exceptions\\WebhookVerificationFailedException will be thrown. A number of other exceptions will be thrown when the webhook service is misconfigured, please see [error handling](#error-handling)

Account identifiers
===================

[](#account-identifiers)

All account identifiers implement a common interface, so you can access:

```
$accountIdentifier->getType();
$accountIdentifier->toArray();
```

Based on the specific type, you can get more information:

```
use TrueLayer\Interfaces\AccountIdentifier\ScanDetailsInterface;
use TrueLayer\Interfaces\AccountIdentifier\IbanDetailsInterface;
use TrueLayer\Interfaces\AccountIdentifier\NrbDetailsInterface;
use TrueLayer\Interfaces\AccountIdentifier\BbanDetailsInterface;

if ($accountIdentifier instanceof ScanDetailsInterface) {
    $accountIdentifier->getAccountNumber();
    $accountIdentifier->getSortCode();
}

if ($accountIdentifier instanceof IbanDetailsInterface) {
    $accountIdentifier->getIban();
}

if ($accountIdentifier instanceof NrbDetailsInterface) {
    $accountIdentifier->getNrb();
}

if ($accountIdentifier instanceof BbanDetailsInterface) {
    $accountIdentifier->getBban();
}
```

Custom idempotency keys
=======================

[](#custom-idempotency-keys)

By default, the client will generate and manage idempotency keys for you. However, there are cases when you might want to set your own idempotency keys and you can do this by using the `requestOptions` setter when creating a resource.

```
// Create a RequestOptionsInterface instance and set your custom idempotency key
$requestOptions = $client->requestOptions()->idempotencyKey('my-custom-idempotency-key');

// Creating a payment with a custom idempotency key
$client->payment()
    ->paymentMethod($method)
    ->amountInMinor(10)
    ->currency('GBP')
    ->user($user)
    ->requestOptions($requestOptions)
    ->create();

// Creating a refund with a custom idempotency key
$client->refund()
    ->payment($paymentId)
    ->amountInMinor(1)
    ->reference('My reference')
    ->requestOptions($requestOptions)
    ->create();

// Creating a payout with a custom idempotency key
$client->payout()
    ->amountInMinor(1)
    ->currency(Currencies::GBP)
    ->merchantAccountId($accountId)
    ->beneficiary($payoutBeneficiary)
    ->requestOptions($requestOptions)
    ->create();
```

Custom API calls
================

[](#custom-api-calls)

You can use the client library to make your own API calls without worrying about authentication or request signing:

```
$responseData = $client->getApiClient()->request()->uri('/merchant-accounts')->get();

$responseData = $client->getApiClient()->request()
    ->uri('/payments')
    ->payload($myData)
    ->header('My Header', 'value')
    ->post();
```

Error Handling
==============

[](#error-handling)

The client library throws the following exceptions:

PSR Exceptions
--------------

[](#psr-exceptions)

### ClientExceptionInterface

[](#clientexceptioninterface)

Thrown according to the PSR-18 specification, if the HTTP client is unable to send the request at all or if the response could not be parsed into a PSR-7 response object.

```
Psr\Http\Client\ClientExceptionInterface
```

Custom Exceptions
-----------------

[](#custom-exceptions)

All custom exceptions will extend from the base `TrueLayer\Exceptions\Exception` class.

### ApiResponseUnsuccessfulException

[](#apiresponseunsuccessfulexception)

Thrown if the API response is not a 2xx status.

```
\TrueLayer\Exceptions\ApiResponseUnsuccessfulException

$e->getErrors(); // Get the errors provided by the API, as an array
$e->getStatusCode(); // The response status code
$e->getType(); // The error type, as a link to the TrueLayer docs
$e->getDetail(); // A description of the error message
$e->getTraceId(); // The TrueLayer error trace id
```

### ApiRequestJsonSerializationException

[](#apirequestjsonserializationexception)

Thrown if the request data cannot be json encoded prior to calling the APIs.

```
\TrueLayer\Exceptions\ApiRequestJsonSerializationException
```

### InvalidArgumentException

[](#invalidargumentexception)

Thrown when a provided argument is invalid, for example an invalid beneficiary type

```
\TrueLayer\Exceptions\InvalidArgumentException
```

### SignerException

[](#signerexception)

Thrown if the request signer cannot be initialised or signing fails.

```
\TrueLayer\Exceptions\SignerException
```

### EncryptException

[](#encryptexception)

Thrown when the client library fails to encrypt a payload that needs to be cached.

```
\TrueLayer\Exceptions\EncryptException
```

### DecryptException

[](#decryptexception)

Thrown if the client library fails to decrypt the value of a cached key.

```
\TrueLayer\Exceptions\DecryptException
```

### TLPublicKeysNotFound

[](#tlpublickeysnotfound)

Thrown when the webhook service cannot retrieve TL's public keys.

```
\TrueLayer\Exceptions\TLPublicKeysNotFound
```

### WebhookHandlerException

[](#webhookhandlerexception)

Thrown when the webhook service is provided with an invalid handler.

```
\TrueLayer\Exceptions\WebhookHandlerException
```

### WebhookHandlerInvalidArgumentException

[](#webhookhandlerinvalidargumentexception)

Thrown when the webhook service cannot get the request body, signature header or the provided handlers have invalid arguments.

```
\TrueLayer\Exceptions\WebhookHandlerInvalidArgumentException
```

### WebhookVerificationFailedException

[](#webhookverificationfailedexception)

Thrown when the webhook signature cannot be verified.

```
\TrueLayer\Exceptions\WebhookVerificationFailedException
```

###  Health Score

51

—

FairBetter than 96% of packages

Maintenance63

Regular maintenance activity

Popularity36

Limited adoption so far

Community26

Small or concentrated contributor base

Maturity69

Established project with proven stability

 Bus Factor1

Top contributor holds 51.6% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~42 days

Recently: every ~62 days

Total

30

Last Release

243d ago

Major Versions

v0.0.6 → v1.0.02023-01-26

v1.6.0 → v2.0.02024-03-26

v2.6.0 → v3.0.02024-12-04

PHP version history (2 changes)v0.0.1PHP ^7.4 || ^8.0

v2.0.0PHP ^8.1

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/98873?v=4)[Lee Boynton](/maintainers/lboynton)[@lboynton](https://github.com/lboynton)

![](https://avatars.githubusercontent.com/u/9030768?v=4)[Stefan Danaita](/maintainers/stefandanaita)[@stefandanaita](https://github.com/stefandanaita)

![](https://avatars.githubusercontent.com/u/1301561?v=4)[Alexandru Lighezan](/maintainers/lighe)[@lighe](https://github.com/lighe)

![](https://avatars.githubusercontent.com/u/21106665?v=4)[TrueLayer](/maintainers/TrueLayer)[@TrueLayer](https://github.com/TrueLayer)

---

Top Contributors

[![lighe](https://avatars.githubusercontent.com/u/1301561?v=4)](https://github.com/lighe "lighe (32 commits)")[![stefandanaita](https://avatars.githubusercontent.com/u/9030768?v=4)](https://github.com/stefandanaita "stefandanaita (22 commits)")[![artyom-jaksov-tl](https://avatars.githubusercontent.com/u/171248816?v=4)](https://github.com/artyom-jaksov-tl "artyom-jaksov-tl (5 commits)")[![dili91](https://avatars.githubusercontent.com/u/10221348?v=4)](https://github.com/dili91 "dili91 (1 commits)")[![lboynton](https://avatars.githubusercontent.com/u/98873?v=4)](https://github.com/lboynton "lboynton (1 commits)")[![tl-tai-tang](https://avatars.githubusercontent.com/u/90049745?v=4)](https://github.com/tl-tai-tang "tl-tai-tang (1 commits)")

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/truelayer-client/health.svg)

```
[![Health](https://phpackages.com/badges/truelayer-client/health.svg)](https://phpackages.com/packages/truelayer-client)
```

###  Alternatives

[laravel/framework

The Laravel Framework.

34.7k509.9M17.0k](/packages/laravel-framework)[opensearch-project/opensearch-php

PHP Client for OpenSearch

15224.3M65](/packages/opensearch-project-opensearch-php)[phpro/http-tools

HTTP tools for developing more consistent HTTP implementations.

28137.8k](/packages/phpro-http-tools)[multisafepay/php-sdk

MultiSafepay PHP SDK

14930.8k7](/packages/multisafepay-php-sdk)[open-telemetry/sdk

SDK for OpenTelemetry PHP.

2322.9M248](/packages/open-telemetry-sdk)[mariosimao/notion-sdk-php

A complete Notion SDK for PHP developers.

171225.1k1](/packages/mariosimao-notion-sdk-php)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
