Webhooks
Webhooks allow your application to receive real-time notifications about events that take place within the platform. Instead of continuously polling our API for updates, webhooks push data to your application when events occur.
Integrating through Apex AscendOS?Monark webhooks are not delivered to you. AscendOS sends order status updates as the
alternative_order.v1.updatedevent. See Building on Apex AscendOS.
Setup
Register an HTTPS endpoint with POST /primary/v1/webhook, giving its url and a token. Monark signs every delivery with the token.
PUT /primary/v1/webhook replaces the whole configuration, so send url, token and isActive every time. Leaving out isActive deactivates the webhook, and events raised while it is inactive are not delivered.
Delivery
Each event is delivered as an HTTPS POST with a JSON body of { "eventType": "...", "data": { ... } } and these headers:
X-Webhook-Signature: the signature described belowX-Webhook-Event-Id: a unique ID for the event. Use it to skip events you have already processedContent-Type: application/json; charset=utf-8User-Agent: MonarkWebhookClient
Monark picks up new events within about a minute. A delivery that times out after 30 seconds, returns 408 or a 5xx, or hits a network error is retried twice, after 1 and 5 seconds. After that it is marked as a failed delivery and is not sent again. Any other non-2xx response is marked as failed straight away. Return a 2xx as soon as you have stored the event, and do the processing afterwards.
Events can arrive out of order, so treat each one as a signal and re-read the record with a GET before acting on it.
Previous events, including failed deliveries, can be queried with the webhook/{webhookId}/events endpoint. Failed deliveries can't be resent, so check the event log after any outage on your side.
Webhook Signature Verification
The X-Webhook-Signature header carries a Base64-encoded HMAC-SHA256 of the raw request body, keyed with your webhook token (both as UTF-8).
To verify that the webhook came from our system and wasn't tampered with:
- Get the signature from the
X-Webhook-Signatureheader - Compute an HMAC-SHA256 using your webhook token as the key and the raw request body, exactly as received and before any parsing, as the message
- Base64-encode the result and compare it with the header using a constant-time comparison. Reject the delivery if they don't match
const crypto = require('crypto');
/**
* Validates a webhook signature
* @param {string|Buffer} payload - The raw request body, exactly as received
* @param {string} signature - The signature from the X-Webhook-Signature header
* @param {string} webhookToken - Your webhook token
* @returns {boolean} - Whether the signature is valid
*/
function validateWebhookSignature(payload, signature, webhookToken) {
const computed = crypto
.createHmac('sha256', Buffer.from(webhookToken, 'utf8'))
.update(payload)
.digest(); // raw bytes
const received = Buffer.from(signature || '', 'base64');
// timingSafeEqual throws if the lengths differ
return received.length === computed.length &&
crypto.timingSafeEqual(computed, received);
}using System.Security.Cryptography;
using System.Text;
/// <summary>
/// Validates a webhook signature
/// </summary>
/// <param name="payload">The raw request body, exactly as received</param>
/// <param name="signature">The signature from the X-Webhook-Signature header</param>
/// <param name="webhookToken">Your webhook token</param>
/// <returns>Whether the signature is valid</returns>
public static bool ValidateWebhookSignature(string payload, string signature, string webhookToken)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(webhookToken));
byte[] computed = hmac.ComputeHash(Encoding.UTF8.GetBytes(payload));
byte[] received;
try
{
received = Convert.FromBase64String(signature ?? string.Empty);
}
catch (FormatException)
{
return false;
}
return CryptographicOperations.FixedTimeEquals(computed, received);
}Events
For the list of supported events, see Webhook Event Types.
IP Whitelisting
For webhook IP whitelisting configuration, please ensure that the following IP addresses are added to your allowlist to enable proper communication with our webhook endpoints.
The sandbox environment webhook traffic will originate from
5.161.56.181/32
while production webhook requests will be sent from
107.20.245.176/32
These CIDR-formatted IP addresses should be configured in your firewall rules, security groups, or webhook endpoint access controls to allow inbound HTTPS traffic from Monark's systems.
Updated 11 days ago