Guide to Faundit Webhooks: Features and Best Practices
Faundit webhooks notify your application when the status of a lost-and-found item or a return request changes. If you're building on Faundit, webhooks are how you react to status changes without polling.
This guide covers how Faundit webhooks work, the two events you'll handle, how to verify the X-Faundit-Signature-Next, and why to avoid the deprecated v0 header.
What are Faundit webhooks?
Faundit webhooks are HTTP POSTs delivered to a URL you configure. The current (v1) scheme signs each delivery with an X-Faundit-Signature-Next header: an HMAC-SHA256 (hex) over v1:<timestamp>:<body>, where <timestamp> is the X-Faundit-Timestamp header value and <body> is the raw, unparsed request body. A deprecated v0 scheme sends X-Faundit-Signature over v0:<timestamp> only, which doesn't cover the body, so prefer the -Next header. This is not Standard Webhooks.
Faundit webhook features
| Feature | Details |
|---|---|
| Configuration | Register your endpoint; request the signing secret from tech@faundit.com |
| Signature header | X-Faundit-Signature-Next (current), X-Faundit-Signature (deprecated v0) |
| Signature scheme | HMAC-SHA256 (hex) over v1:<timestamp>:<body>, keyed with the signing secret |
| Timestamp | Sent in X-Faundit-Timestamp |
| Events | item-status, request-status |
| SDK | None |
Common events
Faundit has exactly two event types. The granular statuses (delivered, finished, expired) are fields in the payload, not separate events.
| Event | Fires when |
|---|---|
item-status | An item's status changes |
request-status | A request's status changes |
Branch on the event type, then read the status field for the specifics.
Setting up Faundit webhooks
Register your endpoint with Faundit and request the signing secret from tech@faundit.com (it isn't self-service). If you're on API v2, note that Members / faundit_memberID were renamed to Locations / locationID, though legacy IDs are still accepted.
Securing Faundit webhooks
The current header is X-Faundit-Signature-Next. To verify, build v1:<timestamp>:<body> using the X-Faundit-Timestamp value and the raw body, compute an HMAC-SHA256 with your signing secret, hex-encode it, and compare. Use the raw body before JSON parsing.
const crypto = require("crypto");
const SECRET = process.env.FAUNDIT_WEBHOOK_SECRET;
function verify(rawBody, timestamp, signature) {
const message = `v1:${timestamp}:${rawBody.toString()}`;
const expected = crypto.createHmac("sha256", SECRET).update(message).digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(signature || "");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
const ok = verify(
req.body,
req.headers["x-faundit-timestamp"],
req.headers["x-faundit-signature-next"] // prefer -Next over the deprecated v0 header
);
if (!ok) return res.sendStatus(401);
res.sendStatus(200); // acknowledge fast
processQueue.add(JSON.parse(req.body)); // branch on event type, async
});
The same check in Python:
import hashlib
import hmac
import os
SECRET = os.environ["FAUNDIT_WEBHOOK_SECRET"].encode()
def verify(raw_body: bytes, timestamp: str, signature: str) -> bool:
message = (f"v1:{timestamp}:").encode() + raw_body
expected = hmac.new(SECRET, message, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature or "")
Faundit webhook limitations and pain points
The deprecated v0 header doesn't cover the body
The Problem: The old X-Faundit-Signature signs v0:<timestamp> only, with no body integrity. Verifying against it means an attacker can change the body without invalidating the signature.
Why It Happens: The v0 scheme predates body signing.
Workarounds:
- Use
X-Faundit-Signature-Next(thev1:<timestamp>:<body>scheme) and ignore v0.
How Hookdeck Can Help: Hookdeck verifies the current scheme at the edge, so your app isn't exposed to the weaker v0 signature.
The signed message is prefixed and colon-joined
The Problem: The HMAC is over v1:<timestamp>:<body>, not the body alone. Signing the body by itself, or forgetting the v1: prefix, fails.
Why It Happens: Faundit versions and timestamps the signed message.
Workarounds:
- Reconstruct the exact
v1:<timestamp>:<body>string from the raw body and theX-Faundit-Timestampheader.
How Hookdeck Can Help: Hookdeck reconstructs and verifies the signed message at the edge.
The secret isn't self-service
The Problem: You can't generate the signing secret yourself, you request it from Faundit, which slows setup.
Why It Happens: Faundit issues secrets manually.
Workarounds:
- Request the secret from tech@faundit.com early, and store it securely.
How Hookdeck Can Help: Hookdeck holds the secret and verifies centrally, so it lives in one place rather than across every service.
Only two events, with status in the payload
The Problem: There are only item-status and request-status. Code that expects granular events like delivered or expired never fires, because those are payload fields.
Why It Happens: Faundit models granularity as status fields, not event names.
Workarounds:
- Branch on the event type, then read the status field.
How Hookdeck Can Help: Hookdeck's filters can route on the status field inside the payload, giving you status-level routing.
Best practices
Verify over v1:<timestamp>:<body> with the signing secret
Reconstruct the prefixed, colon-joined message from the raw body and X-Faundit-Timestamp, HMAC-SHA256, hex, and compare against X-Faundit-Signature-Next in constant time.
Prefer the -Next header
Ignore the deprecated X-Faundit-Signature (v0) that omits the body.
Read the status field
Branch on item-status / request-status, then handle the granular status from the payload.
Return 200 and process asynchronously
Acknowledge quickly and defer work to a queue. See why to process webhooks asynchronously.
Make Faundit webhooks production-ready
Hookdeck verifies X-Faundit-Signature-Next, deduplicates, and durably queues every event
Conclusion
Faundit webhooks are verified with the current X-Faundit-Signature-Next header, an HMAC-SHA256 over v1:<timestamp>:<body> keyed with your signing secret, using the timestamp from X-Faundit-Timestamp. Avoid the deprecated v0 header that signs only the timestamp. Verify over the raw body, branch on the two event types, and read the granular status from the payload.
Hookdeck verifies the signature, deduplicates, and durably queues every event at the edge, so your app only ever processes verified, unique events.
Get started with Hookdeck for free and handle Faundit webhooks reliably in minutes.