CDNShark Documentation

Reseller API

← Back to Documentation

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

EventFires when
reseller.customer.createdYou create a customer
reseller.service.provisionedAn order is placed and your credit is debited
reseller.service.activeAsynchronous provisioning finishes successfully
reseller.service.failedAsynchronous provisioning fails after the charge
reseller.service.suspendedA service is suspended
reseller.service.unsuspendedA service is reactivated
reseller.credit.lowYour 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 secretthis 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.