Using Webhooks

Why use Webhooks?

Webhooks are a powerful resource that you can use to automate your workflow and improve the scalability of your implementation.

With the exception of the step where you Create a Business via the API, the Middesk workflow is largely asynchronous.

Since Business entities are not static, it is common for Middesk to find updated information about that Business as it continues to monitor it. If you have a Webhook set up, Middesk can immediately notify you of that change upon discovery.

Some examples of when Middesk would send a Webhook are:

  • Approving a new account when a Business is complete and meets requirements
  • Notifying a team when a Business requires further review
  • Updating account profiles with accurate, validated business information

Creating a Webhook

If you provide Middesk a Webhook URL, we will send requests to it to notify you any time an event takes place for a Business.

📘

Registering Webhooks

To register your Webhook URL with Middesk, use our Webhooks API or go to the Webhooks section in your Dashboard Settings.

Webhook Events

A Webhook request consists of an Event object payload that Middesk will send via an HTTP POST request to your URL endpoint.

The request contains all the relevant information about how the Business object in question was updated, including the type of event and the data associated with it.

The id of the main object will be included in the headers with the key X-Correlation-Id. This allows for easily mapping together related Webhook events when only the headers are available.

An Event object payload contains the following fields:

PropertyTypeDescription
objectstringvalue is event.
idstringThe Middesk defined id representing the event.
created_atstringThe timestamp the event was created.
typestringCorresponds to an event, eg business.created, business.updated.
datastringA container for the data associated with the notification.
{
  "object": "event",
  "id": "f215a707-655e-400f-84e6-fbb949f5612a",
  "type": "business.created",
  "data": {
    "object": {
      "id": "0f86dab5-8195-4b95-b3c0-19deaeba2a8e",
      "tin": null,
      "name": "A Company",
      "tags": [],
      "names": [],
      "domain": null,
      "object": "business",
      "review": null,
      "status": "open",
      "orders": [
        {
          "id": "d9e4076c-25d7-4a93-917b-66568459cbc4",
          "object": "order",
          "status": "pending",
          "product": "identity",
          "created_at": "2020-01-02T23:54:48.180Z",
          "updated_at": "2020-01-02T23:54:48.180Z",
          "completed_at": null
        }
      ],
      "summary": null,
      "website": null,
      "officers": [],
      "addresses": [],
      "formation": null,
      "watchlist": null,
      "created_at": "2020-01-02T23:54:48.154Z",
      "updated_at": "2020-01-02T23:54:48.154Z",
      "external_id": null,
      "phone_numbers": [],
      "registrations": []
    }
  },
  "created_at": "2020-01-02T23:54:48.239Z"
}

🚧

Note: Middesk will add new events in the future. If there are specific events that you would like prioritized, please contact [email protected].

Types of Webhook Events

Today, Webhook requests consist of the following types:

TypeDescription
business.createdA new Business has been created.
business.updatedThe status of a Business has changed (with the exception of when a Business goes into an in_audit status).
industry_classification.createdA True Industry Classification has been created.
industry_classification.completedA True Industry Classification has completed.
order.createdAn Order has been created for a Business.
order.updatedAn Order has been updated.
subscription.createdA Subscription has been created for a Business.
subscription.updatedA Subscription has been updated for a Business.
tin.retriedThe TIN has been retried successfully.
agent_tax_registration.createdThe Agent Tax Registration has been created.
agent_tax_registration.updatedThe status of an Agent Tax Registration has changed.
lien.updatedThe status of a Lien has changed to filed when Middesk files with the state, or to open when Middesk has reflected the Lien (i.e. the UCC-1 is available).

Subscription-specific Webhook Events

If you create a Subscription for a specific event_type, you will receive one or more of the following webhook requests.

TypeDescription
tin.retrievedA TIN previously with unknown: true has been retried.
address.createdA new address was created for the Business.
address.deletedA previously found address was deleted for the Business.
bankruptcy.createdA new Bankruptcy has been added to the subscribed Business.
name.createdA new name was created for the Business.
name.deletedA previously found name was deleted for the Business.
person.createdA new officer was found for the Business.
person.deletedA previously found officer was deleted for the Business.
registration.createdA new SOS Registration was created for the Business.
registration.updatedA change has been detected for an SOS Registration associated with this Business.
watchlist_result.createdSent when a new watchlist hit has been found for a business that has been enrolled in Middesk's Watchlist Monitoring Subscription.

