Sign your payments requests

Generate public and private keys and use them to sign API requests.

The Payments API v3 uses a pair of ECDSA keys in addition to a bearer token. The keys are a form of encryption that ensures your payments are secure.

With this form of encryption, you upload one public key to your Console account, and provide the other private key with your Payments v3 API requests. The combination of keys verifies and authenticates the request.

This procedure explains how to sign your requests.

1. Sign up for Console

Before you can sign your requests, you must sign up for a Console account.

2. Generate your key pair

To generate your key pair, you can use OpenSSL or LibreSSL, which are installed on MacOS and Windows by default. To do so:

  1. Open the command line.
  2. Use these commands to generate your key pair:
openssl ecparam -genkey -name secp521r1 -noout -out ec512-private-key.pem
openssl ec -in ec512-private-key.pem -pubout -out ec512-public-key.pem

The keys, named ec512-private-key.pem and ec512-public-key.pem by default, are generated in your current working directory.

📘

Key security

Ensure that you store your private key securely.

We recommend that you use your preferred key management system to generate and store your keys.

To learn more about how to use the command line, see the Apple or Microsoft documentation.

3. Upload your public key to Console

  1. Go to Console > Payments > Settings.
  2. Upload your public key in the Signing keys box.
    When you upload your public key, a KID is generated on this page. This is different to your public key itself, and is required to sign your requests.

4. Use a library to set up request signing

The end result of setting up request signing is that you can include a correctly formatted header named Tl-signature with your requests. Create this header using the public and private certificates you generated earlier.

In our Github, we maintain request signing libraries in a range of languages, so you can use the one best suited to your integration. Our other more general integration libraries also use these libraries for request signing.

For example, a Tl-Signature looks like this in our Java request signing library:

// `Tl-Signature` value to send with the request.
String tlSignature = Signer.from(kid, privateKey)
        .header("Idempotency-Key", idempotencyKey)
        .method("post")
        .path(path)
        .body(body)
        .sign();

🚧

Sign your requests without our libraries

It's possible to sign requests without using our libraries. The process is detailed here.

However, we strongly recommend that you use our signing libraries for easier integration.

Common request signing recommendations

When you set up request signing, make sure to check for these common issues.

  • Whichever library you use, ensure that the path you sign is the same as the path used to send the request. For example, if you're testing https://api.truelayer-sandbox.com/test-signature, the path must be /test-signature.
  • All signed headers sent with a request must be exactly as they were signed, with none missing. This is a lso the case for the Idempotency-Key header, which you must also send with exactly the same value both when generating the Signature, and when using it in the Payment request.
  • Ensure that the body passed to the signing library matches the body sent with the request exactly, byte for byte.
    • It must not be formatted differently or have fields in a different order.
    • Ensure the request body has no trailing newlines if it was not signed that way.
    • Ensure that if you have some fields that you are passing as null (which in general is not recommended - in this case just do not pass the field), those are not removed once the body is serialised, causing differences between bodies.
    • Recommended: for all those reasons above, it's recommended to first serialise the body and store it in an object 'body', which is then the very same object you are using both for generating the signature, and passing the body in the request call.
  • Ensure the public key and private key you are signing with match the KID (Public Key ID) in our Console. You can find your KID in Payments > Settings.
A screenshot of the Payments V3 > Settings page in Console, where you can upload your signing keys and add Webhook URIs.

The Payments V3 > Settings page in Console, where you can upload your signing keys and add Webhook URIs.

5. Test your request signing

You can send a POST or DELETE request to our /test-signature endpoint to check if your configuration works. If correctly configured, the endpoint validates your Tl-signature and returns a 204 No Content response. It doesn't validate your request body.

This is an example of a request to the /test-signature endpoint:

curl -X POST \
	-H "Authorization: Bearer ${access_token}" \
	-H "Tl-Signature: ${signature}" \
	--data '{"nonce":"9f952b2e-1675-4be8-bb39-6f4343803c2f"}' \
	https://api.truelayer-sandbox.com/test-signature