Securing Webhooks

Ensuring your integration is only receiving the expected Deliveroo requests.

Deliveroo notifies you about order and rider events through webhooks. A hash-based message authentication code (HMAC) signature, included alongside the webhook payload, can be used to verify the event. You may read more about HMAC here.

Once you have configured your webhook endpoints, we will provide a webhook secret. This secret is known only by you and Deliveroo. The verification signature is generated using the webhook secret.

Verifying Signature

This guide describes how to verify the old webhook events, i.e new_order and cancel_order event types.

Step 1: Extract the signature and GUID from request headers

Retrieve the GUID and signature from the request headers X-Deliveroo-Sequence-Guid and
X-Deliveroo-Hmac-Sha256, respectively.

Step 2: Prepare the signed payload

Create the payload by concatenating the GUID and the request body,

  • separated by \n (a newline character with a space before and after it) for legacy new_order and cancel_order webhooks in POS integration.
  • separated by (a space) for all the other webhooks.

Step 3: Determine the expected signature

Compute an HMAC with the SHA256 hash function. Use the webhook secret as the key, and use the payload prepared in step 2 as the message.

Step 4: Verify the signature

Compare the signature you determined with the signature you retrieved from the request header. You may consider the event valid only if the two signatures match.

Examples

package main

import "fmt"

func main() {
    seq := "our_sequence_guid"     // GUID from request header
    hmacSHA := "webhook_signature" // Signature from request header
    requestBody := "request_body"

    secret := "your_webhook_secret" // Your webhook secret
    mac := hmac.New(sha256.New, []byte(secret))

    data := []byte(fmt.Sprintf("%s \n %s", seq, requestBody)) // only for the legacy new_order and cancel_order webhooks in POS integration    
    // OR
    data := []byte(fmt.Sprintf("%s %s", seq, requestBody)) // for all the other webhooks
    mac.Write(data)
    expectedMAC := fmt.Sprintf("%x", mac.Sum(nil))

    if expectedMAC != hmacSHA {
        fmt.Println("Invalid webhook signature")
    }
}
require "openssl"

webhook_secret = "your_webhook_secret"
sequence_guid = "our_sequence_guid" // extract from request header
payload = "our_payload" // request payload

digest = OpenSSL::Digest.new('sha256')

data = "#{sequence_guid} \n #{payload}" // only for the legacy new_order and cancel_order webhooks in POS integration
// OR
data = "#{sequence_guid} #{payload}" // for all the other webhooks
OpenSSL::HMAC.hexdigest(digest, webhook_secret, data) // verify
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Cryptography;
using System.Text.RegularExpressions;

namespace Rextester
{
    public class Program
    {
       public static void Main (string[] args) {
        string webhook_secret = "your_webhook_secret";
        string sequence_guid = "our_sequence_guid";
        string payload = "our_payload";

        string data = string.Format("{0} \n {1}", sequence_guid, payload); // only for the legacy new_order and cancel_order webhooks in POS integration      
        // OR
        string data = string.Format("{0} {1}", sequence_guid, payload); // for all the other webhooks

        byte[] keyByte = new ASCIIEncoding().GetBytes(webhook_secret);
        byte[] messageBytes = new ASCIIEncoding().GetBytes(data);

        byte[] hashmessage = new HMACSHA256(keyByte).ComputeHash(messageBytes);
    
        Console.WriteLine(string.Concat(Array.ConvertAll(hashmessage, x => x.ToString("x2"))));
  }
    }
}

New Order And Rider Events Webhooks

This guide will help you how to verify the new order and rider events webhooks. There is a minor difference in verifying the new order and rider events webhooks. These webhook includes below events

  • order.new
  • order.status_update
  • rider.status_update

Step 1: Extract the signature and GUID from request headers

Retrieve the GUID and signature from the request headers X-Deliveroo-Sequence-Guid and
X-Deliveroo-Hmac-Sha256, respectively.

Step 2: Prepare the signed payload

Create the payload by concatenating the GUID and the request body, separated by (a blank space).

Step 3: Determine the expected signature

Compute an HMAC with the SHA256 hash function. Use the webhook secret as the key, and use the payload prepared in step 2 as the message.

Step 4: Verify the signature

Compare the signature you determined with the signature you retrieved from the request header. You may consider the event valid only if the two signatures match.

Examples

package main

import "fmt"

func main() {
    seq := "our_sequence_guid"     // GUID from request header
    hmacSHA := "webhook_signature" // Signature from request header
    requestBody := "request_body"

    secret := "your_webhook_secret" // Your webhook secret
    mac := hmac.New(sha256.New, []byte(secret))

    data := []byte(fmt.Sprintf("%s %s", seq, requestBody))
    mac.Write(data)
    expectedMAC := fmt.Sprintf("%x", mac.Sum(nil))

    if expectedMAC != hmacSHA {
        fmt.Println("Invalid webhook signature")
    }
}
require "openssl"

webhook_secret = "your_webhook_secret"
sequence_guid = "our_sequence_guid" // extract from request header
payload = "our_payload" // request payload

digest = OpenSSL::Digest.new('sha256')

data = "#{sequence_guid} #{payload}" // prepare  payload
OpenSSL::HMAC.hexdigest(digest, webhook_secret, data) // verify
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Cryptography;
using System.Text.RegularExpressions;

namespace Rextester
{
    public class Program
    {
       public static void Main (string[] args) {
        string webhook_secret = "your_webhook_secret";
        string sequence_guid = "our_sequence_guid";
        string payload = "our_payload";

        string data = string.Format("{0} {1}", sequence_guid, payload);

        byte[] keyByte = new ASCIIEncoding().GetBytes(webhook_secret);
        byte[] messageBytes = new ASCIIEncoding().GetBytes(data);

        byte[] hashmessage = new HMACSHA256(keyByte).ComputeHash(messageBytes);
    
        Console.WriteLine(string.Concat(Array.ConvertAll(hashmessage, x => x.ToString("x2"))));
  }
    }
}

What’s Next