Checking Webhook Signatures

Middesk can optionally sign the Webhook requests that it sends to your endpoints. We do so by including a signature in the request's X-Middesk-Signature-256 header. This header allows you to verify that the requests were sent by Middesk, not by a third party.

Before you can verify signatures, you'll need to set a secret via the Webhooks API.

Signatures are generated by Middesk using a hash-based message authentication code (HMAC) with SHA-256. To check the signature, follow these steps:

Step 1: Extract the signature from the header

Read the value from the X-Middesk-Signature-256 header.

Step 2: Prepare the expected signature

Compute an HMAC with the SHA-256 hash function. Use the provided secret as the key, and use the response body as the message.

Step 3: Compare the Signatures

Compare the signature extracted from the header to the expected signature that you computed using a secure, constant time string comparison method.

require 'openssl'

secret = 'sec_...'

def verify(payload, signature)
  digest = OpenSSL::Digest.new('sha256')
  expected = OpenSSL::HMAC.hexdigest(digest, secret, payload)
  OpenSSL.secure_compare(expected, signature)
end

post '/my/webhook/url' do
  payload = request.body.read
  sig_header = request.env['X_MIDDESK_SIGNATURE_256']

  unless verify(payload, sig_header)
    # Invalid signature
    status 400
    return
  end
    
  event = JSON.parse(payload)
  
  case event.type
  when 'business.created'
    business = event.data.object
    puts 'Business created!'
  when 'business.updated'
    business = event.data.object
    puts 'Business updated!'
  # ... handle other event types
  else
    # Unexpected event type
    status 400
    return
  end

  status 200
end
from flask import Flask, request, abort
import hmac
import hashlib
import json
app = Flask(__name__)


secret = 'sec_...'


def verify(payload, signature):
    expected = hmac.new(secret, payload, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)


@app.route('/my/webhook/url', methods=['POST'])
def receive_webhook():
    payload = request.data
    sig_header = request.headers['X-Middesk-Signature-256']

    if not verify(payload, sig_header):
        # Invalid signature
        abort(400)

    event = json.loads(payload)

    if event['type'] == 'business.created':
        business = event['data']['object']
        print('Business created!')
    elif event['type'] == 'business.updated':
        business = event['data']['object']
        print('Business updated!')
    # ... handle other event types
    else:
        # Unexpected event type
        abort(400)

    return ''

Authenticating Webhooks using Mutual TLS

Another way to authenticate Middesk webhook requests is to verify a secure connection with the client using Mutual Transport Layer Security (Mutual TLS).

In a typical TLS connection, only the server's identity is authenticated by presenting a certificate to the client. The client verifies the server's certificate using a trusted 3rd party certificate authority. With Mutual TLS, the client will also present a certificate of its own to the server. This requires you to configure your server to request and verify a client certificate during the TLS connection handshake.

Middesk's webhook client certificate is issued by the DigiCert Assured ID Root G2 Certificate Authority which is a well-known certificate authority which is already configured on most operating systems by default but can be downloaded directly here or found among the list of DigiCert root certificates.

Our chosen certificate authority issues many certificates so it is crucial to verify that the client is indeed Middesk! Your server should verify that the client certificate has the following Subject Distinguished Name (Subject DN) fields before handling a webhook request:

O=Middesk\, Inc.

and

CN=webhooks.middesk.com

The first ensures that the client certificate was issued to Middesk, Inc., as verified by the certificate authority. The second ensures that the client certificate is being used as intended.

It is quite common for client TLS connection termination and HTTP request routing to be performed by a reverse proxy server. In this case, you must configure this proxy server to ask for and verify a client certificate. Then, before routing the webhook request to your backend server application, verify that the client certificate subject matches the one above.

IP Addresses for Webhooks

Below is the list of IP addresses that Middesk sends webhook requests from:

  • 35.239.59.102
  • 35.192.63.74
  • 104.198.38.1