-
Notifications
You must be signed in to change notification settings - Fork 0
Webhooks
Christian KASSE edited this page Apr 2, 2026
·
1 revision
Essabu sends webhook events to your application when important actions occur on the platform. Webhooks are signed with HMAC-SHA256 to ensure authenticity.
| Event Type | Description |
|---|---|
invoice.created |
A new invoice was created |
invoice.paid |
An invoice was fully paid |
payment.succeeded |
A payment was completed |
payment.failed |
A payment attempt failed |
employee.created |
A new employee was added |
employee.terminated |
An employee was terminated |
loan.approved |
A loan application was approved |
loan.disbursed |
Loan funds were disbursed |
subscription.created |
A new subscription started |
subscription.cancelled |
A subscription was cancelled |
{
"id": "evt_abc123",
"type": "invoice.created",
"created_at": "2026-03-26T10:00:00Z",
"data": {
"id": "inv-uuid",
"total": 1500.00,
"currency": "USD",
"customer_id": "cust-uuid"
}
}Every webhook request includes an X-Essabu-Signature header. Always verify this before processing.
import hashlib
import hmac
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
"""Verify the webhook HMAC-SHA256 signature."""
expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)import hashlib
import hmac
import json
from flask import Flask, request, jsonify
app = Flask(__name__)
WEBHOOK_SECRET = "whsec_your_webhook_secret"
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
@app.route("/webhooks/essabu", methods=["POST"])
def handle_webhook():
payload = request.get_data()
signature = request.headers.get("X-Essabu-Signature", "")
if not verify_signature(payload, signature, WEBHOOK_SECRET):
return jsonify({"error": "Invalid signature"}), 401
event = json.loads(payload)
event_type = event.get("type", "")
data = event.get("data", {})
if event_type == "invoice.created":
print(f"New invoice: {data.get('id')} - {data.get('total')}")
elif event_type == "payment.succeeded":
print(f"Payment succeeded: {data.get('id')} - {data.get('amount')}")
elif event_type == "employee.created":
print(f"New employee: {data.get('first_name')} {data.get('last_name')}")
elif event_type == "loan.approved":
print(f"Loan approved: {data.get('id')} - {data.get('amount')}")
else:
print(f"Unhandled event type: {event_type}")
return jsonify({"received": True}), 200import hashlib
import hmac
import json
from fastapi import FastAPI, Request, HTTPException
app = FastAPI()
WEBHOOK_SECRET = "whsec_your_webhook_secret"
@app.post("/webhooks/essabu")
async def handle_webhook(request: Request):
payload = await request.body()
signature = request.headers.get("X-Essabu-Signature", "")
expected = hmac.new(WEBHOOK_SECRET.encode(), payload, hashlib.sha256).hexdigest()
if not hmac.compare_digest(f"sha256={expected}", signature):
raise HTTPException(status_code=401, detail="Invalid signature")
event = json.loads(payload)
event_type = event["type"]
data = event["data"]
# Process the event
print(f"Received: {event_type}")
return {"received": True}- Always verify signatures before processing webhook data
- Respond with 200 quickly -- do heavy processing asynchronously
- Handle duplicates -- webhooks may be delivered more than once
- Use HTTPS for your webhook endpoint
- Log all received events for debugging and audit trails
Getting Started
Core Concepts
Modules
Advanced