Signature verification

How to verify Volt notification signatures using HMAC SHA256 and test your implementation

How Volt notification signatures work

Volt signs every notification to ensure it's authentic and untampered. The signature is generated using a combination of your notification secret, the notification body, and a timestamp—never including personal or sensitive information. Each notification will include a custom HTTP header named X-Volt-Signed, which contains this signature.

Signature process overview

  • Volt sends a POST request to your configured notification endpoint.
  • Using the notification body and your notification secret, you generate your own version of the expected signature.
  • You compare your calculated signature to the value in the X-Volt-Signed header to verify that they match.

Verifying the signature

To verify a notification signature, you need three pieces of information—all included in the notification. Follow these steps:

Extract the following from the notification:

  • User-Agent header
  • X-Volt-Timed header
  • X-Volt-Signed header
  • The body of the notification

From the User-Agent header, extract the notification version. This is the value after the forward slash ( / ).
Example: If User-Agent is Volt/2.0, the version is 2.0.

Concatenate the notification body, the value of X-Volt-Timed, and the version using the pipe character | as a delimiter, in the following format:
body|X-Volt-Timed|version
This will be the string you use for signature verification.

Please ensure you use the body exactly as we send it.

You shouldn't expand escaped characters before calculating the signature.
For example, we’ll send data with accented characters escaped like this: "groupName":"Soci\u00e9t\u00e9 G\u00e9n\u00e9rale". If you convert it back to accented characters so you can read the groupName as "Société Générale" then you'll end up with a signature that doesn't match.

Hash the concatenated string with HMAC SHA256, using your notification secret as the key.

Example code (PHP):

$hash = hash_hmac('sha256', $check_string, $notification_secret);

Compare the HMAC signature you just generated to the value in the notification's X-Volt-Signed header. If they match, the notification is valid.

Responding to notifications

Once you've compared your calculated HMAC signature to the one received with the notification, you should return one of two HTTP responses.

  • If the signatures match, return an empty HTTP response with a status code of 200 (OK)
  • If they do not match, return an empty HTTP response with a code of 400 (Bad Request) and do not process the notification

Testing notifications

Use the example values below to verify your signature verification implementation works correctly:

itemExample value
version1.0 (from the User-Agent header containing Volt/1.0)
X-Volt-Timed1631525064
X-Volt-Signeded22494369277d25cf8c2293d142e5fddb9cecbea1f54e28ac16db0bee3b8009
body (empty as in a test notification)
notification secret9c0c8c97-c224-45ed-a195-23b54b1c67e5

Steps to test

Concatenate the body, X-Volt-Timed, and version using the pipe delimiter (|) in that order:

{}|1631525064|1.0

Hash the concatenated string using HMAC SHA256 with your notification secret:

$hash = hash_hmac('sha256', $string, $notification_secret);

Compare your generated HMAC signature to the value in the X-Volt-Signed header. They should match:

ed22494369277d25cf8c2293d142e5fddb9cecbea1f54e28ac16db0bee3b8009

Notifications containing real data

When you receive real notifications, the body element should be supplied as one continuous, unformatted string—with no spaces or line breaks. Use the body exactly as received.

Example notification body:

{"payment":"4a96elcb-8ae0-426c-a95e-d34f18fe32ad","reference":"EXAMPLE123","amount":8888,"status":"PENDING","detailedStatus":"BANK_REDIRECT"}

Concatenated verification string:

{"payment":"4a96elcb-8ae0-426c-a95e-d34f18fe32ad","reference":"EXAMPLE123","amount":8888,"status":"PENDING","detailedStatus":"BANK_REDIRECT"}|1631525064|1.0

Expected HMAC signature:

9e09fdc90e8121e9d11f560c226271940b6b1f936ffc7a3f2551956c716b1019

Responding to tests

Your system should always be able to respond to a test notification and respond with a 200 (OK) status code. In the test notification, we'll send an empty JSON object in the request body, so your check string should look like this:

Test notification structure

{}|X-Volt-Timed|version

Test notification example

{}|12345678|2.0

We use test notifications to determine the health of your system. If we stop sending you notifications because of failure, you'll need to send and respond to a test notification before we start sending you other notifications again.

Interactive signature tester

Test your signature verification implementation using the interactive tool below:

The body of the POST message from Volt.

The value of the X-Volt-Timed header.

Extracted from User-Agent (e.g. "Volt/2.0").

This will be used to generate the signature.

How is this guide?

Last updated on

On this page