Webhooks
Introduction
Webhooks are HTTP callbacks that allow you to receive real-time notifications about events that happen in our system. When an event occurs, our system sends an HTTP POST request to the configured URL, providing you with the data related to the event. This mechanism allows for asynchronous processing and integration with your application, enabling seamless data flow and event-driven architecture.
Webhook Configuration
Setting Up a Webhook Endpoint
To start receiving webhook events, you need to set up an endpoint in your application that can accept HTTP POST requests. This endpoint should be capable of processing the incoming data and performing the necessary actions based on the event type.
Registering the Webhook URL
To start receiving events, you need to register your webhook URL with our system. Currently the webhook URL is set up in our system by your Snapdocs Implementation Specialist.
There is no per-event subscription: a single URL receives every event your application's scopes cover. Plan your listener to route on event_type rather than expecting one endpoint per event. The full event list is in the eVault Events Catalog.
Handling Webhook Events
The type of events your application will receive will depend on the scope it has been granted during its creation
- applications with scope
mers:basicwill receive all events related to MERS actions — registrations, transfers, eDeliveries, deactivations, assumptions, modifications, and other eRegistry actions - application with scope
auto_validation:basicwill receive all events related to auto validation
Event Structure
Each webhook event contains a JSON payload with information about the event. The event payload will never contain PII or sensitive information. We broadcast various identifiers and statuses. If more information is needed, your application can perform subsequent authenticated API calls.
The payload will always include an event_type indicating the type of event, a status relevant to the event type, anevent_timestamp and one or more relevant object IDs (e.g., document_id). Your application can use this ID to make subsequent requests to our API and retrieve more details about the objects.
For example, for a transfer event, the event payload will be:
{ "event_type": "transfer_submitted", "status": "processing_accept_or_reject", "transfer_id": "8bbc6a97-6a90-48c6-859b-efda72a1cd36", "display_status": "pending", "event_timestamp": "2026-05-21T12:00:00Z" }
For more details on webhooks payload see:
- transfer of rights for transfer and edelivery webhook events
- Auto-Validation for auto-validation webhook events
Handle requests
- Handle duplicate events: Webhook endpoints might occasionally receive the same event more than once. We advise you to guard against duplicated event receipts by making your event processing idempotent.
- Verify events are sent from Snapdocs eVault: Use webhook signatures to verify if the events are sent from Snapdocs eVault.
Webhook responses
If the webhook arrives successfully, respond quickly with a 200 HTTP status to acknowledge the event was received. The response status should not reflect whether or not your application has successfully processed the event payload.
If the webhook does not arrive successfully, respond with an error HTTP status code (400-599).
If we receive an error code in the response, we will attempt to re-send the event up to 13 times over the course of 24 hours from the first attempt, with increasing durations between each subsequent attempt.
Security
To enhance the security of webhook events, we implement HMAC (Hash-based Message Authentication Code) for verifying the authenticity and integrity of the data transmitted between our server and your application.
Overview
HMAC combines a cryptographic hash function with a secret key to ensure that a message (or payload) is both authentic and unaltered. By using HMAC, we can provide a secure mechanism to verify that webhook events are sent by us and have not been tampered with during transmission.
How it works
- Secret key: We generate a unique secret key used to sign the webhook payload. This key will be provided to you through secure channels, it is known only to our server and your application.
- Signature generation: When we send a webhook event, we compute an HMAC signature using a timestamp added to the payload and our secret key.
- Signature verification: Your application verifies the signature to ensure the payload has not been altered and is indeed from us
Implementation details
When we send a webhook event to your endpoint, it will include the following HTTP headers:
X-Authorization-Digest: the algorithm that Snapdocs Connect uses to generate the signature, "HMACSHA256"X-Authorization-Timestamp: the timestamp the message was created in ISO-8601 format, for example "2021-12-17T19:08:59Z"X-Authorization-Signature: the base64 encoded HMAC signature to compare
Here is the equivalent in bash of the request made to your application (where payload is the webhook event payload and HEX_KEY is the secret key):
KEY_HEX="secretkeystring" payload='{"foo":"bar"}' now=$(date -u +"%Y-%m-%dT%H:%M:%SZ") data="${now}${payload}" digest=$(echo -n $data | openssl dgst -sha256 -hmac ${KEY_HEX} -binary | base64) curl -X POST <url> --header "X-Authorization-Digest: HMACSHA256" \ --header "X-Authorization-Timestamp: ${now}" \ --header "X-Authorization-Signature: ${digest}" \ --header 'Content-Type: application/json' \ --data ${payload}
Below are steps you can take to verify the HMAC signature:
- Extract the digest and timestamp from the headers
- Calculate the payload signature using the digest algorithm (in our case "HMACSHA256") and the secret key provided to you against the timestamp + request body
- Extract the request signature from the header
- Compare the request signature and the calculated signature
Example verification code:
require 'openssl'
require 'base64'
timestamp = request.headers["X-Authorization-Timestamp"]
request_signature = request.headers["X-Authorization-Signature"]
data = request.body.read
hash_bytes = OpenSSL::HMAC.digest('sha256', hmac_key, timestamp.concat(data))
computed_signature = Base64.strict_encode64(hash_bytes)
if computed_signature == request_signature
# normal process
else
# did not come from Snapdocs eVault