Skip to main content

Webhooks

Webhooks let you receive events instantly instead of continuously polling your server. When an event occurs, Rabisu sends a signed POST request to your registered URL.

1. Register an Endpoint — POST /webhooks

curl -X POST https://api.rabisu.com/api/v1/webhooks \
-u "rsk_live_xxx:rsks_yyy" \
-H "Content-Type: application/json" \
-d '{
"url": "https://reseller.com/modules/addons/rabisu/webhook.php",
"event_types": ["service.*", "credit.added"],
"description": "Production webhook"
}'

The HMAC secret is returned only once — store it securely:

{
"success": true,
"data": {
"id": 12,
"url": "https://reseller.com/.../webhook.php",
"event_types": ["service.*", "credit.added"],
"secret": "whsec_...ONE_TIME...",
"is_active": true
},
"meta": { "trace_id": "...", "timestamp": "..." }
}

URL Rules (SSRF Protection)

  • https:// is required.
  • The URL may not contain user:pass@.
  • All resolved DNS IPs must be public (private/internal IPs are rejected).

2. Subscription Patterns

The event_types array supports these forms:

PatternMeaning
*All events (catch-all)
service.*Namespace wildcard — all events starting with service
service.createdExact event name

Valid namespaces: service, product, credit. Sending an invalid pattern makes the registration fail with 422 (a clear error instead of silently "receiving no events").

3. Event Catalog

EventWhenPayload fields (summary)
service.createdVPS provisioning completed (active)provision_id, service_id, order_id, product_id, status
service.suspendedService suspendedservice_id, reason
service.unsuspendedSuspension liftedservice_id
service.terminatedService terminatedservice_id
product.price_changedProduct price changed (notification)product_id
product.stock_changedProduct stock status changedproduct_id, stock_active
product.disabledProduct closed for saleproduct_id
credit.addedReseller credit added (refund/manual)reseller_id, amount, currency, reason, new_balance

Note: product.* events carry a notification only. Fetch the current data with GET /products/{id} (hybrid notification + pull).

Every payload includes a schema_version field at its root (currently 1).

4. Signature Verification (CRITICAL)

Every request includes an X-Rabisu-Signature header. The signature is the HMAC-SHA256 of the raw request body:

X-Rabisu-Signature: sha256=<hmac_sha256(raw_body, secret)>

Verification (PHP):

$raw = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $raw, $webhookSecret);
$received = $_SERVER['HTTP_X_RABISU_SIGNATURE'] ?? '';

if (!hash_equals($expected, $received)) {
http_response_code(401); // Invalid signature
exit;
}
// Safe: the payload can be processed
$payload = json_decode($raw, true);
  • Always verify the signature — otherwise you accept forged requests.
  • Use a constant-time comparison such as hash_equals.
  • Verify against the raw body before decoding to JSON (re-serialized JSON breaks the signature).

5. Delivery and Response Contract

Your endpoint should return the following HTTP codes:

ResponseMeaningRabisu behavior
2xxProcessed successfullyDelivery complete
4xx (incl. 401)Permanent error (signature/format)Not retried
5xxTransient errorRetried with exponential backoff

Retry schedule: 1m → 5m → 15m → 1h → 6h → 24h. After 6 attempts the event is marked "dead letter". After 5 consecutive failures the endpoint is automatically deactivated (circuit breaker) — reactivate it with PATCH /webhooks/{id} once fixed.

6. Management Endpoints

  • GET /webhooks — list registered endpoints (including inactive)
  • GET /webhooks/{id} — detail
  • PATCH /webhooks/{id} — reactivate / update event_types or description
  • DELETE /webhooks/{id} — delete (soft delete)