Reseller API — Webhooks
Webhooks let your billing system react to what happens on the platform instead of polling. Subscriptions belong to you, the reseller, and carry events about your customers — your customers never see them.
Available events
| Event | Fires when |
|---|---|
reseller.customer.created | You create a customer |
reseller.service.provisioned | An order is placed and your credit is debited |
reseller.service.active | Asynchronous provisioning finishes successfully |
reseller.service.failed | Asynchronous provisioning fails after the charge |
reseller.service.suspended | A service is suspended |
reseller.service.unsuspended | A service is reactivated |
reseller.credit.low | Your balance falls below your threshold |
The distinction between provisioned and active matters. provisioned means the order was accepted and you were charged. active means the thing actually exists and works — for a VPS those are minutes apart. failed means you were charged but the build did not complete, and is the event you should alert on.
The current list is always available from:
GET /api/reseller/webhooks/events
Create a subscription
curl -X POST "https://cdnshark.com/api/reseller/webhooks" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"label": "Billing system",
"url": "https://billing.example.com/hooks/cdnshark",
"events": ["reseller.service.active", "reseller.service.failed", "reseller.credit.low"]
}'
Use ["*"] to receive everything. The response contains a secret — this is the only time it is shown. Store it before discarding the response.
Verifying deliveries
Every delivery carries three headers:
X-CDNShark-Event: reseller.service.active
X-CDNShark-Delivery: 9f1c2e44-...
X-CDNShark-Signature: sha256=...
The signature is an HMAC-SHA256 of the raw request body using your secret. Verify it before trusting the payload, and compare using a timing-safe function:
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
if (! hash_equals($expected, $_SERVER['HTTP_X_CDNSHARK_SIGNATURE'])) {
http_response_code(401);
exit;
}
Payload shape
{
"event": "reseller.service.active",
"delivery": "9f1c2e44-3b7a-4c19-8f22-1d0e5a6b7c88",
"created_at": "2026-08-01T09:31:07+00:00",
"customer": {"id": 4210, "email": "jane@example.com", "name": "Jane Doe"},
"product_type": "vps",
"resource": {"vps_id": 771, "hostname": "web01.example.com"}
}
Order events additionally carry order and charged.
Retries and reliability
Respond with any 2xx to acknowledge. A non-2xx or a timeout (10 seconds) is retried three times with a growing delay — 5 minutes, 30 minutes, then 2 hours — after which the delivery is marked failed.
Deduplicate on delivery, and treat handlers as idempotent: a retry after your endpoint processed but failed to respond will arrive again.
Inspect delivery history, including failures and response codes:
GET /api/reseller/webhooks/{id}/deliveries
Rotating a secret
POST /api/reseller/webhooks/{id}/rotate-secret
Returns a new secret and invalidates the old one immediately, so deploy the new value first if you cannot tolerate a gap.