Using data in webhook payloads

This topic describes how the plugin allows you to use data in webhook payloads. If you have a question, please respond to this topic. If you think there’s an issue with this process please file a bug report. If you’d like an update to this process, please submit a feature request.

Step 1. Extract the key(s)

First, you need to extract a relevant key(s) from the payload. This is done by providing a “path” to the value in the webhook receiver payload key path setting. A path uses a special syntax to handle nested items and arrays of items.

attr.key[]ref_key=ref_value.key

Given this payload object, the “value” is what is returned as the key. If there is an array in the path, multiple key values will be returned for later processing.

{
  "key" : {
    "key": [
      {
        "ref_key": "ref_value",
        "key": value
      }
    ]
  }
}

To break that down

  • Each level in the object is separated by .
  • An array is traversed using key[] (optional)
  • An array is filtered using ref_key=ref_value (optional)

To illustrate this, let’s look at handling a JSON webhook payload for an “Order creation” event from Shopify. The payload for that event looks something like this (shortened for convenience):

{
  "id": 820982911946154508,
  "email": "jon@doe.ca",
  "line_items": [
    {
      "title": "Aviator sunglasses",
      "product_id": 788032119674292922,
    },
    {
      "title": "Mid-century lounger",
      "product_id": 788032119674292922,
    }
  ],
  "customer": {
    "email": "john@test.com"
  }
}

Looking at this, we can see our Mr John Smith from Canada has purchased two products in this order: aviator sunglasses, and a couch (assuming that’s what a “lounger” is).

Now, say we want to give access to group A to anyone who purchases aviator sunglasses and access to group B to anyone who purchases a lounger. The best “key” to use here is the product ids for these products. So, our webhook receiver payload key path will look like this

line_items[].product_id

That will extract all product ids from a Shopify order creation payload for processing

Step 1A. Request (optional)

You can use the keys extracted in step 1 in a subsequent request to retrieve another key to replace the original key. To use this feature, you need to fill out three settings

webhook receiver request: Must be enabled for the feature to work.

webhook receiver request url: The endpoint url of the subsequent request. The key obtained in step 1 can be interpolated using :key. For example, to retrieve the metafields of a Shopify product you would use this url (you would first need to create a private app in your shopify account)

https://{apikey}:{password}@{hostname}.myshopify.com/admin/api/2021-01/products/:key/metafields.json

webhook receiver request key path: The key path of the key you want to extract from the response from the subsequent request. For example, a response to a Shopify metafield request looks like this (abbreviated)

{
  "metafields": [
    {
      "key": "group",
      "value": "premium"
    }
  ]
}

If you want to retrieve the value of a metafield using the metafield key you would use this path:

metafields[]key={key_value}.value

When a key is obtained in a receiver request it will replace the original key extracted from the webhook payload.

Step 2. Extract the user

Currently the plugin assumes that each webhook payload is being used to update objects specific to a single user. This may be updated or made more flexible in the future, but specific use cases will need to be identified.

This means we need to determine which user the payload concerns. The way the plugin handles this currently is through email matching. Likewise, this may be augmented or added to in the future. To match the payload to a user, provide a path to an email that will match a discourse user’s email, using the same path syntax as for the key.

In our Shopify order creation example, the path is customer.email.

Step 3. Map the key(s) to discourse objects

Now that we have keys and users we can perform specific actions via the webhook receiver key object map. This tells the plugin which key relates to which discourse object. The format of the map is

key:object_type.object_id

Currently the only supported object type are Discourse groups. So your key object map will look something like this

788032119674292922:group.138
788032119674292922:group.139
  • 788032119674292922 and 788032119674292922 are keys extracted from the payload
  • group is the object type
  • 138 and 139 are the ids of the groups the keys related to

If any of the keys extracted from the payload match an entry in this map, the action performed will depend on the object type. In the case of a group, the user extracted in step 2 will be added to the group.

In our Shopify example this means that if the plugin receives a webhook payload on the creation of an order and:

  • the customer email matches a discourse user’s email; and
  • product ids are mapped to group ids in the key object map

The matching discourse user will be added to the mapped group.