Skip to content

Webhooks

Slipcase can send real-time notifications to your application when new articles are published. Instead of polling the API, your application receives an HTTP POST request for each matching article as it happens.

  1. A Slipcase administrator configures a webhook subscription for your organisation, including content filters and your endpoint URL.
  2. When an article is published that matches your filters, Slipcase sends an HTTP POST to your endpoint.
  3. Each request is signed with HMAC-SHA256 so you can verify it came from Slipcase.
EventDescription
article.publishedFired when a new article matching your filters is published

More event types may be added in the future.

Each webhook is an HTTP POST with Content-Type: application/json. The body is a single article object:

{
"id": 123456,
"heading": "Example article headline",
"excerpt": "A brief introduction to the article content...",
"body": "<p>Full article body in HTML.</p>",
"featured_image": "https://assets.slipcase.com/image/abc123",
"additional_images": [
"https://assets.slipcase.com/image/def456"
],
"date": "2026-04-17",
"url": "https://www.slipcase.com/article/example-article-headline",
"article_type": "article",
"article_format": 2,
"topics": ["Insurance", "Reinsurance"],
"organisation_logo_url": "https://assets.slipcase.com/logo/org123",
"organisation_name": "Example Publisher",
"external_url": "https://www.example.com/original-article",
"paywalled": false,
"registration_required": false
}

See Article Object — Push API payload for the full attribute reference.

Every webhook request includes the following headers:

HeaderDescription
X-Slipcase-SignatureHMAC-SHA256 signature for verifying authenticity
X-Slipcase-TimestampUnix timestamp (seconds) when the request was signed
X-Slipcase-Delivery-IdUnique UUID for this delivery attempt
X-Slipcase-EventEvent type (e.g. article.published)
Content-Typeapplication/json

Every webhook is signed using your subscription’s signing secret (provided by your Slipcase administrator). You should always verify the signature before processing a webhook.

The signature is computed as:

HMAC-SHA256( timestamp + "." + raw_body, signing_secret )
  1. Extract X-Slipcase-Timestamp and X-Slipcase-Signature from the request headers.
  2. Strip the sha256= prefix from the signature header.
  3. Concatenate the timestamp, a literal ., and the raw request body.
  4. Compute the HMAC-SHA256 hex digest using your signing secret.
  5. Compare your computed signature with the one from the header using a timing-safe comparison.
$timestamp = $_SERVER['HTTP_X_SLIPCASE_TIMESTAMP'];
$signature = str_replace('sha256=', '', $_SERVER['HTTP_X_SLIPCASE_SIGNATURE']);
$body = file_get_contents('php://input');
$expected = hash_hmac('sha256', $timestamp . '.' . $body, $signingSecret);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit('Invalid signature');
}
const crypto = require('crypto');
const timestamp = req.headers['x-slipcase-timestamp'];
const signature = req.headers['x-slipcase-signature'].replace('sha256=', '');
const body = req.rawBody; // raw request body as string
const expected = crypto
.createHmac('sha256', signingSecret)
.update(`${timestamp}.${body}`)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
res.status(401).send('Invalid signature');
return;
}
import hmac
import hashlib
timestamp = request.headers['X-Slipcase-Timestamp']
signature = request.headers['X-Slipcase-Signature'].replace('sha256=', '')
body = request.get_data(as_text=True)
expected = hmac.new(
signing_secret.encode(),
f'{timestamp}.{body}'.encode(),
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, signature):
abort(401, 'Invalid signature')

To prevent replay attacks, validate that the X-Slipcase-Timestamp is recent:

$timestamp = (int) $_SERVER['HTTP_X_SLIPCASE_TIMESTAMP'];
if (abs(time() - $timestamp) > 300) { // 5-minute tolerance
http_response_code(401);
exit('Timestamp too old');
}

The timestamp is part of the HMAC input, so it cannot be tampered with without invalidating the signature.

Each delivery includes a unique X-Slipcase-Delivery-Id. If your endpoint receives the same delivery ID more than once, you should treat subsequent deliveries as duplicates and skip processing.

Store processed delivery IDs (e.g. in a database or cache) and check before processing:

if ($this->alreadyProcessed($deliveryId)) {
http_response_code(200);
exit;
}

If your endpoint returns a non-2xx status code or fails to respond, the delivery will be retried automatically with exponential backoff. After all retry attempts are exhausted, the delivery is sent to a dead-letter queue for investigation.

  • Respond fast — return 200 OK immediately, then process asynchronously
  • Verify signatures — always validate X-Slipcase-Signature before trusting the payload
  • Check timestamps — reject requests older than 5 minutes
  • Handle duplicates — use X-Slipcase-Delivery-Id for idempotency
  • Use HTTPS — your endpoint must be accessible over HTTPS

Webhook subscriptions are configured by a Slipcase administrator. Contact your account manager to provide:

  • Your endpoint URL (must be HTTPS)
  • Any content filter preferences (topics, companies, article types, etc.)

You will receive a signing secret to verify incoming webhooks.