Webhook Documentation
The Register system provides event notification via webhooks for customer systems to consume. This document will provide an overview of how this system works and is intended for a technical audience.
If you're unfamiliar with webhooks we recommend webhooks.fyi to understand the current best practices of the technology. We also recommend reading the spec from Standard Webhooks, while not yet a true standard, this is an effort to establish a common set of conventions that can be standardized in the future.
Topics Covered:
Basic terminology
Setting up your first webhook
Receiving Webhook Messages
Verifying authenticity of webhook messages
Managing existing webhooks
Basic terminology
The following terms will be used in this document with the provided definitions.
Event Category
A logical group of events that can be subscribed to as a whole. Ex: The Brand Event Category includes all events that are related to a Brand Registration
Event Type
A specific kind of event that has occurred.
Ex: The StatusChange event type is sent when a Registration moves into a new status.
Webhook Message
Refers to the HTTP POST request that is sent to the customer's system. The relevant parts of the request are:
Headers
Webhook-Id
Webhook-Signature
Webhook-Timestamp
Body
The body of the request consists of the JSON payload of the webhook
Webhook Destination
Refers to a combination of an Event Category and a URL that will receive the Webhook Messages
Setting up your first webhook
Creating Webhook Destinations is fully self service through the Register API. Interactive API documentation of the endpoints discussed throughout this document are available here.
In order to create your first webhook you will send a POST request to the /webhooks endpoint with a body indicating which Event Category you would like to receive and what URL should be used.
POST /webhooks Body
{
"event_category": "Campaign",
"url": "https://example.com "
}
You should receive a 201 Created response if the Destination was successfully created.
Minutiae
Our system allows for multiple Destinations to be created for each Category. In other words, you can create two (or more) Destinations for single Event Category (such as Campaign ) that go to different URLs.
Our system also allows for multiple Destinations to be created for a single URL. In other words, you can create a Destination for one Event Category (such as Brand ) and another Destination for a different Event Category (such as Campapign ) with both Destinations using the same URL.
Receiving webhook messages
Once you have a Webhook Destination configured you will start receiving POST requests at that URL with the following structure.
Request Headers
Each message will contain 3 headers that are pertinent to handling these messages. They are called Webhook-Id , Webhook-Signature , and Webhook-Timestamp .
Webhook-Id:
This header will contain a UUID identifying the webhook. This ID will remain consistent across any retry attempts and can be used as an idempotency key.
Webhook-Signature:
This header will contain an Ed25519 signature that can be used to verify the authenticity of the entire message. This header is following the Standard Webhook convention and is prefixed with v1a, to indicate it is an Ed25519 based signature. For more information on authenticating Volt Webhooks please see the "Verifying authenticity of webhook messages" section of this document.
Webhook-Timestamp:
This header will contain a UNIX timestamp indicating the time that the Webhook Message was sent. This timestamp will not remain consistent across retries and should not be confused for an event timestamp which is included in the body of the webhook and does remain consistent across all retry attempts. Your system
should verify that the timestamp in this header is within some allowable tolerance of the current timestamp to prevent replay attacks. Within a couple of minutes of the current time should be sufficient.
Request Body
Each message will contain a JSON body with details of the event that has occurred.
Each message will include an EventTime , EventCategory , and an EventType field. Other fields will be included as appropriate based on the Event Category and Event Type.
Example:
{
"event_time":"2025-07-18T16:18:14.989348439+00:00",
"event_category":"BRAND",
"event_type":"Created",
}
Verifying authenticity of webhook messages
Due to the open nature of webhooks it is important to verify the authenticity of the webhook messages that you receive. Each message sent includes a Webhook Signature header which contains an Ed25519 signature that was constructed from the Webhook-Id , Webhook-Timestamp , and Message body. By verifying this signature with the following process you can be assured that the message originated from the Volt system.
Process Overview:
Retrieving the public key
Preparing the signature message
Verifying the signature
Retrieving the public key
The Ed25519 algorithm makes use of asymmetric keys (one public and one private key) to perform it's cryptographic functions. In order to verify the signature that Volt created with our private key you will need to acquire our public key. This key can be retrieved via a GET request to the /webhooks/key endpoint. This request will return a JSON object with a single key, public_key , which will contain Volt's public key in a text based format, known as PEM, which is well suited for efficient transfer of key data.
Once the key has been retrieved you will need to take a couple of additional steps to use the public key in your system.
Stripping header and footer
First the header ( -----BEGIN PRIVATE KEY----- ) and footer ( -----END PRIVATE KEY----- ) will need to be stripped from the PEM formatted key. Be sure that the new line ( \n ) characters are also being stripped in this process.
Base64 decoding
The PEM format encodes the key as Base64 data in order to be easily represented in a text format. Before working with the key further you will need to decode the Base64 string back into it's true binary form. This decoded data is also known as DER formatted keys.
Importing the key
Now that the key has been stripped and decoded you should be prepared to use the public key in your cryptographic library of choice. This process will look different depending on the library you've chosen. In general, you will either create a key object that wraps the binary key data or pass the data directly into your verification function.
Preparing the signature message
In order to verify the signature is valid you will need to reconstruct the message that was signed. This is a straightforward process but it must be followed exactly as even a single character out of place will result in a failed verification.
The signature message consists of the value of the Webhook-Id header, the value of the Webhook-Timestamp header, and the entire body of the request; with each value concatenated and separated by a period. Please ensure that the body of the request has not undergone any kind of formatting or parsing after being received as this will cause the signature to be invalid.
Placeholder Example:
let message = `${webhook_id}.${webhook_timestamp}.${webhook_payload}`;
Literal Example:
01981e54-414d-7223-acd3-b08f82481364.1752855494.
{"brand_name":"Amazon","brand_registration_id":"01981e54-4117-71b3-8122- 076c7eade396","campaign_registration_id":null,"campaign_website":null,"comments":null," current_status":"Created","event_category":"BRAND","event_time":"2025-07- 18T16:18:14.989348439+00:00","event_type":"Created","previous_status":null}
Verifying the signature
Now that we have a public key and a message prepared we only have one more step to complete before we can verify the signature, to decode the Base64 encoded Webhook-Signature header. Once the value of this header has been decoded into raw binary we can proceed to verify the signature.
Once again the exact process to verify this signature is dependent on the cryptographic library that you've chosen within your system. In general it is likely a function or method that you will provide with the public key, the signature, and the message. This function will then indicate if the signature is valid based on the key and message provided.
Example
If you would like to see an example of this process please visit this Github Repository (coming soon) which contains sample code.
Managing existing webhooks
After there are webhooks registered to your organization you are able to manage them using a handful of API endpoints detailed here. Interactive API documentation of the endpoints discussed throughout this document are available here.
List all webhook destinations
In order to see a listing of all of your Webhook Destinations you will send a GET request to the /webhooks endpoint. This endpoint supports an optional query string parameter, event_category , to filter the results to a specific Category. Omitting this parameter will show Destinations for all Categories.
List a single webhook destination
In order to see the details of a single Destination you will send a GET request to the /webhooks/{id} endpoint.
Activate or deactivate a webhook destination
Webhook Destinations can be enabled and disabled without fully removing them from the system by sending a PATCH request to the /webhooks/{id}/active endpoint with a body indicating if the Destination should be active or not.
PATCH /webhooks/{id}/active
{
"active": false
}
Delete a webhook destination
In order to fully remove a Destination from the system you will send a DELETE request to the /webhooks/{id} endpoint.