About notifications

As return URLs are plain text and could be modified by your customer, we inform you of a payment’s success/failure/pending status by sending a POST request that contains a digitally signed payment notification to a secure URL on your server.

By using a secret key that you receive during application setup, you can check the signature of the message to confirm that it came from Volt and is a genuine notification. Never process any message that appears to originate at Volt without performing this verification step first.

If a status was originally pending, we’ll send you another notification when it changes to success or failure. Each notification will be digitally signed, and you’ll then need to confirm that you have received the notification and the signature is correct.

Important!

The success notification is only a confirmation that the payment was successfully initiated at the bank. Some banks allow payments to be cancelled after they are initiated so this is not a guarantee that the funds will arrive in your account. Note, however, that we do issue payment received notifications via Connect.

Notification content

Payment initiation

For our core Gateway product, we’ll send a notification to your payment notification URL if:

  • A payment initiation is complete
  • A payment is delayed, or 
  • The payment initiation fails for any reason

 

Notification fields

The body of the notification contains a JSON formatted data structure, which has the following fields:

  • payment is Volt’s internal ID for the payment, as returned in your initial payment request
  • reference is the reference you specified for the payment
  • amount is the payment amount; always in minor units of currency (pence, cents) rather than pounds, euros or dollars
  • status refers to a broad classification of transactions based on their detailed status; it provides a high-level overview of where each transaction stands; each group encompasses multiple detailed statuses that share similar characteristics or states
  • detailedStatus is a more specific and in-depth update that provides finer details about the payment’s status
  • currency is the currency of the payment (is applicable only for Received notification)
  • timestamp is when the notification was generated (is applicable only for Received notification)
  • merchantInternalReference is an optional longer reference you can specify for the payment.  It can be up to 100 characters, including special characters.  If this value is provided during payment creation, then it will be a part of the notification.

 

{
  "payment": "292d48f6-90f3-450b-93eb-0b480b8b70dd",
  "reference": "Invoice-12345",
  "merchantInternalReference": "Order for a trip to Greece 20-27.08.2023",
  "amount": 1000,
  "status": "FAILED",
  "detailedStatus": "REFUSED_BY_BANK"
}

What each status means

The COMPLETED status means that the payment has been instructed and your customer’s bank has accepted it. Both the payment request and instruction process are completed.

However, banks are still able to cancel payments after the instruction has been accepted, so a status of COMPLETED does not guarantee that you will receive the funds. It is important to confirm receipt of funds with your receiving bank before releasing the goods or services.

The PENDING status means that payment is not yet confirmed by the customer’s bank. This can occur for multiple reasons, including the customer’s bank encountering a delay in processing payments or a second person being required to approve payments.

Once Volt is made aware that the payment status has changed, you’ll receive another notification with the final status of COMPLETED or FAILED. If you’d like to manually check for status changes periodically, you can do so using the GET/payments/{id} endpoint.

The FAILED status means that the payment request could not be completed. This could be due to technical reasons in the banking network, the customer cancelled the payment, or the customer’s bank rejected it. 

Classification of the statuses

The statuses mentioned above, which are presented by the ‘status’ field in the notification (COMPLETED, FAILED, and PENDING) refer to a broad classification that provides a high-level overview of where each transaction stands. Due to this reason, an additional status was introduced to provide a more specific and in-depth update that offers finer details about the payment’s status. The additional status is represented by the ‘detailedStatus’ field. 

COMPLETED

COMPLETED
{
  "payment": "292d48f6-90f3-450b-93eb-0b480b8b70dd",
  "reference": "Invoice-12345",
  "merchantInternalReference": "Order for a trip to Greece 20-27.08.2023",
  "amount": 1000,
  "status": "COMPLETED",
  "detailedStatus": "COMPLETED"
}

FAILED

