Consuming Webhooks
Details webhooks, including payload structure and best practices for receiving, authenticating, and processing event data at the endpoints
Consuming webhooks involves handling and processing event notifications sent from Upmind to your service’s endpoint. You may use official Upmind webhook endpoint libraries (e.g., upmind/webhook-endpoint for PHP) or write your own handler using any modern language or framework.
Events
Each webhook corresponds to a specific hook event (sometimes referred to as a trigger) by user actions (like staff login) or automated processes (such as recurring invoice payments).
When triggered, your webhook code receives a hook code identifying the event (e.g., invoice_paid_hook) and a unique webhook event ID, which can be used to prevent duplicate processing.
Payload
Upmind sends webhooks as HTTP POST requests with a JSON string payload in the request body. All payloads share a core structure and include a version property (default: V1) that defines their format.
You can see an example of a V1 webhook payload here. Webhook payloads include the following data:
- Unique event ID
- Hook category (e.g., client, invoice, subscription)
- Hook (event trigger)
- Date/Time
- Brand
- Actor (initiator, such as client or staff)
- Object (the main data, varies by category; for example, an invoice object)
Authentication
Each webhook endpoint is assigned a random secret used to authenticate incoming webhooks through a payload signature. Currently, this is the only supported authentication method, with more methods coming soon.

Authentication
For added security, verify the incoming request's IP address and proceed only if it matches one of Upmind's IP addresses.
Signature authentication
Each webhook request includes an X-Webhook-Signature
header, a SHA-256 HMAC hash of the request body created using the endpoint secret. In your code, you can compute the same hash and compare it to the header value, proceeding only if they match.
PHP and Node.js Signature Validation Example:
<?php
$secret = 'xxxxxxx'; // your webhook endpoint secret
$requestBody = file_get_contents('php://input') // raw request body;
$expected = hash_hmac('sha256', $requestBody, $secret);
if (!hash_equals($expected, $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'])) {
http_response_code(401);
exit('Invalid webhook signature');
}
let crypto = require("crypto");
let endpointSecret = "xxxxxxxxxx"; // your webhook endpoint secret
let requestBody = "{...}"; // raw request body
let signature = (hmac = crypto
.createHmac("sha256", endpointSecret)
.update(requestBody)
.digest("hex"));
// compare signature to x-webhook-signature header, and respond with an error if they don't match
Response and reliability
- Success: Return an HTTP 200 status. Upmind will log the response and consider the event delivered.
- Authentication Failure: Return HTTP 401; the event remains available in logs for review.
- Other Failures: For unexpected errors, return HTTP 500. Upmind logs unsuccessful attempts for troubleshooting.
Timeouts
Webhook requests time out after 30 seconds. The best practice is to queue incoming events first and then process them asynchronously using tools such as Redis, RabbitMQ, or SQS to avoid timeout errors.
Updated 15 days ago