Webhooks
Webhooks are automated HTTP JSON requests sent by Sticitt to your server whenever a significant event occurs. They are the most reliable way to keep your system in sync with the Sticitt platform.
Send through the endpoints you want to receive the various webhooks to technology@sticitt.co.za. You can specify an endpoint for each event type, and for each environment. We will provide you with the webhook key for each environment.
1. Handling Requests
Sticitt sends webhooks as POST requests with a JSON body.
Response Requirement
To acknowledge receipt, your endpoint must return an HTTP 200 OK status code.
If your server returns any other status code (e.g., 400, 500, or 503), or if the request times out, Sticitt will treat delivery as failed.
- Retry Interval: The webhook will retry every 15 seconds.
- Best Practice: Your application should catch internal errors and still respond with
200 OKif the payload is malformed or irrelevant, unless you specifically want the system to retry (e.g., if your database is temporarily down).
2. Security & Verification
To ensure requests actually come from Sticitt and have not been tampered with, every webhook includes a cryptographic signature.
The Pay-Signature Header
Each request includes a custom header:
Pay-Signature: <Base64 Encoded String>
Verifying the Signature
You must calculate the HMAC-SHA256 signature of the raw request body using your webhook_key as the key, and compare it to the header value.
If the calculated signature does not match the Pay-Signature header, ignore the request. It may be a malicious attempt to spoof a payment.
Example: Calculating Signature
- C#
- Node.js
- Python
- PHP
- Java
using System.Security.Cryptography;
using System.Text;
public class Program
{
private static string CalculateSignature(string message, string webhookKey)
{
//Retrieve key from client secret.
var encoding = new UTF8Encoding();
var key = encoding.GetBytes(webhookKey);
var payload = encoding.GetBytes(message);
//Sign request
var pen = new HMACSHA256(key);
var signature = pen.ComputeHash(payload);
//Encode signature as base64
var base64Signature = Convert.ToBase64String(signature);
return base64Signature;
}
public static void Main(string[] args)
{
var message = "YOUR_MESSAGE_TO_BE_SIGNED";
var key= "YOUR_WEBHOOK_KEY";
Console.WriteLine("Calculated Signature: " + CalculateSignature(message, key));
}
}
const crypto = require('crypto');
function calculateSignature(message, webhookKey) {
// Retrieve key from client secret.
const key = Buffer.from(webhookKey, 'utf-8');
const payload = Buffer.from(message, 'utf-8');
// Sign request
const signature = crypto.createHmac('sha256', key).update(payload).digest();
// Encode signature as base64
const base64Signature = signature.toString('base64');
return base64Signature;
}
const message = "YourMessageToBeSigned";
const webhookKey = "YOUR_WEBHOOK_KEY";
const calculatedSignature = calculateSignature(message, webhookKey);
console.log("Calculated Signature:", calculatedSignature);
import hmac
import hashlib
import base64
def calculate_signature(message, webhook_key):
# Retrieve key from client secret.
key = bytes(webhook_key, 'utf-8')
payload = bytes(message, 'utf-8')
# Sign request
signature = hmac.new(key, payload, hashlib.sha256).digest()
# Encode signature as base64
base64_signature = base64.b64encode(signature).decode('utf-8')
return base64_signature
message = "YourMessageToBeSigned"
webhook_key = "YOUR_WEBHOOK_KEY"
calculated_signature = calculate_signature(message, webhook_key)
print("Calculated Signature:", calculated_signature)
<?php
function calculateSignature($message, $webhookKey) {
// Retrieve key from client secret.
$key = utf8_encode($webhookKey);
$payload = utf8_encode($message);
// Sign request
$signature = hash_hmac('sha256', $payload, $key, true);
// Encode signature as base64
$base64Signature = base64_encode($signature);
return $base64Signature;
}
// Example of usage
try {
$message = "YourMessageToBeSigned";
$webhookKey = "YOUR_WEBHOOK_KEY";
$calculatedSignature = calculateSignature($message, $webhookKey);
echo "Calculated Signature: " . $calculatedSignature;
} catch (Exception $e) {
echo $e->getMessage();
}
?>
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class SignatureCalculator {
private static String calculateSignature(String message, String webhookKey) throws Exception {
// Retrieve key from client secret.
byte[] key = webhookKey.getBytes(StandardCharsets.UTF_8);
byte[] payload = message.getBytes(StandardCharsets.UTF_8);
// Sign request
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
hmacSha256.init(secretKeySpec);
byte[] signature = hmacSha256.doFinal(payload);
// Encode signature as base64
String base64Signature = Base64.getEncoder().encodeToString(signature);
return base64Signature;
}
public static void main(String[] args) {
try {
String message = "YourMessageToBeSigned";
String webhookKey = "YOUR_WEBHOOK_KEY";
String calculatedSignature = calculateSignature(message, webhookKey);
System.out.println("Calculated Signature: " + calculatedSignature);
} catch (Exception e) {
e.printStackTrace();
}
}
}