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
Please note request body can contain any UTF-8 characters.
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 UTF8Encoding().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).
Please note request body can contain any UTF-8 characters.
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 UTF8Encoding().GetBytes(data);
byte[] hashmessage = new HMACSHA256(keyByte).ComputeHash(messageBytes);
Console.WriteLine(string.Concat(Array.ConvertAll(hashmessage, x => x.ToString("x2"))));
}
}
}
Updated 9 months ago