Webhooks

Ask Magistrate to notify you when specific events happen by passing a webhook_url when you create an envelope.

How to use webhooks

Creating a webhook endpoint is similar to creating any normal endpoint in your application or website. It's a publicly accessible URL where Magistrate can POST JSON payloads. You tell Magistrate what the URL is when you create an envelope by passing the webhook_url attribute. This immediately dispatches a webhook of type webhook_url_verification.

Your URL should return a 2xx status code when it receives a POST request. We recommend that your webhook endpoint quickly return a 2xx status code and process the JSON payload after returning the successful response to Magistrate's webhook request. Magistrate will automatically retry webhooks that receive a 3xx, 4xx, or 5xx response status code. It will retry it every two hours up to three times.

Magistrate will not retry webhooks of type webhook_url_verification, and if that fails (i.e., does not return a 2xx status code), the API call itself will fail with status code 400.

Magistrate does not guarantee that webhooks will arrive in any particular order, so your application should take care to check the occurred_at timestamp of the event.

Shape generally

The exact payload for a webhook depends on the webhook's type. But all webhooks are shaped like this:

  • Name
    id
    Type
    string
    Description

    Unique ID of the webhook. This can be used as an idempotency key to ensure you are not processing the same webhook more than once.

  • Name
    api_version
    Type
    integer
    Description

    The API version. This is always 1.

  • Name
    type
    Type
    string
    Description

    Type of the webhook. This will always be envelope_signed or webhook_url_verification, but we recommend you check this in your application code because other webhook types will be added over time and will be considered non-breaking changes to the API.

  • Name
    occurred_at
    Type
    string
    Description

    Date and time the event causing the webhook occured. ISO-8601 formatted string.

  • Name
    data
    Type
    object
    Description

    Actual data related to the webhook. Will contain at least an envelope_id key. Other data depends on the webhook type.

Magistrate webhook payload

{
  "id": "aaa9ad59-33c2-4290-bf66-bab79002b71e",
  "api_version": 1,
  "type": "envelope_signed",
  "occurred_at": "2022-10-10T09:35:41Z",
  "data": {
    ...
  }
}

Check signatures

Magistrate signs the webhooks it sends to your endpoint by including a signature in the Magistrate-Signature header. This allows you to verify that the webhook is authentic. Magistrate generates signatures using a hash-based message authentication code (HMAC) with SHA-256.

Magistrate-Signature:
t=2022-10-10T14:55:03Z,
v1=d53617a93be26024b3e27f9978d3a6ee20d5e2c2284975a97dd8f35ad088f8d3

To verify the signature, follow these steps:

  1. Split the value of the Magistrate-Signature header, using the , character as the separator, to get a list of elements. Then split each element, using the = character as the separator, to get a prefix and value pair. The value for the prefix t corresponds to the timestamp, and v1 corresponds to the signature.

  2. Generate a signed_payload string by concatenating:

    • The timestamp
    • The character .
    • The JSON payload, i.e., the request body
  3. Calculate the expected signature by computing an HMAC with the SHA256 function and taking the hexadecimal digest. The secret key can be obtained in your integration panel. Use the signed_payload string as the message.

  4. Compare the expected signature to the signature in the header. If it matches, compute the difference between the current timestamp and the received timestamp and decide if the difference is within your tolerance. The delta should be no more than a couple of seconds.

Here is an example of how to verify the signature in your app:

Verifying a request

const signature = req.headers['Magistrate-Signature']
const timestamp = signature.split(",")[0].split("=")[1]
const signed_payload = timestamp + "." + req.body
const hash = crypto.createHmac('sha256', secret).update(signed_payload).digest('hex')

const expected = signature.split(",")[1].split("=")[1]
if (hash === expected) {
  // Request is verified
} else {
  // Request could not be verified
}

Webhook type reference

There are two webhook types. We will be adding additional webhook types in a backwards-compatible way over time.

Webhook type: envelope_signed

The envelope_signed webhook type is sent when any party signs an envelope. If there are multiple signature blocks for that party in an envelope, this webhook is sent each time a signature block is signed.

If you create a contract with the autosign attribute as true, it will immediately trigger an envelope_signed webhook for the signature blocks that were automatically signed.

The recommended way to determine if the envelope has been completely signed is to look at value of data.envelope_status. If its partially_executed, that means there remain empty signature blocks. If its fully_executed, that means all signature blocks have been signed.

If you need information about the envelope that is not included with the webhook, you should retrieve the envelope.

The data attribute has the following shape:

  • Name
    envelope_id
    Type
    string
    Description

    Unique ID of the envelope that is the subject of the webhook.

  • Name
    signature_id
    Type
    string
    Description

    Unique ID of the signature that was just signed.

  • Name
    envelope_status
    Type
    string
    Description

    One of fully_executed or partially_executed depending on if the envelope has been completed by all parties or not, respectively.

envelolpe_signed webhook payload

{
  "id": "f9c62dca-5a5b-4564-a0a9-cd86bbe7fde0",
  "api_version": 1,
  "type": "envelope_signed",
  "occurred_at": "2022-10-10 10:14:01Z",
  "data": {
    "envelope_id": "891a4c2f-e0d8-4256-ad10-e217f3e6ac12",
    "signature_id": "346d3ab0-677b-421f-8e3e-795de74044ad",
    "envelope_status": "fully_executed"
  }
}

Webhook type: webhook_url_verification

The webhook_url_verification webhook type is sent immediately when a user passes a webhook_url parameter in an API call. This tests to make sure the URL is valid and returning a 2xx status code.

The data attribute has the following shape:

  • Name
    user_email
    Type
    string
    Description

    The email address of the user who made the API call that triggered this webhook.

webhook_url_verification webhook payload

{
  "id": "c0fa00dc-5da0-4bfe-9b46-3a34f729f8cc",
  "api_version": 1,
  "type": "webhook_url_verification",
  "occurred_at": "2022-11-10 12:12:02Z",
  "data": {
    "user_email": "harry@getmagistrate.com"
  }
}