Webhook

1
2
3
4
5
{
    "Name": "RESTar.Admin.Webhook",
    "Kind": "EntityResource",
    "Methods": ["GET", "POST", "PATCH", "PUT", "DELETE", "REPORT", "HEAD"]
}

Webhooks are custom HTTP callback operations that are triggered by events that are raised by the RESTar application, and that generate HTTP requests with data that can be directed to either a local resource or a remote server on the internet. An introduction to webhooks is provided here.

The Webhook resource contains all webhooks currently added to the RESTar application. Webhooks consist of the following components:

  • A specified event selector that is used for selecting the events that should trigger the webhook. By default, the payload of the event is used as body in the outgoing request generated by the webhook, but this can be overridden by using a custom webhook request.
  • An HTTP method for the outgoing request. If no method is given, POST is used – which is what we usually want to use anyways.
  • A destination URI, that is used in the outgoing request. This can be a relative URI if the destination is a local RESTar resource, or absolute if the destination is any server on the local network or the internet.
  • HTTP headers to include in the outgoing request. This is usually required if an external destination requires authorization of some kind, and is always required for local destinations if the current RESTar application is set up to require API keys.
  • An optional custom request, to use when overriding the data to include as body in the outgoing HTTP request. See the section below for more information.

Webhook request bodies

When triggered by an event, the webhook will by default use the event payload as body for the outgoing HTTP request. How the payload is converted to a request body depends on the data type of the event payload, as well as the configuration of the webhook.

If the event payload is a binary data stream, it’s used directly as body of th outgoing HTTP request, with the content type defined by the event as value of the Content-Type request header. Since the data is already serialized, the webhook cannot change the content type.

If the payload consists of entities, they are serialized to binary data streams before used in the request body, and here the webhook can define the content type to use by setting the Content-Type header in Headers of the webhook. If no content type is set, JSON is used for entity payload serialization.

Notes on JSON

When serializing entity payloads to JSON, note that RESTar always writes entity payloads to JSON arrays, regardless of the number of entities contained in the event payload. This behavior mirrors how responses from GET requests always contain arrays, even if there is just one entity in the response. Remote servers accepting calls from RESTar webhooks using JSON as content type should therefore always expect arrays when deserializing the bodies of incoming requests.

Format

Entities in the Webhook resource have the following format:

Properties marked in bold are required.

Property name Type Description
Id string (read-only) A unique ID for this webhook
Label string A descriptive label for this webhook
Method Method The method to use in the triggered request. Default is POST
Destination string The destination URI for this webhook. Can be relative or absolute
EventSelector string The event selector to use for selecting the events that should trigger this webhook
Headers object The headers to include in the triggered request
IsPaused boolean Is this webhook currently paused? Paused webhooks are skipped
CustomPayloadRequest CustomPayloadRequest An optional local request to use when fetching event data to include as payload in the triggered request

Event selectors

Event selectors are URI strings that select event resources. Their syntax is identical to regular request URI strings, but cannot contain meta-conditions. Just like request URIs, they contain a resource and conditions, and the conditions are used to filter out events based on the properties of their payloads.

Examples

Imagine we have an event resource PersonCreated that has Person entities as payload. Events of this event resource type are raised every time a Person entity is created. Person entities, let’s say, have string properties Name and Email. For a webhook listening on PersonCreated events, we can use the following event selectors:

1
2
3
4
/PersonCreated                                    // the webhook is triggered by all PersonCreated events
/PersonCreated/Name>G&Name<H                      // only where the Person has a name beginning with 'G'
/PersonCreated/Name>G&Name<H&Email!=null          // only where the Person has a name beginning with 'G' and
                                                  // email is not null

Custom payload requests

Custom payload requests are local GET requests, selecting entities from a local entity or binary resource. If a CustomPayloadRequest instance is included in a Webhook definition, the resulting entities from evaluating the custom request is used instead of the data passed along with the event when defining the body of the outgoing HTTP request.

Custom webhook requests are useful when we want to use an Event as simply a webhook trigger, but define the webhook request body from a separate data source. Just as with webhooks, we need to define an Authorization header if the current RESTar application is set up to require API keys.

Format

Properties marked in bold are required.

Property name Type Description
Method Method (read-only) The method to use. Is always set to GET
URI string The URI to use
Headers object The headers to include in the request. Make sure to include Authorization if the current RESTar application requires API keys
Body object or array of object The body to use in the request
BreakOnError boolean Should the outgoing webhook request be aborted if this custom request generates an error response? If false, the error message is sent.
BreakOnNoContent boolean Should the outgoing webhook request be aborted if this custom request generates a 204: No content? If false, an empty request is sent.

Example

For this example, we have an entity resource Person. Entities of this resource can look like this:

1
2
3
4
{
    "Name": "George Bluth",
    "Email": "george@bluth.com"
}

We also have an event resource PersonCreated that has Person entities as payload. These events are raised whenever a new Person entity is inserted. We can list all available event resources using a GET request to RESTar.AvailableResource, and in the result we see PersonCreated:

1
2
3
4
5
6
7
8
9
10
GET /RESTar.AvailableResource/Kind=EventResource
Response body:
[
    {
        "Name": "MyApp.PersonCreated",
        "Description": "Raised whenever a Person entity is inserted, with the just inserted Person entity as payload",
        "Methods": [],
        "Kind": "EventResource"
    }
]

To create a webhook listening for all occurances when a Person entity was inserted, has a name longer than 10 characters and the Email property is not null or empty, we can use the following event selector:

1
/PersonCreated/Name.Length>10&Email!=null&Email!=''

Next, we want our webhook configured to send a POST request with the Person to a remote web service with URL https://example.com/person. We include apikey ABC123 in the Authorization header to authenticate our requests with the remote server.

The complete webhook would be defined as:

1
2
3
4
5
6
7
8
9
10
11
{
    "Label": "My webhook",
    "Method": "POST",
    "Destination": "https://example.com/person",
    "EventSelector": "/PersonCreated/Name.Length>10&Email!=null&Email!=''",
    "Headers": {
        "Authorization": "apikey ABC123"
    },
    "IsPaused": false,
    "CustomPayloadRequest": null
}