Manage webhooks

In order to improve user privacy in accordance with GDPR regulations, Bitbucket and other Atlassian Cloud products are updating our product APIs to consolidate how we manage access to personal data. These API changes are necessary to support upcoming improvements to Atlassian products that give users greater control over who can see and access their data.

The short summary is that username endpoints and username fields will stop being available on April 12, 2019, and we’re introducing some new data points that are available immediately to replace them. For more information, visit the API deprecation notice.

Webhooks provide a way to configure Bitbucket Cloud to make requests to your self-hosted server (or another external service) whenever certain events occur in Bitbucket Cloud. A webhook consists of:

  • A subject – the resource that generates the events. Currently, this resource is the repository where you create the webhook.

  • One or more events – the default event is a repository push, but you can select multiple events that can trigger the webhook.

  • A URL – the endpoint where you want Bitbucket to send the event payloads when a matching event happens.

There are two parts to getting a webhook to work: creating the webhook and triggering the webhook. After you create a webhook for an event, every time that event occurs, Bitbucket sends a payload request that describes the event to the specified URL. Thus, you can think of webhooks as a kind of notification system.

If you're having problems with a webhook, see Troubleshoot Webhooks.

When to use webhooks

Use webhooks to integrate applications with Bitbucket Cloud, for example:

  • Every time a user pushes commits in a repository, you may want to notify your CI server to start a build.

  • Every time a user pushes commits or creates a pull request, you may want to display a notification in your application.

Advantages of webhooks

Without webhooks, if you want to detect when events occur in Bitbucket Cloud, you need to poll the API. However, polling the API is inconvenient, inefficient, and error-prone. Consider how SMS messages work on mobile phones. You don't have to check your messages every 5 minutes to see if you have a text because your phone sends you a notification. In the same way, webhooks work like the notification so that the API does not have to check for the same activity every minute.

Create webhooks

You can create a webhook through Bitbucket Cloud or with the API. Use the following steps to create a webhook on a repository in Bitbucket. The administrators of a repository are the only users who can create a webhook on that repository.

You can create up to 50 webhooks per repository.

  1. From Bitbucket, open the repository where you want to add the webhook.

  2. Click Repository settings on the left sidebar.

  3. On the Settings page, select Webhooks on the left sidebar.

  4. Click the Add webhook button to create a webhook for the repository.

  5. On the Add new webhook page, enter a Title with a short description.

  6. Enter the URL to the application or server.

  7. (Recommended) Enter the Secret so you can verify the incoming webhook payloads. For more details, see the Secure webhooks section.

  8. (Optional) If you don't want the webhook to be active after you save, remove the checkmark from Active.

  9. (Optional) If you're using a self-signed certificate and want to disable certificate verification, select Skip certificate verification.

    Note: We recommend that you don't disable certificate verification because self-signed certificates are inherently not secure. Read the next section for more information about why you would or wouldn't use self-signed certificates.

  10. If necessary, update the Triggers field.
    By default, the trigger for the webhook is a repository push, as demonstrated by the Repository push field. If you want additional or different actions to trigger the webhook, click Choose from a full list of triggers. You will see a list of all the event types that can trigger the webhook.

  11. After you entered all the necessary information for your webhook, click Save.

To create a webhook using the API, you need to know the format of the HTTP request that Bitbucket expects and the format of the HTTP response that Bitbucket returns to your server. Refer to the reference documentation for descriptions and examples of these requests and responses.

You may also need to know the Bitbucket Cloud IP addresses to allowlist.

If you use self-signed certificates

When you create a webhook, Bitbucket provides the Skip certificate verification option, which allows you to disable certificate verification when sending event payload requests to the webhook URL. You may want to use this option if you receive webhooks at an HTTPS endpoint that's using a self-signed SSL certificate. However, because self-signed certificates are inherently not secure, we strongly advise that you don't disable certificate verification unless:

  • You can't install a valid SSL certificate that a public certificate authority has signed, AND

  • You're not concerned about the security of your webhooks.

With HTTPS endpoints, the data we deliver is encrypted with a symmetric key which is itself encrypted using the public key of the SSL certificate. However, when using self-signed certificates, the certificate itself cannot be considered trustworthy since it has not been signed by a trusted authority. As a result, when we deliver data via an HTTPS endpoint with a self-signed certificate, we have no way to know that we're communicating with the intended server. That means that without certificate verification, a malicious party can successfully execute a man-in-the-middle (MITM) attack by posing as your server.

If possible, we recommend that you don't disable certificate verification. Obtaining an SSL certificate from a trusted certificate authority is the only way to be confident during the initial key exchange that both parties are who they say they are. That way, you know that the data Bitbucket sends you is encrypted properly with the public key from your certificate, and not someone else's. For some affordable options for SSL certificates, see:

Secure webhooks

About webhook deliveries

Once your self-hosted server is configured to receive payloads, it will listen for any delivery that's sent to the endpoint you configured. For security reasons, you should only process deliveries from Bitbucket Cloud.

