CDNShark Documentation

Customer API

← Back to Documentation

Webhooks API

Webhooks send an HTTP POST to your URL when something happens in your account, so you do not have to poll. Manage them in the portal (Webhooks) or with the endpoints below.

Events

EventWhenFields in the payload
video.uploadedA video finished uploadingvideo_id, video_title, library_id
video.transcode.completeA video is ready to playvideo_id, video_title, library_id, duration, master_url
video.transcode.failedTranscoding failedvideo_id, video_title, library_id, error
pullzone.created / pullzone.deletedA pull zone was created or deleted (portal or API)pull_zone_id, label, cdn_hostname
storage.bucket.created / storage.bucket.deletedA bucket was created or deleted (portal or API)bucket_id, bucket_name
live.stream.started / live.stream.endedA live stream went live or stoppedstream_id, stream_slug, stream_name
payment.succeededAn invoice was paidinvoice_id, invoice_number, amount, currency, gateway

Every payload also has event, delivery (a unique id) and created_at:

{
  "event": "live.stream.started",
  "delivery": "5f0c2a2e-8a3b-4b7e-9f55-2f7a1c3d9e10",
  "created_at": "2026-09-26T18:13:57+00:00",
  "stream_id": 16, "stream_slug": "friday-show-x1y2z3", "stream_name": "Friday show"
}

Verify that a delivery is from CDNShark

Each request carries these headers:

  • X-CDNShark-Event: the event name.
  • X-CDNShark-Delivery: the delivery id.
  • X-CDNShark-Signature: sha256=<hex>: the HMAC-SHA256 of the raw request body, keyed with your webhook's secret.
// PHP
$expected = 'sha256=' . hash_hmac('sha256', file_get_contents('php://input'), $secret);
if (! hash_equals($expected, $_SERVER['HTTP_X_CDNSHARK_SIGNATURE'] ?? '')) { http_response_code(401); exit; }

// Node.js (Express: use express.raw() so you get the raw body)
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(req.body).digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(req.get('X-CDNShark-Signature') || ''));

Delivery and retries

Answer with any 2xx within 10 seconds. If your server cannot be reached or times out, we retry up to 3 times: after 5 minutes, 30 minutes and 2 hours. A delivery your server answers with a non-2xx status is recorded as failed and not retried. Use delivery to ignore duplicates.

Endpoints

MethodPathPermissionWhat it does
GET/api/webhookswebhooks:readYour webhooks (an array).
POST/api/webhookswebhooks:writeCreate. Body: label (up to 120 characters), url, events (an array of event names). Returns 201 with secret, shown once. Up to 20 per account.
PUT/api/webhooks/{id}webhooks:writeChange any of label, url, events, is_active.
DELETE/api/webhooks/{id}webhooks:writeDelete.
GET/api/webhooks/{id}/logswebhooks:readThe last 100 deliveries: event, attempts, HTTP status, errors.
GET/api/webhooks/eventswebhooks:readEvery event name with a description.
curl -X POST https://cdnshark.com/api/webhooks \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"label": "Live notifications", "url": "https://example.com/hooks/cdnshark",
       "events": ["live.stream.started", "live.stream.ended"]}'