Webhook Signing
Verify that incoming requests to your endpoints are genuinely from Fliq using HMAC-SHA256 signatures.
Signature verification is optional but strongly recommended for production workloads. Without it, anyone who discovers your endpoint URL can send forged requests.
How it works
Every outgoing request from Fliq — both job executions and webhook notifications — includes two signature headers:
X-Fliq-Timestamp: 1774076020
X-Fliq-Signature: v1=661165d836a1ea...X-Fliq-Timestamp— Unix timestamp (seconds) when the request was signed. Use this to reject stale requests (replay protection).X-Fliq-Signature— HMAC-SHA256 signature prefixed withv1=. The version prefix allows future algorithm upgrades without breaking existing integrations.
Getting your signing secret
Go to Dashboard → Settings → Webhook Signing to view your signing secret. It starts with whsec_. You can rotate it at any time — rotation takes effect immediately.
After rotation, in-flight jobs may temporarily use the previous secret. They will be retried automatically with the new secret.
Signature scheme
The signed payload is a dot-separated string of four fields:
signed payload
{timestamp}.{METHOD}.{url}.{body}timestamp— exact value of theX-Fliq-TimestampheaderMETHOD— uppercase HTTP method (e.g.POST)url— full URL of the request, as configured in the jobbody— raw request body, or empty string if none
The HMAC is computed using SHA-256 with your signing secret as the key, then hex-encoded and prefixed with v1=.
Verification examples
Copy the verification function for your language and call it in your request handler before processing the payload.
import hmac, hashlib, time
def verify_fliq_signature(secret, timestamp, method, url, body, signature):
# Reject requests older than 5 minutes
if abs(time.time() - int(timestamp)) > 300:
raise ValueError("Timestamp too old — possible replay attack")
payload = f"{timestamp}.{method}.{url}.{body or ''}"
expected = "v1=" + hmac.new(
secret.encode(), payload.encode(), hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, signature):
raise ValueError("Invalid signature")
# Usage in your request handler:
# verify_fliq_signature(
# secret="whsec_...",
# timestamp=request.headers["X-Fliq-Timestamp"],
# method=request.method,
# url=request.url,
# body=request.get_data(as_text=True),
# signature=request.headers["X-Fliq-Signature"],
# )Best practices
- Always check the timestamp. Reject requests where
X-Fliq-Timestampis more than 5 minutes old to prevent replay attacks. - Use constant-time comparison. Use
hmac.compare_digest(Python),crypto.timingSafeEqual(Node.js), orhmac.Equal(Go) to prevent timing attacks. - Store the secret securely. Use environment variables or a secrets manager — never hardcode it in your source code.
- Rotate periodically. You can rotate your signing secret at any time from the dashboard. In-flight jobs will self-heal via automatic retries.