Uptime Basics sends versioned JSON events to a public HTTPS endpoint. Verify the raw body before processing it, respond quickly, and move slow work to your own queue.
The Uptime-Basics-Signature header uses this form:
Signature header
t=1785600000,v1=HEX_DIGEST
Build the signed message from the timestamp, a period, and the exact raw request body. Calculate HMAC-SHA256 with your endpoint secret. Reject old timestamps and compare against every supplied v1 value in constant time.
import hashlib
import hmac
import time
def verify_webhook(raw_body: bytes, header: str, secret: str, tolerance=300):
values = [part.split("=", 1) for part in header.split(",") if "=" in part]
timestamp = next((value for key, value in values if key == "t"), None)
signatures = [value for key, value in values if key == "v1"]
if timestamp is None or abs(time.time() - int(timestamp)) > tolerance:
return False
signed = timestamp.encode() + b"." + raw_body
expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
return any(hmac.compare_digest(expected, signature) for signature in signatures)
Framework body parsers can change whitespace or encoding. Capture the raw request bytes before parsing JSON.
Secret rotation without downtime
Rotate from Account > Integrations. The new secret is shown once and the previous secret remains valid for 24 hours. During this grace period the signature header contains two v1 values.
Store the new secret alongside the existing secret.
Accept a valid signature from either secret.
Deploy the updated receiver.
Remove the previous secret after the grace period.
Rotating again replaces the previous grace-period secret. Do not repeatedly rotate while a rollout is still in progress.
Retries, redelivery, and endpoint health
A 2xx response marks a delivery successful. Timeouts, transport failures, and non-2xx responses can retry up to five attempts with delays of 60, 300, 900, and 900 seconds.
Return a 2xx response as soon as the event is authenticated and durably queued.
Do not rely on events arriving exactly once or strictly in order.
Deduplicate using eventId.
Use deliveryId when troubleshooting one attempt.
Manual redelivery creates a new delivery ID while preserving the original event ID.
An endpoint receives a warning after 7 consecutive failures and is automatically suspended after 10. Correct the destination and reactivate it from Account > Integrations.