Webhooks
Outline supports webhooks for your workspace so that an external web server can be notified by HTTP when selected events occur within Outline.
Webhooks can be triggered whenever specific events occur in Outline. For example, you can configure a webhook to trigger whenever:
A new document is published
A comment is created
A user joins the workspace
…and much more.
Create a webhook
As an admin can add a new webhook through Settings → Webhooks, you can choose a descriptive name, the url to receive events, and select which events to receive.
Receiving webhooks
All webhooks will be sent as a POST request with the following JSON payload:
{
"id": string; // UUID that represents the delivery attempt
"actorId": string; // UUID of the user that triggered the event
"webhookSubsriptionId": string; // UUID of the specific webhook
"createdAt": string; // Date the event was sent in ISO 8601
"event": string; // The name of the event, eg. "users.create"
"payload": {
"id": string; // UUID of the model that was mutated
"model": Object; // The model attribute contains the properties of the object
}
}Your receiving endpoint should return with a 200 success response within 5000ms, any internal processing should be done on a background job if it might take longer than this.
Verifying requests
Outline creates a unique signature with each payload that enables you to optionally verify that the request is coming from Outline’s servers. You can find the signature in the Outline-Signature HTTP header (or outline-signature).
The signature is created by hashing the request body with the SHA-256 function, and combining it with an HMAC signing secret. The resulting signature is unique to each request and doesn't contain any secret information (source).
The following example code suggests how you might use this signature to verify the incoming request given an express-compatible NodeJS server:
Example
import * as crypto from 'crypto';
const header = request.headers['outline-signature'];
const timestamp = header.split(',')[0].split('=')[1];
const signature = header.split(',')[1].split('=')[1];
const body = request.body;
// Save from the webhook creation screen and store securely in your environment
const SECRET = process.env.OUTLINE_SIGNING_SECRET;
const calculatedSignature = crypto.createHmac('sha256', SECRET)
.update(`${timestamp}.${body.toString()}`)
.digest('hex');
if (calculatedSignature === signature) {
console.log('Signatures match.');
} else {
console.log('Signatures do not match.');
}Failures
If a delivery fails then it will be retried automatically several times with an exponential backoff. Webhooks will be automatically disabled when they have failed to deliver 25 events in a row. The creator will receive an email about the failure and can re-enable once the error is addressed.