Skip to main content
Follow these steps to integrate webhooks:
1

Create an HTTP endpoint to receive webhook requests.

This endpoint must accept POST requests such as the one below:
  • URL: https://website.com/webhook_payment (HTTPS is mandatory)
  • METHOD: POST
  • HEADERS:
  • BODY:
This is an example of a webhook sent for a payment_intent.created event. The data field holds the object concerned by the event, owner is your merchant ID and id identifies the event.
2

Register this endpoint with the HUB2 API and subscribe to events.

The HUB2 API provides a dedicated endpoint for this action. Call it with the following body:
Code samples:
The webhook is created in the environment (live or sandbox) given in the Environment header. The HUB2 API responds with HTTP 201 and a body such as:
This response contains the secret associated with the webhook: "secret": "whsec_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX". It is returned only once, at creation.
Store the secret securely: you need it to verify the integrity of every webhook you receive.For more details, see the webhooks API reference: Create a webhook.
3

Verify the webhook signature.

This step is mandatory: it ensures that no one can send you forged webhooks.Skipping it leaves a vulnerability that a malicious party could exploit, for example to have their own transactions validated.
To make sure a webhook comes from the HUB2 API, check the signature of its body (payload).

a. Get the secret of the webhook.

This secret was returned in step 2 ("secret": "whsec_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" in the example).

b. Sign the payload.

Take the body of the POST request sent by HUB2 (see step 1) as a string, exactly as received, and compute its HMAC-SHA256 with the secret as key, encoded in lowercase hexadecimal.Examples by programming language:
Sign the raw body as received, before any parsing. Parsing the JSON and serializing it again can change the string (spacing, key order, character escaping) and produce a different signature.

c. Check the signature.

Finally, compare the computed signature with the one sent by HUB2 in the request headers:
  • Hub2-Signature: header name (HTTP header names are case-insensitive).
  • s1: signature computed with the current secret.
  • s0: signature computed with the previous secret, if there is one. Otherwise, s0 is empty.
Accept the webhook if your signature matches s1, or s0 during a secret rotation. Use a constant-time comparison function where your language provides one.
When the secret is rotated (from the HUB2 dashboard), the previous secret is kept and used to compute s0 until the next rotation. This lets you switch to the new secret without rejecting any webhook.