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:
Click to show.
Click to show.
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 (
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.
Click to show.
Click to show.
live or sandbox) given in the Environment header. The HUB2 API responds with HTTP 201 and a body such as:Click to show.
Click to show.
This response contains the secret associated with the webhook:
"secret": "whsec_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX". It is returned only once, at creation.3
Verify the webhook signature.
To make sure a webhook comes from the HUB2 API, check the signature of its body (payload).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.
a. Get the secret of the webhook.
This secret was returned in step 2 ("secret": "whsec_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" in the example).b. Sign the payload.
Readt, the Unix timestamp in seconds, from the Hub2-Signature-V2 header (see step c). Take the body of the POST request sent by HUB2 (see step 1) as a string, exactly as received, and compute the HMAC-SHA256 of the string <t>.<raw body> with the secret as key, encoded in lowercase hexadecimal.Examples by programming language:c. Check the signature.
Finally, compare the computed signature with the one sent by HUB2 in the request headers:Hub2-Signature-V2: header name (HTTP header names are case-insensitive).t: Unix timestamp in seconds, the one you signed in step b.v1: signature computed with the currentsecret.v0: signature computed with the previous secret during the 24 hours following a rotation. Otherwise,v0is omitted.
t is no more than 5 minutes away from your current time and your signature matches v1, or v0 during a secret rotation. Use a constant-time comparison function where your language provides one. Retries and replays carry a new t but the same event id: deduplicate on the id.Each request also carries the legacy
Hub2-Signature: s1=<signature>,s0=<signature> header, where s1 and s0 are the HMAC-SHA256 of the raw body alone, with the current and previous secret (s0 is empty outside a rotation). It is kept for existing integrations, but it has no timestamp and does not protect against replayed requests: use Hub2-Signature-V2.