Sign your requests

Learn how to sign requests to your Payment API.

All modification requests (for example, POST, DELETE) to our Payments APIs, authenticated with a client_credentials token generated by TrueLayer's authentication server, must be signed.

When you sign your requests to our APIs, you ensure a second layer of security on top of the authorisation bearer token, guaranteeing that the payload has not been tampered with.


Supported algorithms

We only support the ES512 signing algorithm for modification requests to our Payments APIs.

ES512 belongs to the family of Elliptic Curve Digital Signature Algorithms (ECDSA).

To sign an HTTP request using ECDSA you will need to generate an Elliptic Curve (EC) key pair. You will need:

  • a public key, to be uploaded in the new Payments Settings page in our Console.
  • a private key, to be used for signing requests, which you should not share with anyone outside of your organisation. ES512, in particular, requires a key pair that uses the P-521 family of elliptic curves (also known as secpt521r1).

To sign your requests to the Payments API, you'll need to:

  1. Generate signing key pair
  2. Sign your requests

Sign your requests with our libraries

In our public repository, we maintain libraries in a range of languages, which provide methods for signing and verifying according to the scheme described later. Our backend libraries also make use of these signing libraries for the API requests.

Sign your requests without using libraries


Manual signing

We encourage the use of our signing libraries mentioned previously for easier integration.

You can also sign your requests as follows:

Step 1: Generate a signing key pair

You can generate a key pair using openssl.

  1. To generate the private key, run:
docker run --rm -v ${PWD}:/out -w /out -it alpine/openssl ecparam -genkey -name secp521r1 -noout -out ec512-private-key.pem
  1. You can then obtain the public key by running:
docker run --rm -v ${PWD}:/out -w /out -it alpine/openssl ec -in ec512-private-key.pem -pubout -out ec512-public-key.pem
  1. Go to Console > Payments Settings and upload the file ec512-public-key.pem.

Step 2: Sign a request

You need to specify a Tl-Signature header in your HTTP request. The header value is a JWS with detached content, signed using the ES512 algorithm.

A JWS with detached content has the following structure:


The payload segment is omitted in the JWS with detached content.

The JOSE header must contain the following parameters and values:

  • alg: ES512
  • kid: The id of the key used for signing as value. This is the UUID value shown in the new Payments Settings in Console next to your uploaded public key.
  • tl_version: 2
  • tl_headers: An ordered comma separated list of headers to include in signing (must at least include Idempotency-Key) as value.

The following example shows what a JOSE header looks like:

  "alg": "ES512",
  "kid": "9f2b7bd6-c055-40b5-b616-120ccfd33c49",
  "tl_version": "2",
  "tl_headers": "Idempotency-Key"

The JWS payload should be built using the following in order:

  • The HTTP VERB (capitalized), followed by a space, then the absolute path (without trailing slashes), for example: POST /payouts, followed by a newline character \n
  • For each header specified in tl_headers, in the same order (and with the same casing):
    • The header name, followed by a colon, a space, then the header value, for example: Idempotency-Key: 619410b3-b00c-406e-bb1b-2982f97edb8b, followed by a newline character \n
  • The serialized HTTP request body (if sending a body)

The following example shows what a JWS payload might look like:

POST /payouts
Idempotency-Key: 619410b3-b00c-406e-bb1b-2982f97edb8b
  "merchant_account_id": "ee69a988-5e1b-4dab-a1f9-94593f6a132e",
  "amount_in_minor": 100,
  "currency": "GBP",
  "beneficiary": {
    "type": "external_account",
    "name": "Benny Fishery",
    "scheme_identifier": {
      "type": "sort_code_account_number",
      "sort_code": "123456",
      "account_number": "12345678"
    "reference": "myref"

Once you build your payload, you generate a signature with your private key and place it on the right side of your JWS.

Did this page help you?