In the Integrations section of the Console, you can create Destinations for your integrations to link to:
Currently, only webhooks can be designated as the endpoint for an integration:
If you've defined a Notification Rule based on a system event, you can link this to a webhook integration Destination as the endpoint for the Notification. See Utilizing Events and Notifications for more details.
You can specify the type of authentication you want an integration to use when connecting to the Destination:
Currently, only the M3TER_SIGNED_REQUEST
credentials format can be used as the authentication method used for connecting to a webhook Destination. See the Webhook Authentication section below for more details on how to work with this format.
If credentials are not required, then dummy values can be used.
When you have created a Destination, you can link an integration or Notification to it and complete your setup.
Tip: Integrations Webhook API Example? See Integrations Webhook API Example in our API Reference for a worked example of creating a webhook destination using the API.
This topic explains how to create and manage your integration Destinations. Detailed guidance is also given on how to construct and verify a secure signature for the M3TER_SIGNED_REQUEST
:
To create a Destination:
1. Select Integrations>Destinations. The Destinations page opens and lists any existing Destinations.
2. Select Create destination. The Create page opens.
3. Enter Destination Details:
Name and Code:
Note that when you enter a name and click in the Code field, a default code is entered based on the name you've entered, which you can then edit as required.
Description for the Destination.
URL for the webhook Destination.
Important - only valid Domain Name System (DNS) entries permitted! If you enter an invalid DNS entry for the webhook destination URL, then an error message will show when you try to save the Destination.
4. In the Credentials panel:
Credential Type. Method of authentication with the Destination.
Note that only the M3TER_SIGNED_REQUEST
authentication method is currently available and the Credential Type field is pre-populated with this value.
Enter the API key and API secret you want use for the M3TER_SIGNED_REQUEST
authentication when connecting to the Destination.
5. Select Create Destination. You are returned to the Destinations Details page. The Destination is now available for linking your integrations or Notifications to it.
From the Destinations page, you can edit, view details, or delete a Destination.
To manage Destinations:
1. Select Integration>Destinations. The Destinations page opens and lists any existing Destinations.
2. If you want to edit a Destination select Edit:
3. On the Edit page, make your changes and select Update.
4. If you want to view the details of a Destination, select its NAME hotlink. The Destination Details page opens:
In this example, Notification Destination 1 details are shown. Note that you can Copy directly to your Clipboard the:
URL
Destination ID
5. If you want to delete a Destination, select Delete:
A confirmation dialog appears. Select Yes to confirm the delete action.
Warning! If you try to delete a Destination to which you've linked an integration or Notification, then you won't be able to and an error message will show.
Currently, the only authentication support for connecting to a webhook is signing a request using an ApiKey and ApiSecret. In m3ter, this is the M3TER_SIGNED_REQUEST
credentials format. This format implements a signed request for webhook access and is designed to enable you to build secure webhook endpoints and safeguard them from malicious attacks.
m3ter will sign all the requests it makes to your webhook. When you receive a request on your configured endpoint, you should:
Validate that the timestamp of the request is within an acceptable grace period.
Compute the signature based on the information you receive and compare that with the signature m3ter passes. This allows you to verify that the request was made by m3ter and not a third party as bad actor.
You'll receive the following m3ter headers:
X-m3ter-timestamp
- the timestamp when m3ter made the request.
X-m3ter-apikey
- the apiKey
corresponding to the apiSecret
used to sign the request.
X-m3ter-signature
- the signature m3ter computed for this request. You need to validate this header.
X-m3ter-signaturemethod
- the algorithm used for computing the signature. Currently, the algorithm used is always HmacSHA256
.
X-m3ter-version
- the m3ter signature algorithm. Currently, this is always 1
.
X-m3ter-signature
HeaderTo validate the X-m3ter-signature
header, you must prepare a payload
String that you sign with your API Secret.
To compute the payload, you must concatenate the following data using a pipe |
separator:
url
query string - Currently, there's no support for passing in query parameters. For now, you can hard code to this String: {}
API Key - provided in the X-m3ter-apikey
header.
timestamp -provided in the X-m3ter-timestamp
header.
body - the request body.
1POST https://test.com2X-m3ter-timestamp: 16884606853103X-m3ter-apikey: testApiKey4X-m3ter-signature: a9f9936e662512f943a904f3a71d0141c9bdfbf9fd5496902172864e9333ba155X-m3ter-signaturemethod: HmacSHA2566X-m3ter-version: 178body: {"orgId":"f49e8e22-ddd2-4367-b1ed-761e7e1fbdfd","entityId":"136f7b01-6bbd-4779-88a1-4a22d47b4f97","requestType":"NOTIFICATION","name":"Bill Approved for Locking","description":"Bill approved for locking","accountId":"16c14570-5790-43b5-9ed8-109541b780bb","originalEventId":"8ab97599-02a4-4604-b9fb-e0110ef3dbb9","eventName":"billing.bill.updated","notificationEventId":"679c70ef-f843-4dac-add2-75420666f598","notificationCode":"bill_approved_for_locking"}9
The payload will be:
1payload = "https://test.com|{}|testApiKey|1688460685310|{\"orgId\":\"f49e8e22-ddd2-4367-b1ed-761e7e1fbdfd\",\"entityId\":\"136f7b01-6bbd-4779-88a1-4a22d47b4f97\",\"requestType\":\"NOTIFICATION\",\"name\":\"Bill Approved for Locking\",\"description\":\"Bill approved for locking\",\"accountId\":\"16c14570-5790-43b5-9ed8-109541b780bb\",\"originalEventId\":\"8ab97599-02a4-4604-b9fb-e0110ef3dbb9\",\"eventName\":\"billing.bill.updated\",\"notificationEventId\":\"679c70ef-f843-4dac-add2-75420666f598\",\"notificationCode\":\"bill_approved_for_locking\"}"2
1const crypto = require('crypto');23// Main function to validate request authenticity4exports.validateSecret = function({ url, queryString, apiKey, apiSecret, timestamp, body, signature }) {5var currentTimestamp = Date.now();6var result = false;78// Check if the provided timestamp is in the past by comparing it with the current timestamp9if (currentTimestamp - 30 * 1000 > timestamp) {10var details = "timestamp in the past: " + currentTimestamp;11return {"result": result, "log": details};12}1314// Prepare the payload string by concatenating the request data15var sharedSecret = apiSecret; // Secret associated with the apiKey16var safeQueryString = !queryString ? '{}' : queryString;17var payload = url + "|" + safeQueryString + "|" + apiKey + "|" + timestamp + "|" + body;1819// Generate a cryptographic signature of the payload using HMAC-SHA25620var sig = crypto.createHmac('sha256', sharedSecret)21.update(payload)22.digest('hex');2324// Compare the generated signature with the provided signature using a timing-safe comparison25result = crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(signature));2627// Return the result and additional information for debugging28return {"result": result, "log": {"payload": payload, "sig": sig, "signature": signature}};29};3031
Login to the Support portal for additional help and to send questions to our Support team.