Webhooks

Collection resource

Path: /webhooks

Allowed methods: GET, POST

Individual resource

Path: /webhook/{uuid}

Allowed methods: GET, PUT, DELETE

Webhooks are HTTP requests that are executed asynchronously after certain events occur in the Pact Broker, that can be used to create a workflow or notify people of changes to the data contained in the Pact Broker. The most common use for webhooks is to trigger builds when a pact has changed or a verification result has been published, but they can also be used for conveying information like posting notifications to Slack, or commit statuses to Github.

Creating

To create a webhook, send a POST request to /webhooks with the body described below. You can also do a PUT to /webhooks/{uuid}, where the UUID is a identifier that you generate yourself. This supports upserting webhooks, allowing you to automate your Pact Broker set up.

The easiest way to create a webhook is by using the Pact Broker Client CLI. It is available as a docker container and a standalone executable for all platforms.

You can also create webhooks through the API Browser by clicking on the NON-GET button for the pb:webhooks relation on the index, pasting in the JSON body, and clicking “Make Request”.

Below is an example webhook to trigger a Bamboo job when any contract for the provider “Foo” has changed. Both provider and consumer are optional - omitting either indicates that any pacticipant in that role will be matched. Webhooks with neither provider nor consumer specified are “global” webhooks that will trigger for any consumer/provider pair.

{
  "description": "Trigger SomeProject CI",
  "provider": {
    "name": "Bar"
  },
  "events": [{
    "name": "contract_content_changed"
  }],
  "request": {
    "method": "POST",
    "url": "http://master.ci.my.domain:8085/rest/api/latest/queue/SOME-PROJECT?os_authType=basic",
    "username": "username",
    "password": "password",
    "headers": {
      "Accept": "application/json"
    }
  }
}

A request body can be specified as well.

{
  "events": [{
    "name": "contract_content_changed"
  }],
  "request": {
    "method": "POST",
    "url": "http://example.org/something",
    "headers": {
      "Content-Type": "application/json"
    },
    "body": {
      "some" : "json"
    }
  }
}

To specify an XML body, you will need to use a correctly escaped string (or use single quotes if allowed).

    {
      "events": [{
        "name": "contract_content_changed"
      }],
      "request": {
        "method": "POST",
        "url": "http://example.org/something",
        "headers": {
          "Content-Type": "application/xml"
        },
        "body": "<xml \"foo\"=\"bar\"></xml>"
      }
    }

BEWARE While the basic auth password, and any header containing the word authorization or token will be redacted from the UI and the logs, the password could be reverse engineered from the database, so make a separate account for the Pact Broker to use in your webhooks. Don’t use your personal account!

Consumer or provider label matching

Webhooks can be created to match events of certain set of consumers or providers by label. Use label attribute for either provider or consumer. Both are optional, but they cannot be provided when name attribute is present. Following example would trigger a webhook when any contract with async labeled provider changed its content:

    {
      "provider": {
        "label": "async"
      },
      "events": [{
        "name": "contract_content_changed"
      }],
      "request": {
        "method": "POST",
        "url": "http://master.ci.my.domain:8085/rest/api/latest/queue/SOME-PROJECT"
      }
    }

Event types

contract_published: triggered every time a contract is published. It is not recommended to trigger your provider verification build every time a contract is published - see contract_content_changed below.

contract_content_changed: triggered when the content of the contract, or tags applied to the contract have changed since the previous publication. If base_equality_only_on_content_that_affects_verification_results is set to true in the configuration (the default), any changes to whitespace, ordering of keys, or the ordering of the interactions or messages will be ignored, and will not trigger this event. It is recommended to trigger a provider verification build for this event.

contract_requiring_verification_published: when a pact is published, triggered once for each unique provider version that is either the latest from the main branch of the provider, or is currently deployed or released.

provider_verification_published: triggered whenever a provider publishes a verification result.

provider_verification_succeeded: triggered whenever a provider publishes a successful verification result.

provider_verification_failed: triggered whenever a provider publishes a failed verification result.

Dynamic variable substitution

The following variables may be used in the request path, parameters or body, and will be replaced with their appropriate values at runtime.

Example usage:

{
  "events": [{
    "name": "contract_content_changed"
  }],
  "request": {
    "method": "POST",
    "url": "http://example.org/something",
    "body": {
      "thisPactWasPublished" : "${pactbroker.pactUrl}"
    }
  }
}

Pacticipant versions used in the template parameters

The consumer version and provider version will be populated from different sources depending on which event has been triggered, and how it has been triggered.

contract published/changed
contract requiring verification published
provider verification published/failed/succeeded

Webhook Whitelist

To ensure that webhooks cannot be used maliciously to expose either data about your contracts or your internal network, the following validation rules are applied to webhooks via the Pact Broker webhook whitelist configuration settings .

The host whitelist may contain hostnames (eg "github.com"), domains beginning with * (eg. "*.foo.com"), IPs (eg "192.0.345.4"), network ranges (eg "10.0.0.0/8") or regular expressions (eg /.*\.foo\.com$/). Note that IPs are not resolved, so if you specify an IP range, you need to use the IP in the webhook URL. If you wish to allow webhooks to any host (not recommended!), you can set webhook_host_whitelist to [/.*/]. Beware of any sensitive endpoints that may be exposed within the same network.

The recommended set of values to start with are:

* your CI server's hostname (for triggering builds)
* your company chat (eg. Slack, for publishing notifications)
* your code repository (eg. Github, for sending commit statuses)

Alternatively, you could use a domain beginning with a * to limit requests to your company’s domain.

Note that the hostname/domain matching follows that used for SSL certificate hostnames, so *.foo.com will match a.foo.com but not a.b.foo.com. If you need more flexible matching because you have domains with variable “parts” (eg a.b.foo.com), you can use a regular expression (eg /.*\.foo\.com$/ - don’t forget the end of string anchor). You can test Ruby regular expressions at rubular.com.

Testing

To test a webhook, navigate to the webhook in the HAL browser, then make a POST request to the “pb:execute” relation. The latest matching pact/verification will be used in the template, or a placeholder if none exists. The response or error will be shown in the window.

Deleting

Send a DELETE request to the webhook URL.

Updating

Send a PUT request to the webhook URL with all fields required for the new webhook.