How Do I Set a Custom Webhook?
Customize your automation to any degree with our custom webhooks. You can use them to track all the booked, rescheduled, or canceled calls. Once you have your webhook set up and hosted, all you have to do is follow a few steps in ACE Meetings.
Webhooks are push API calls that let your app know an event has happened, in ACE's case this would be creating (booking), rescheduling, or canceling a meeting.
Each webhook is a POST request to a URL of your choice, with JSON data describing the event.
In order to acknowledge the event, your app must return a 2xx HTTP status code as any other status code will be considered a failure.
In case of two subsequent failures, the webhook to be automatically disabled.
Managing custom webhooks
In order to create a custom webhook, first off head to the Custom Webhook menu, and then click "Add a webhook".
This will open a modal, which will give you a few fields to fill in:
- Choose your trigger, between creating (book), rescheduling, or canceling a meeting. HTTPS endpoints are highly recommended, to avoid traffic being intercepted/sent in the clear. Make sure that you entered the correct URL to receive webhooks. You must keep the URL up-to-date and are responsible for the safety and security of the data that you transmit through webhooks.
- Paste your webhook URL in the URL field.
- Click "Confirm" to save the webhook.
Optionally, you can also add an HMAC SHA256 secret, which will encrypt the data. Scroll down to the Message Security section for more deails on this.
Once you did that, you will be all set! You will be able to set the webhook to be active or to be paused, or you can edit and delete it whenever.
Message Security
Each webhook can optionally define a secret cryptographic key in the HMAC SHA256 Secret field. Our servers will use that key to generate a hashed digest of each webhook payload. The resulting digest will be encoded to base64 and included in the x-ace-signature header of the webhook. Your server can then use the same process, creating a hashed digest of the payload using the same secret key on your side, and then encoding the resulting hash to base64 before comparing it to the value in that header.
A post with a valid, matching digest in the header can only have originated from a source that uses the correct secret key. If the key has been provided only to ACE Meetings, this confirms that the webhook data is authentic. You can find more information about hash-based message authentication at https://en.wikipedia.org/wiki/Hash-based_message_authentication_code.
Validating message signatures
See the following example code snippets to help you validate message signatures
Java
/** * * @param request - Standard HttpServletRequest * @param secret - The secret string saved in ACE Meetings * @return true - Valid Request, trust request * false - Invalid or spoofed, reject request */ public boolean isValid(HttpServletRequest request, String secret) throws Exception { String aceSignature = request.getHeader("x-ace-signature"); SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(), "HmacSHA256"); Mac mac = Mac.getInstance("HmacSHA256"); mac.init(secretKeySpec); String calculatedSignature = Base64.getEncoder().encodeToString(mac.doFinal(request.getInputStream().readAllBytes())); return calculatedSignature.equals(aceSignature); }
NodeJS with Express
// (Warning when using express and json, you must validate before the json parser) const express = require('express') const crypto = require("crypto"); const app = express() const secret = ""; // Setup validate function to validate before json parser app.use(express.json({ verify: function(req, res, buf, encoding) { const aceSignature = req.headers['x-ace-signature']; let isValid = isValidSignature(buf.toString(), aceSignature, secret); // Reject request if not valid }})); app.post('/', (req, res) => { // Handle request }); app.listen(3000, () => {}); const isValidSignature = (body, aceSignature, secret) => { const computedSignature = crypto.createHmac('sha256', secret) .update(body) .digest() .toString('base64'); return aceSignature === computedSignature; }
PHP
Note: Nginx users need to enable underscores in headers to use this.
$hash = base64_encode( hash_hmac( 'sha256', file_get_contents('php://input') , $secret, true ) ); if ($hash == $_SERVER['x-ace-signature']) { /* Your code here */ }