To ensure your self-hosted server only processes deliveries from Bitbucket Cloud, you need to:

  1. Create a secret token for a webhook.

  2. Store the token securely on your self-hosted server.

  3. Validate incoming webhook payloads against the token, to verify they are coming from Bitbucket Cloud.

Creating a secret token

You can create a new webhook with a secret token, or you can add a secret token to an existing webhook. When creating a secret token, you should choose a random string of text with high entropy. You can also use the “Generate secret” button to let us to generate the secret for you. Make sure to record the secret somewhere secure, it can't be viewed or retrieved once the webhook is saved.

Updating a secret token

You can update the secret token of an existing webhook by editing a webhook. But be aware that any integrations using this secret will need to be updated.

Securely storing the secret token

After creating a secret token, you should store it in a secure location that your server can access. Never hardcode a token into an application or push a token to any repository.

Validating webhook deliveries

Bitbucket Cloud will use your secret token to create a HMAC signature that's sent to you with each payload. The hash signature will appear in each delivery as the value of the X-Hub-Signature header. The value of the header be formatted as method=signature as defined by WebSub. The method can be one of the hashes listed in WebSub. The signature will be the HMAC of the body using the hash specified in method. Right now, Bitbucket will send HMACs using sha256. This might change in the future.

In your code that handles webhook deliveries, you should calculate a HMAC of the body using your secret token and the hash specified in the method. Then, compare the HMAC that Bitbucket Cloud sent with the expected HMAC that you calculated, and ensure that they match. For examples showing how to validate the hashes in various programming languages, see the Examples section.

There are a few important things to keep in mind when validating webhook payloads:

  • Bitbucket Cloud uses an HMAC hex digest to compute the hash.

  • The HMAC is generated using your webhook's secret token, the payload contents and the hash algorithm listed in method.

  • If your language and server implementation specifies a character encoding, ensure that you handle the payload as UTF-8. Webhook payloads can contain unicode characters.

  • Never use a plain == operator. Instead consider using a method like secure_compare or crypto.timingSafeEqual, which performs a "constant time" string comparison to help mitigate certain timing attacks against regular equality operators, or regular loops in JIT-optimized languages.

Testing the webhook payload validation

You can use the following secret, payload and method values to verify that your implementation is correct:

  • secret: It's a Secret to Everybody

  • payload: Hello World!

  • method: sha256

If your implementation is correct, the signatures that you generate should match the following signature values:

  • signature: a4771c39fbe90f317c7824e83ddef3caae9cb3d976c214ace1f2937e133263c9

  • X-Hub-Signature: sha256=a4771c39fbe90f317c7824e83ddef3caae9cb3d976c214ace1f2937e133263c9

Examples

You can use your programming language of choice to implement HMAC verification in your code. Following are some examples showing how an implementation might look in various programming languages. Note that in the examples we are assuming Bitbucket is sending a HMAC using the sha256 hash. Bitbucket might start using another hash for the HMAC in the future. The example code here will start failing if this happens.

Java example

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HexFormat; public class Main { public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException { final String secret = "It's a Secret to Everybody"; final String payload = "Hello World!"; final String givenSignature = "sha256=a4771c39fbe90f317c7824e83ddef3caae9cb3d976c214ace1f2937e133263c9"; final SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); final Mac mac = Mac.getInstance("HmacSHA256"); mac.init(keySpec); final byte[] digest = mac.doFinal(payload.getBytes(StandardCharsets.UTF_8)); final HexFormat hex = HexFormat.of(); final String calculatedSignature = "sha256=" + hex.formatHex(digest); if (!MessageDigest.isEqual(calculatedSignature.getBytes(), givenSignature.getBytes())) { System.out.println("Signatures do not match\nExpected signature:" + calculatedSignature + "\nActual: signature: " + givenSignature); } else { System.out.println("Signatures match"); } } }

Python example

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import hashlib import hmac secret = "It's a Secret to Everybody" payload = "Hello World!" given_signature = "sha256=a4771c39fbe90f317c7824e83ddef3caae9cb3d976c214ace1f2937e133263c9" hash_object = hmac.new( secret.encode("utf-8"), msg=payload.encode("utf-8"), digestmod=hashlib.sha256, ) calculated_signature = "sha256=" + hash_object.hexdigest() if not hmac.compare_digest(calculated_signature, given_signature): print( "Signatures do not match\nExpected signature:" f" {calculated_signature}\nActual: signature: {given_signature}" ) else: print("Signatures match")

Trigger webhooks

When an event associated with a webhook occurs, Bitbucket Cloud sends a request to the webhook URL containing the event payload.

If you want your server to check that the payloads it receives are from Bitbucket, you may need to allowlist certain IP addresses. For more specific information, see What are the Bitbucket Cloud IP addresses I should use to configure my corporate firewall?

You can create webhooks for the following events:

Refer to the event documentation for descriptions and examples of each event payload.

Additional Help