riverty logo

Docs

Get Started Login

Webhooks Implementation Guide

Webhooks allow your application to receive notifications when specific events occur. By setting up webhooks, you can automate workflows and respond to events as they happen. This guide will walk you through the steps to integrate webhooks into your system.

Integration Steps:

To process webhook events, follow these steps:

  1. Set up your endpoint
  2. Set up your webhook configuration
  3. Accept webhook events

Step 1: Set up your endpoint

To receive webhook events, you need to create an endpoint on your server that can handle POST requests. Your webhook endpoint must be a publicly accessible HTTPS URL.

Here are some key considerations when setting up your endpoint:

  • Return a 2xx status code quickly before performing any complex logic to prevent timeouts.
  • Implement security best practices, such as verifying webhook signatures and validating incoming requests. (For more details, check Step 3.)

Step 2: Set up your webhook configuration:

To start using webhooks, you need to provide the following details to our integration team:

  • Endpoint URL: The HTTPS URL you created in Step 1, where webhook events will be delivered. We recommend using separate URLs for testing and live environments.
  • Events: Specify which events you want to receive.

Once submitted, our integration team will register your endpoint with our webhook service.

Step 3: Accept webhook events

Riverty sends all events with a custom signature, which uniquely encodes each payload body. To verify the messages received at your webhook endpoint, you need to decode the payload body using our shared secret.

Retrieve and store secret

Upon registering a configuration for your webhook endpoint, we will generate a unique shared secret that our integration will share with you. This secret should be stored safely, preferably in a key vault or similar. To validate all events sent by Riverty, you need to retrieve this secret from your storage in order to decode the custom Riverty-Signature from the request header.

Example of a signature:

Riverty-Signature:
t=1715780015,
v1=ada4a220ba1879410b20c553b54b6255930a4486f628aaa630f80a41432d95a7
Plain text
  • Riverty-Signature = Custom signature for Riverty
  • t = timestamp
  • v1 = signature

Validating header signature

Here is a high level overview of how you can receive and validate events:

  1. Receive the webhook payload - Receive the POST request.

  2. Extract necessary information - Extract the Riverty-Signature from the request header and the message from the request body

  3. Extract the timestamp and signature from the header - The Riverty-Signature header of the webhook request contains the timestamp and signature, separated by a comma: The timestamp is prefixed with t= and the signature is prefixed with v1=. Split the header on the comma to get the two parts, then split each part on the = to get the timestamp and signature:

    headerSignature = "<Riverty-Signature header from the webhook request>"
    parts = split headerSignature by ','
    timestampPart = find and split the part that starts with "t=" by '=' and take the second element
    signaturePart = find and split the part that starts with "v1=" by '=' and take the second element
    Plain text
  4. Check the timestamp(optional) - The timestamp from the signature key in the request header is the time the webhook request was sent, in seconds since the Unix epoch. Compare this to the current UTC UNIX time to ensure the request is not a replay attack. If the difference is more than 5 minutes, the request should be rejected:

    headerTimestamp = convert timestampPart to a number
    currentTimestamp = get current UTC Unix timestamp
    timeDifference = absolute difference between currentTimestamp and headerTimestamp
    if timeDifference > 5 * 60 then throw an exception
    Plain text
  5. Retrieve the shared secret - Obtain the shared secret from your storage to validate the header.

  6. Validate the signature - The signature is a HMAC SHA256 hash of the timestamp and the message body, using the secret key. To validate the signature, compute the hash of the timestamp and the received message body using the same secret key, and compare it to the received signature. Confirm the signature's validity using the timestamp, signature string, payload, and shared secret (return status code 401 Unauthorized if the header is invalid):

    receivedMessage = "<raw json string from the HttpContext.Request.Body>"
    secretKey = "<your secret key>"
    messageWithTimestamp = headerTimestamp + receivedMessage
    
    keyByte = convert secretKey to byte array
    messageBytes = convert messageWithTimestamp to byte array
    
    computedHash = compute HMACSHA256 hash of messageBytes using keyByte
    computedSignature = convert computedHash to hexadecimal string, remove '-' characters and convert to lowercase
    
    if computedSignature != signaturePart then throw an exception
    if computedSignature == signaturePart then the message is considered valid
    Plain text
  7. Quickly return a response - Once the signature is validated and the message has been parsed, your endpoint must promptly return a 2xx status code before executing any complex logic that might cause a timeout.

Automatic Retries for failes webhooks

Riverty knows your system has successfully processed the webhook request when we receive an HTTP status 200 OK. If a different status is returned, we will continue retrying for up to 24 hours, giving you the chance to process the request once the issue with your hosting service is resolved.

We will call your webhook a total of 10 times, following these intervals:

  • 1 minute
  • 5 minutes
  • 10 minutes
  • 20 minutes
  • 30 minutes
  • 1 hour
  • 2 hours
  • 3 hours
  • 6 hours
  • 12 hours

Implementation Recommendations

Support HTTPS

HTTPS receiving endpoints are required in both testing and live modes. Riverty ensures a secure connection to your server before delivering webhook data. To enable this, your server must be properly configured to support HTTPS with a valid server certificate.

Handle duplicate events

Webhook endpoints might sometimes receive the same event multiple times. To prevent handling duplicate events, ensure your event processing is idempotent. One approach is to log the events you’ve already processed and avoid processing any events that have been logged. This can be done using the unique ID of the message, present in all the messages we send.

Handle events asynchronously

Configure your handler to process incoming events using an asynchronous queue. Handling events synchronously can create scalability issues, especially during high-volume periods—like end-of-month invoice consolidations. Asynchronous queues allow your system to process multiple events concurrently at a manageable rate, improving performance and reliability.

Shared Secret

To decode the signature and verify that the event was sent by us, we generate a unique key when you configure a webhook endpoint. Each endpoint has its own unique shared secret. Store this secret securely. If you have any security concerns or need the secret refreshed, please contact our integration manager, and we will assist you.

Replay Attacks

A replay attack happens when an attacker captures a legitimate payload and its signature, then retransmits them. To prevent this, we include a timestamp in the Riverty-Signature header. This timestamp is part of the signed payload and is verified by the signature, preventing an attacker from modifying the timestamp without invalidating the signature. If the signature is valid but the timestamp is outdated, you can discard the payload.

Do you find this page helpful?