Getting Started

Hook0 makes it easy for your software systems to offer and distribute webhooks to your users.

Your app + Hook0 = ♥

Integrating Hook0 to your system will require you to interact with it in three different ways:

  1. Setup: create your organization and application, declare your event types
  2. Subscribe: manually create subscriptions to events (as an admin) or implement proxy endpoints in your app so that your users can create subscriptions to events that concern them
  3. Send events: make you app send events to Hook0 whenever something interesting happens


Organization & application

Head over to and register. This will create an organization and a user that owns it. You can then log into Hook0 UI and access your dashboard.

Next thing is to create an application inside your organization. You can name it the way you want!


About organizations and applications

An organization can have multiple users, with either read-write or read-only permissions. It is also linked to a pricing plan and its limitations. It can contain multiple applications.

An application is a logical unit that acts as a scope to everything event-related: events, event types, subscriptions, …

Having several applications can be useful if you want to manage different webhook systems that do not interact with each other. For example, it can be two independent SaaS apps, or your production and staging environments.

Event types

Then, you have a design task coming up: you need to list and name every event type your app can emit. You will be able to add or remove them afterwards, but it is easier to do this upfront, before you start sending events to Hook0.

Use Hook0 UI to create your event types!


In this tutorial we will only create one event type: mycrm.customer.created.

Application secret

In order for our app to be able to use Hook0 API, we need to create an application secret.

This can be done using Hook0 UI, and you will obtain a UUID token (such as 4f8d93f1-d8a1-4357-88ce-8dd029e99b4b). Keep this token close, we will refer to it using $APPLICATION_SECRET.


About application secrets

An application secret is basically an API token that is scoped to a given application.

See the API Authentication page for more details.



Before making a subscription, we need to talk about labels.

Let say an event of type mycrm.customer.created is to be emitted when some user create a new customer in your CRM app. Let also say that your CRM app is a multi tenant app, thus you have multiple organizations (let's go with org1 and org2 for the example). If user1 (who belongs to org1) create a new customer, you do not want user2 (from org2) to receive a webhook about it.

In Hook0, we created the concept of labels in order to scope events. This works in two steps:

  1. When your app send an event to Hook0, it has to specify one or several labels, which are a set of key/values strings. The keys would be scope names (org_id for example) and the values would indicate the specific entities (the actual ID of an organization for example).
  2. When someone create a subscription in Hook0, one has to specify one label. This means that only events that are marked with this label should be dispatched to this subscription.

In our previous example, we could mark our event with the following labels: all → yes and org_id → 1. If user1 create a subscription, we would ensure it would be with the label org_id → 1, which means user1 would only receive webhooks related to its organization. Adding the all → yes label to all our events could allow an instance administrator to create a subscription (with this same label) that would receive all webhooks without filtering by organization.


Labels are flexible

Depending on your system, you can use labels to mark your events in multiple ways. This allows multiple kinds of users to subscribe to events without receiving events that do not concern them.

Ask yourself who you want to offer webhooks to and make a label for each!


Labels in subscriptions must be enforced

Of course, your users should not send API call to Hook0, only your app should. This means you have to implement an endpoint/route in your app that allows your users to create a subscription. This endpoint would ensure that the subscription is created with the right label so that users cannot cheat!

Creating a subscription

As we discussed in the previous section, it is important to ask yourself which kind of users need to be offered webhooks. This might require to implement an endpoint or a route in your app so that they can create subscriptions.

In this tutorial, we will go with a simpler case: you, as an instance administrator of your app, want to receive webhooks for all events.

To create a subscription, we need the following things:

  • The application ID
  • An optional description
  • Optional metadata in a key/value form (that would be the machine-readable version of the description)
  • A boolean to define whether or not the subscription is enabled
  • A list of event types to subscribe to
  • A label (a key and a value)
  • Information related to the target (where the webhook should be sent):
    • A target type (for now, we only support http)
    • A target URL
    • Optional HTTP headers that should be included in the webhook HTTP requests

We will also need to authenticate our API call, so we will use our application secret.

Working with cURL, the API call to create a subscription would look like this:

curl --request POST \
     --url '' \
     --header "Authorization: Bearer $APPLICATION_SECRET" \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '
     "application_id": "your_app_ID",
     "description": "This is the subscription from the tutorial",
     "metadata": {
         "tutorial": "true"
     "is_enabled": true,
     "event_types": [
     "label_key": "all",
     "label_value": "yes",
     "target": {
         "type": "http",
         "method": "POST",
         "url": "",
         "headers": {}

Send events

Now you need to implement a few things in you app, so that it will send events to Hook0.


Your app will need to know three things:

  • Hook0 API URL: the URL of Hook0's API; usually if you are using Hook0 SaaS
  • your Hook0 application ID: an UUID you can find in Hook0 UI
  • your Hook0 application secret: $APPLICATION_SECRET

You should add these to the configuration system you use in your app so that these values can be easily obtained from anywhere in your code where you need to send events.

Sending an event

Now we are ready to send an event to Hook0 using the event ingestion endpoint.

Here is an example of what we would send using cURL (but you need to implement that in your app):

curl --request POST \
     --url '' \
     --header "Authorization: Bearer $APPLICATION_SECRET" \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '
     "application_id": "your_app_ID",
     "event_id": "some_uuid_for_your_event",
     "event_type": "mycrm.customer.created",
     "metadata": {},
     "labels": {
          "all": "yes"
     "occurred_at": "2022-11-04T16:12:58Z",
     "payload_content_type": "application/json",
     "payload": "{\"test\": true}"

It is important to mention that:

  • the event ID is an UUID that you need to generate
  • the occurred_at field is the date when the event occurred; it could be the current datetime, but it could a past date you already manipulate in your app
  • the payload_content_type field must be one of: text/plain, application/json or application/octet-stream+base64
  • the payload field must always be a string:
    • if payload_content_type is text/plain, it can contain any string
    • if payload_content_type is application/json, it must contain a JSON-encoded string (and not a JSON object/array directly, it must be a string from the event JSON perspective)
    • if payload_content_type is application/octet-stream+base64, it must contain a base64-encoded string

Receiving a webhook

At that point, your event should have been dispatched to the target you specified in the subscription! 🎉


Before doing anything with this webhook, you should verify it to prevent yourself from malicious webhook calls and replay attacks.