NexIP Developers · Webhooks
Signed Webhooks
Receive monitoring and account events as HTTPS JSON with HMAC-SHA256 signatures, replay protection and predictable retry behavior.
HTTPS JSON
HMAC-SHA256
Replay protection
Webhook API 1.2
Events
NexIP can send monitoring, security and account lifecycle events.
monitor.downmonitor.recoveredmonitor.degradedmonitor.ssl_warningmonitor.ssl_criticalaccount.password_changedaccount.api_key_createdaccount.plan_expiringaccount.plan_expiredaccount.limit_warningnotification.testWebhook payload
{
"id": "evt_...",
"event": "monitor.down",
"created_at": "2026-07-11T10:00:00Z",
"severity": "critical",
"data": {
"monitor_id": 123,
"status": "down"
}
}
Headers and signature
X-NexIP-Event: monitor.down X-NexIP-Delivery: 456 X-NexIP-Timestamp: 1783754400 X-NexIP-Signature: sha256=...
Calculate HMAC-SHA256 over timestamp + "." + the exact raw request body. Reject timestamps older than five minutes, then compare signatures in constant time.
PHP verification
<?php
$timestamp = $_SERVER['HTTP_X_NEXIP_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_NEXIP_SIGNATURE'] ?? '';
$body = file_get_contents('php://input');
if (abs(time() - (int)$timestamp) > 300) {
http_response_code(401);
exit;
}
$expected = 'sha256=' . hash_hmac(
'sha256',
$timestamp . '.' . $body,
$secret
);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit;
}
http_response_code(204);
Node.js verification
const signed =
`${request.headers['x-nexip-timestamp']}.${rawBody}`;
const expected =
'sha256=' +
createHmac('sha256', secret)
.update(signed)
.digest('hex');
const valid = timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
Delivery policy
2xx
Delivery accepted after durable processing.
408 / 425
Temporary failure. NexIP retries delivery.
429 / 5xx
Retryable. Retry-After is respected for 429.
400–404
Not retried for permanent client errors.
Redirects are not followed. This helps prevent webhook delivery from being redirected into private networks.
Test event
notification.test
contains:
{
"test": true
}