Webhook Basics
Getting Started
You can create webhooks either on your Workflows page or via the POST webhooks/subscribe endpoint.
A webhook event will be considered successful if the webhook URL returns a 200 HTTP response.
Verifying Signatures
Each webhook event sent by Zylvie is signed via a Hash-based Message Authentication Code (HMAC) using the workflow secret key.
We generate a unique secret key for each workflow automation that you create, which you can obtain from your Edit Workflow page.
The HMAC-SHA1 algorithm is used to generate the webhook payload signature, which is passed along with each request in the headers as Zylvie-Signature
.
Code Examples
You may use these follow code examples to verify webhook signatures, so you know for sure that it's coming from us:
-
Python
WEBHOOK_SIGNING_SECRET = 'webhook signing secret' def verify_signature(request_body, signature): digest = hmac.new(bytes(WEBHOOK_SIGNING_SECRET, 'UTF-8'), request_body, hashlib.sha1).hexdigest() return signature == digest if not verify_signature(request.body, request.META['HTTP_ZYLVIE_SIGNATURE']): # verification failed # verification success
-
PHP
const WEBHOOK_SIGNING_SECRET = 'webhook signing secret'; function verifySignature($webhookJson, $signature) { // Re-serialize the parsed JSON object $jsonString = json_encode($webhookJson); // Create HMAC-SHA1 digest of the re-serialized JSON $digest = hash_hmac('sha1', $jsonString, WEBHOOK_SIGNING_SECRET); return $signature === $digest; } // Read the raw request body $rawBody = file_get_contents('php://input'); // Parse the JSON into an associative array $webhookJson = json_decode($rawBody, true); if (!verifySignature($webhookJson, $_SERVER['HTTP_ZYLVIE_SIGNATURE'])) { // verification failed http_response_code(400); echo "Signature verification failed"; exit; } // verification success
-
Ruby
WEBHOOK_SIGNING_SECRET = 'webhook signing secret' post '/payload' do request.body.rewind body = request.body.read signature = request.env['HTTP_ZYLVIE_SIGNATURE'] # Parse the JSON body webhook_json = JSON.parse(body) # Re-serialize the JSON object, matching the Python implementation json_string = JSON.generate(webhook_json) # Generate HMAC-SHA1 signature using the re-serialized JSON digest = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), WEBHOOK_SIGNING_SECRET, json_string) unless digest == signature # verification failed halt 400, "Signature verification failed" end # verification success # Continue processing... end def verifySignature(webhook_json, signature) # Convert webhook_json (already parsed object) to string json_string = JSON.generate(webhook_json) # Create the HMAC-SHA1 digest digest = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), WEBHOOK_SIGNING_SECRET, json_string) return digest == signature end
-
Node.js
const WEBHOOK_SIGNING_SECRET = 'webhook signing secret'; const crypto = require('crypto'); function verifySignature(jsonObject, signature) { const jsonString = JSON.stringify(jsonObject); const digest = crypto .createHmac('sha1', WEBHOOK_SIGNING_SECRET) .update(jsonString) .digest('hex'); return signature === digest; }; app.post('/webhooks', function (req, res, next) { if (!verifySignature(req.body, req.headers['Zylvie-Signature'])) { // verification failed } // verification success });
Retry Policy
A webhook call will be retried for up to 3 times if the HTTP endpoint responds with any status code other than 200.