Setting up a webhook

To set up a webhook, you can create one in the Extend dashboard settings under the “Developer” tab Once created, you will start to receive webhook events to the url you specified during workflow runs.

Verifying webhook requests from Extend

Extend will sign each webhook request using a secret unique to the webhook. You can use this signature along with the timestamp to verify that the request is coming from Extend as well as protect against replay attacks.

Steps to verify a webhook request from Extend

At a high level, the steps to verify a webhook request from Extend are
  1. Retrieve the timestamp of the request from x-extend-request-timestamp, the body of the request, and the signing secret associated with the webhook.
  2. Concatentate the timestamp and request body using the following format: v0:${timestamp}:${requestBody}
  3. Compute a HMAC 256 digest on the resulting string using the signing secret as the key. The secret can be found in the webhooks table under the “Developer” tab
4. Compare this digest with the signature provided in x-extend-request-signature. If they are equal, then the request is verified to be from Extend. Here is pseudocode in Javascript to perform the verification:
  import crypto from "crypto";

  // retrieve from x-extend-request-timestamp
  const timestamp = 1707777128;

  const requestBodyString = JSON.stringify(request.body);

  // retrieve from the webhook details on the "Developers" tab
  const signingSecret = "wss_C...l";

  const message = `v0:${timestamp}:${requestBodyString}`;
  const expectedSignature = crypto.createHmac("sha256", signingSecret).update(message).digest("hex");

  // retrieve from x-extend-request-signature
  const receivedSignature = "d3a8d5de6d463023b052ee1eb8e7f247dce6bf90b4a3e1117b4922afdc90029b";

  if (expectedSignature === receivedSignature) {
    // proceed
  }

Webhook event shape

FieldDescription
eventIdstring - Unique identifier for the event
eventTypestring - Type of the event that occurred (workflow_run.completed)
payloadobject - Contains the WorkflowRun object. See the GET WorkflowRun endpoint for the shape.
Here is what you can expect for a given incoming event:
Example Event
{
  "eventId": "event_1234",
  "eventType": "workflow_run.completed",
  "payload": {
    "object": "workflow_run",
    "id": "workflow_run_1234"
    // etc.
  }
}

Event types

The following table outlines the various event types you can receive via webhooks:
Event TypeDescription
workflow_run.completedTriggered whenever a WorkflowRun is completed
workflow_run.failedTriggered whenever a WorkflowRun fails
workflow_run.needs_reviewTriggered whenever a WorkflowRun needs review*
* Only triggered when the workflow is configured to have a HumanReview step in the Extend workflow builder.