Using hooks

Hooks are used to automate processes on the API. They decrease the amount of manual actions a user performs.

An example use case for hooks would be to automatically set a service and contract on a shipment when it is created. This use case could be interesting for an England based business that ships most of its products to England (and therefore always uses the same service). A hook could be created to automatically set the desired service and contract when a shipment to England is created, thus eliminating a big part of the shipment creation process.

Building a hook

Creating a hooks resource can be complicated, but can be split up by asking two questions:

  • When should the hook be executed (triggers)?
  • What should happen when the hook is executed (actions)?

Triggers

In order for a hook to trigger, specific conditions can be specified.

A hook for the example used above, would have to trigger when any shipment to England is created.

{
  "resource_type": "shipments",
  "resource_action": "create",
  "predicates": [
    {
      "operator": "==",
      "pointer": "/attributes/recipient_address/country_code",
      "value": "GB"
    },
    {
      "operator": "==",
      "pointer": "/attributes/recipient_address/region_code",
      "value": "ENG"
    }
  ]
}

Looking at the hook trigger above, the resource_type and resource_action attributes indicate that the hook should trigger when a resource of type shipments is created. Furthermore, the predicates specify that this hook should only trigger when when the country_code and region_code of the shipment’s recipient_address attribute are GB and ENG respectively.

For more information about triggers, see the resource page on hook triggers.

Actions

Looking at the example above, the actions for this hook would be to set a service and contract on the shipments resource when it is created. First, the uuid of the chosen service needs to be retrieved. In this case, an imaginary uuid will be used to represent the chosen service: ea7bf0c0-2eb5-4348-b90d-2fabd03c424c.

Secondly, a contract should be retrieved to set on the shipment that contains prices for the chosen service. An imaginary uuid is used again, this time to represent the contract id: e04134d0-1a43-4b29-a5de-d6c63f8d4f1b.

More information on services and contracts and how to retrieve them can be found on the their resource pages.

A hook action for the example used above would have to set the service and contract relationships on shipment creation.

{
  "action_type": "update-resource",
  "values": [
    {
      "pointer": "/relationships/service/data/id",
      "value": "ea7bf0c0-2eb5-4348-b90d-2fabd03c424c"
    },
    {
      "pointer": "/relationships/service/data/type",
      "value": "services"
    },
    {
      "pointer": "/relationships/contract/data/id",
      "value": "e04134d0-1a43-4b29-a5de-d6c63f8d4f1b"
    },
    {
      "pointer": "/relationships/contract/data/type",
      "value": "contracts"
    }
  ]
}

The action_type property indicates what kind of action the hook would perform when it is triggered. In this case it should update a shipments resource with the service and contract relationships. The values property can contain multiple values that the hook needs to set. In this case, the pointer properties of each value object resolve to the service and contract’s relationships objects. The value properties contain what value should be set on the resource property indicated by the pointer. In this case the id and type of the service and contract relationships objects are set to their id’s and resource types.

A hook can only set resource properties that have not already been set. It will not overwrite any values!

For more information about hook actions, see the resource page on hook actions.

Hook ownership

In order for a hook to trigger on a shipment creation, the shop creating the shipment should have access to it. Because hooks follow hierarchy, the hook in this example should be owned by either the shop creating the shipment or its parent organization. In this case the shop creating the shipment is the owner of the hook. The uuid 1bb3e441-8a70-4be8-b910-1315460859f2 is used as shop id.

A shops type resource has a parent resource of type organizations. This means that if a hook is owned by an organization, all shops will automatically use that hook.

Creating the hooks resource

After establishing when a hook should trigger and what it should do, the hook can be created. A hook is created by calling the POST /hooks endpoint, which will create a hooks resource in the MyParcel.com API.

{
  "data": {
    "type": "hooks",
    "attributes": {
      "name": "Set service and contract for shipments to England",
      "order": 100,
      "active": true,
      "trigger": {
        "resource_type": "shipments",
        "resource_action": "create",
        "predicates": [
          {
            "pointer": "/attributes/recipient_address/country_code",
            "operator": "==",
            "value": "GB"
          },
          {
            "pointer": "/attributes/recipient_address/region_code",
            "operator": "==",
            "value": "ENG"
          }
        ]
      },
      "action": {
        "action_type": "update-resource",
        "values": [
          {
            "pointer": "/relationships/service/data/id",
            "value": "ea7bf0c0-2eb5-4348-b90d-2fabd03c424c"
          },
          {
            "pointer": "/relationships/service/data/type",
            "value": "services"
          },
          {
            "pointer": "/relationships/contract/data/id",
            "value": "e04134d0-1a43-4b29-a5de-d6c63f8d4f1b"
          },
          {
            "pointer": "/relationships/contract/data/type",
            "value": "contracts"
          }
        ]
      }
    },
    "relationships": {
      "owner": {
        "data": {
          "type": "shops",
          "id": "1bb3e441-8a70-4be8-b910-1315460859f2"
        }
      }
    }
  }
}

The code block above shows what the request body for a hook that sets a service and contract on any shipment that has England as destination.

Chaining hooks and ordering

Multiple hooks can be triggered by the same resource action. Using the example from before, it would be possible to use two hooks:

A hook for setting the service relationship if the destination is England
A hook to set the desired contract when a shipment is created with the mentioned service

In order for the second hook (to set the contract relationship) to trigger, the first hook needs to be executed first. The order attribute of the hooks resource determines the priority of a hook when multiple hooks apply. A lower order means that it has higher priority. In this case, because the order of the first hook is lower (100) than the order of the second hook (200), the first hook is executed first.

Using multiplications of 100 for the order attribute makes it easier to “insert” new hooks before existing ones without having to update all of the existing hook’s order attributes.

12-03-2019