REFUSED_BY_RISK
{
  "payment": "292d48f6-90f3-450b-93eb-0b480b8b70dd",
  "reference": "Invoice-12345",
  "merchantInternalReference": "Order for a trip to Greece 20-27.08.2023",
  "amount": 1000,
  "status": "FAILED",
  "detailedStatus": "REFUSED_BY_RISK"
}
REFUSED_BY_BANK
{
  "payment": "292d48f6-90f3-450b-93eb-0b480b8b70dd",
  "reference": "Invoice-12345",
  "merchantInternalReference": "Order for a trip to Greece 20-27.08.2023",
  "amount": 1000,
  "status": "FAILED",
  "detailedStatus": "REFUSED_BY_BANK"
}
ERROR_AT_BANK
{
  "payment": "292d48f6-90f3-450b-93eb-0b480b8b70dd",
  "reference": "Invoice-12345",
  "merchantInternalReference": "Order for a trip to Greece 20-27.08.2023",
  "amount": 1000,
  "status": "FAILED",
  "detailedStatus": "ERROR_AT_BANK"
}
CANCELLED_BY_USER
{
  "payment": "292d48f6-90f3-450b-93eb-0b480b8b70dd",
  "reference": "Invoice-12345",
  "merchantInternalReference": "Order for a trip to Greece 20-27.08.2023",
  "amount": 1000,
  "status": "FAILED",
  "detailedStatus": "CANCELLED_BY_USER"
}
ABANDONED_BY_USER
{
  "payment": "292d48f6-90f3-450b-93eb-0b480b8b70dd",
  "reference": "Invoice-12345",
  "merchantInternalReference": "Order for a trip to Greece 20-27.08.2023",
  "amount": 1000,
  "status": "FAILED",
  "detailedStatus": "ABANDONED_BY_USER"
}
FAILED
{
  "payment": "292d48f6-90f3-450b-93eb-0b480b8b70dd",
  "reference": "Invoice-12345",
  "merchantInternalReference": "Order for a trip to Greece 20-27.08.2023",
  "amount": 1000,
  "status": "FAILED",
  "detailedStatus": "FAILED"
}

PENDING

BANK_REDIRECT
{
  "payment": "292d48f6-90f3-450b-93eb-0b480b8b70dd",
  "reference": "Invoice-12345",
  "merchantInternalReference": "Order for a trip to Greece 20-27.08.2023",
  "amount": 1000,
  "status": "PENDING",
  "detailedStatus": "BANK_REDIRECT"
}
DELAYED_AT_BANK
{
  "payment": "292d48f6-90f3-450b-93eb-0b480b8b70dd",
  "reference": "Invoice-12345",
  "merchantInternalReference": "Order for a trip to Greece 20-27.08.2023",
  "amount": 1000,
  "status": "PENDING",
  "detailedStatus": "DELAYED_AT_BANK"
}
AWAITING_CHECKOUT_AUTHORISATION
{
  "payment": "292d48f6-90f3-450b-93eb-0b480b8b70dd",
  "reference": "Invoice-12345",
  "merchantInternalReference": "Order for a trip to Greece 20-27.08.2023",
  "amount": 1000,
  "status": "PENDING",
  "detailedStatus": "AWAITING_CHECKOUT_AUTHORISATION34"
}

The statuses which are provided by our Volt Connect service such as RECEIVED and NOT_RECEIVED don’t require an in-depth update since they already cover a fine update about the payments status. Due to this reason the structure of content of such notification doesn’t include detailedStatus field. 

RECEIVED
{
  "payment": "292d48f6-90f3-450b-93eb-0b480b8b70dd",
  "reference": "Invoice-12345",
  "merchantInternalReference": "Order for a trip to Greece 20-27.08.2023",
  "amount": 10000,
  "status": "RECEIVED",
  "currency": "EUR",
  "timestamp": "2023-05-25T15:51:29+00:00",
  "sender": {
    "swiftBic": null,
    "location": "NL",
    "accountNumber": null,
    "iban": "NL54RABO0310400732",
    "sortCode": null,
    "name": "T.B.M. Van Buuren"
  }
}
NOT_RECEIVED
{
  "payment": "292d48f6-90f3-450b-93eb-0b480b8b70dd",
  "reference": "Invoice-12345",
  "merchantInternalReference": "Order for a trip to Greece 20-27.08.2023",
  "amount": 10000,
  "status": "NOT_RECEIVED",
  "currency": "EUR",
  "timestamp": "2023-05-25T15:51:29+00:00"
}

Additional notification content

Additional notification content

Volt can provide additional details in your payment notifications. The following table shows the full list of supported fields. It is possible to manage the additional notification content through our merchant portal Fuzebox inside the Application section. 

List of available fields:

Field Json path Description
bank_id sender.bank.id The Volt id for the bank
bank_country sender.bank.country The ISO alpha-2 code of the country where the payment originated
bank_official_name sender.bank.groupName The official group name of the bank where the payment originated
bank_short_branch_name sender.bank.branchName The branch name of the bank branch where the payment originated (where applicable)
bank_bic8 sender.bank.bic8 The bic8 of the bank where the payment originated
sender_iban sender.iban The IBAN of the bank account where the payment originated
sender_account_number sender.accountNumber The Account Number of the bank account where the payment originated
sender_sort_code sender.sortCode The Sort Code of the bank account where the payment originated (UK Payments)
sender_name sender.name The Account Holder of the bank account where the payment originated

