FoxReload Webhooks Integration β HMAC-SHA256, Retries, Idempotency
Polling GET /v1/orders/{id} every few seconds wastes quota and adds latency. FoxReload webhooks push order-status transitions to your endpoint within ~200 ms of the event firing in our fulfilment engine. This guide is for engineers who need a battle-tested webhook integration β signature verification, retry semantics, and idempotency.
1. Register your endpoint
In Settings β Webhooks, register an HTTPS endpoint (HTTP is rejected). You will receive a unique webhook_secret per endpoint β a 64-byte random value used to sign payloads. Subscribe to specific event types to avoid noise:
order.reservedorder.processingorder.deliveredorder.failedbalance.low
You can register up to 10 endpoints per account (e.g. one for production, one for staging, one for internal Slack alerts).
2. Verify the HMAC-SHA256 signature
Every webhook arrives with a X-FoxReload-Signature header of the form t=1715990400,v1=5257a8.... Compute HMAC-SHA256 over the string {timestamp}.{raw_body} using your webhook_secret and compare in constant time.
import hmac, hashlib, time
def verify(raw_body: bytes, header: str, secret: str) -> bool:
parts = dict(p.split("=") for p in header.split(","))
ts, sig = parts["t"], parts["v1"]
if abs(time.time() - int(ts)) > 300: # reject if older than 5 min
return False
signed = f"{ts}.{raw_body.decode()}".encode()
expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, sig)
Reject any request that fails verification with HTTP 401. The 5-minute timestamp window blocks replay attacks.
3. Retry logic and idempotency
FoxReload retries failed deliveries (any non-2xx response or timeout >10 s) on this schedule: 30 s, 2 min, 10 min, 1 h, 6 h, 24 h β up to 6 attempts. After the final attempt the event is moved to your Dead Letter Queue, visible in the dashboard for 30 days.
Every delivery includes X-FoxReload-Event-Id (UUID). Store this ID with a unique constraint in your database and ignore duplicates. Network blips routinely cause our retry layer to deliver the same event twice β your handler must be safe to call N times.
4. Acknowledge fast, process async
Respond HTTP 200 within 5 seconds. If your downstream processing (DB writes, email, reconciliation) takes longer, enqueue the payload onto SQS/Kafka and acknowledge immediately. Slow handlers cause cascading retries, duplicate events, and rate-limit warnings on your endpoint.
If your endpoint is down for >24 hours, FoxReload auto-pauses deliveries and sends an email alert β you can replay missed events from the dashboard once you redeploy.
Want a working reference implementation? FoxReload publishes open-source webhook handler examples in Node.js, Python, and Go, plus a hosted webhook tester β register at foxreload.com and skip the typical week of debugging signature verification edge cases.
