Webhooks
Metronome provides programmatic notifications in the form of webhooks. If you configure a webhook URL, Metronome will send an HTTP POST
request to that URL when certain events occur, such as an invoice being finalized. Your service can then react to that notification by updating customer state, sending an email, etc.
Metronome notifications have the following structure:
{
"id": string, // a unique identifier for this specific notification
"type": string, // the notification type
"properties": {
// additional type-specific properties to describe the notification
}
}
Talk to your Metronome representative to understand and configure which type of notifications you should expect to receive.
Receiving Webhooks
To receive Metronome webhooks, you'll need a webhook handler listening at a publicly accessible HTTPS URL.
Acknowledging the notification
Upon receiving a notification, your endpoint must return a successful status code, such as 200 OK
. If Metronome receives a status code >299, it will attempt to retry until it receives a successful status code.
Handling duplicate notifications
Under normal circumstances, Metronome will send each notification exactly once. However, there are a few situations that could cause you to receive the same notification multiple times:
- Retries -- As mentioned above, if Metronome receives an error when attempting to deliver the notification to your webhook handler, it will retry. Depending on the nature of the error, it's possible that your endpoint receives a notification without acknowledging it, in which case it will receive the same notification again.
- Multiple webhook URLs -- If you configure Metronome to notify multiple webhook URLs, or even the same URL multiple times, notifications will be sent multiple times. If you want to ensure duplicate notifications are ignored, you can use the notification's id field to deduplicate.
Verifying notifications
Because your webhook endpoint is a public URL, anyone could send a request to it. Before you take actions based on the notification, you should verify the information it contains. You can do this in two ways: by fetching data from the Metronome API yourself or by verifying the webhook request's signature.
Call the Metronome API
Webhook notifications contain only minimal information about the event that occurred. This means it's often useful to call the appropriate Metronome API endpoint to get the full details. For example, if you receive a webhook notification informing you that an invoice has been finalized, you can call the /invoices endpoint to fetch the details of the invoice mentioned in the notification. In this way, the notification serves as a hint that something has changed, but your code relies only on data obtained directly from the Metronome API. This means there's no need to verify the webhook request.
Signature verification
If the above strategy doesn't work for your use case, Metronome also provides a method to verify the authenticity of notifications as you receive them by using the Metronome-Webhook-Signature HTTP header. The value of this header is a cryptographic signature of the HTTP request, using a secret key set up when you configure your webhook.
If you have multiple webhooks configured on your Metronome account each one will have it's own secret key.
To validate the signature, first concatenate the value of the request's Date
header and the exact bytes of the request body, separated by a newline character (\n
). Then compute the HMAC-SHA256 of the resulting string, keyed by the webhook's secret key. Finally, compare the hexadecimal representation of the HMAC you computed with the one found in the Metronome-Webhook-Signature
header. If they don't match, the webhook notification did not come from Metronome.
HMAC_SHA256(secret_key, DATE_HEADER + "\n" + BODY)
The Date
header is included to aid in deduplication. You should ignore webhook requests that are older than five minutes, which means your webhook handler only needs to store recent notification IDs to prevent duplicates.
When computing the signature, Metronome uses the exact bytes sent in the request body. Be careful to do the same in your code. If you try to use the parsed JSON body for verification purposes, you'll likely fail signature verification because serializing the data again is not guaranteed to produce the same JSON.
The following code example shows how to perform signature validation:
- bash
- JavaScript
echo -n "$DATE_HEADER\n$BODY" | openssl dgst -sha256 -hmac $KEY
crypto.createHmac("sha256", KEY).update(`${headers["Date"]}\n${body}`).digest("hex");
Example webhook request
The following example webhook was sent to the URL https://example.com/webhook
. The secret key for verification was correct-horse-battery-staple
:
POST /webhook HTTP/1.1
Host: example.com
User-Agent: Metronome
Content-Type: application/json
Date: Mon, 02 Jan 2006 22:04:05 GMT
Metronome-Webhook-Signature: b82652fa2246cf1d8a27e591f155c865f68b46c19b9213fd9c052f2419b4742b
{
"id": "b2c9e307-624e-4e7d-a5a4-1b74107d78c4",
"type": "widget_created",
"properties": {
"customer_id": "5f794d50-085a-4db6-8d15-286e518b7225",
"widget_id": "0891458d-b6f0-4fdd-a41e-380aae1a1e38"
}
}