Example notification content:

{
   "payment":"f839adfb-4b16-422d-a056-b10d5307660f",
   "reference":"uniquereference",
   "merchantInternalReference": "Order for a trip to Greece 20-27.08.2023",
   "amount":2500,
   "status":"COMPLETED",
   "detailedStatus": "COMPLETED",
   "sender":{
      "iban":"DE63500105173256774934",
      "accountNumber": null,
      "sortCode": null,
      "name":"Mrs Jane Doe",
      "bank":{
         "id":"ea54dc4d-d2e4-481f-8424-a9eb9a2db4ab",
         "country":"DE",
         "groupName":"Norisbank",
         "branchName":"Norisbank Berlin",
         "bic8":"HANDSESS"
      }
   }
}

Verifying signatures

The Volt signature is created by combining your notification secret, the body of the notification, and a timestamp. It will never contain personal or sensitive information. Each notification request that we send you will also include a custom HTTP header – called X-Volt-Signed – which will contain the Volt signature.

How the signature works

  • You will receive a POST message from Volt to your preconfigured notification URL
  • Based on the body of the notification and your notification secret, you calculate what you think the signature should be
  • You then check your calculation against the signature received in the X-Volt-Signed to confirm they match
  • If they do 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

Verifying the signature

Calculating the verification hash for a signature is based on three things, all of which are included in the notification. To verify, follow these simple steps:

  1. Extract the User-Agent, X-Volt-Timed and X-Volt-Signed headers and the body of the notification
  2. From the User-Agent header, extract the notification version (this is the part after the forward Slash (/) and will be a numeric value. For example, if the User-Agent is Volt/2.0, the version is 2.0)
  3. Link the notification body with the content of the X-Volt-Timed header and the version, using the pipe delimiter | between them, like this: body|X-Volt-Timed|version. This creates your check string
  4. Hash the check string with HMAC SHA256, using your notification secret (see below for an example)
  5. Finally, compare your signature to the value in the notification’s X-Volt-Signed header

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:

{}|X-Volt-Timed|version

A quick example to test your HMAC hashing

Using example values, here’s a quick test to ensure your signature check works correctly:

  • The version you extracted from the User-Agent: 1.0
  • X-Volt-Timed: 1631525064
  • X-Volt-Signed: ed22494369277d25cf8c2293d142e5fddb9cecbea1f54e28ac16db0bee3b8009
  • The complete, unmodified, body of the notification: {}
  • Your notification secret: 9c0c8c97-c224-45ed-a195-23b54b1c67e5

Next, use the pipe delimiter to join the body, X-Volt-Timed and version:

{}|1631525064|1.0

Then, hash this string using SHA256 and your notification secret of 9c0c8c97-c224-45ed-a195-23b54b1c67e5. If everything is correct, you should receive an HMAC that is identical to your X-Volt-Signed key:

ed22494369277d25cf8c2293d142e5fddb9cecbea1f54e28ac16db0bee3b8009

Troubleshooting notifications

We will make up to 8 attempts to deliver a notification with the aim of receiving a 200 (OK) response from you. A small delay will be added between each attempt in case a technical glitch is preventing the notifications arriving. The first retry will be after 5 seconds, the next after 30 seconds, 3 minutes, 10 minutes and every further will be after 15 minutes.

We will not stop sending you the notifications but all those that failed in the delivery attempt will be queued by us.

If we fail to deliver any notification 6 times in a row

  • We will monitor if any notification was not delivered to you 6 times in a row or failed to be delivered after the last retrial. 
  • If such an event occurred, there will be a summary report sent to you via email listing all payments for which notifications have not been successfully received by you. As the report will be sent once per hour, it will gather the notifications that failed within this particular time.
  • The email will be sent to your technical and/or primary contact, on the address you specified in Fuzebox.
  • If we don’t hear from you that the problem is fixed, then someone from Volt will be in touch.
  • If it’s a problem at your end then, once you’ve fixed the issue, go into Fuzebox and send a test notification (see below) to yourself. If that works, don’t worry, we’ll automatically send you any notifications you may have missed. 

If you still aren’t receiving previously failed notifications

Have you sent a test notification to the correct URL and responded with an HTTP 200 status? We won’t send any queued live payment notifications until we know you can process the test notification properly.

Are notifications showing as enabled in Fuzebox?

If you responded to the test notification and it was a success but payment notifications are not being delivered, please contact our support team and we’ll get to the bottom of it.