Gareth Wilson Gareth Wilson

Guide to Faundit Webhooks: Features and Best Practices

Published


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

FeatureDetails
ConfigurationRegister your endpoint; request the signing secret from tech@faundit.com
Signature headerX-Faundit-Signature-Next (current), X-Faundit-Signature (deprecated v0)
Signature schemeHMAC-SHA256 (hex) over v1:<timestamp>:<body>, keyed with the signing secret
TimestampSent in X-Faundit-Timestamp
Eventsitem-status, request-status
SDKNone

Common events

Faundit has exactly two event types. The granular statuses (delivered, finished, expired) are fields in the payload, not separate events.

EventFires when
item-statusAn item's status changes
request-statusA 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 (the v1:<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 the X-Faundit-Timestamp header.

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.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.