Webhooks
When you create an inbox with a webhook_url (Bearer API key required), TempFoxMail POSTs
each delivered message to your endpoint and signs the request so you can verify authenticity.
Registering
curl -X POST https://api.tempfoxmail.com/v1/inboxes \
-H "Authorization: Bearer tfm_live_…" \
-H "content-type: application/json" \
-d '{ "domain": "example.com", "webhook_url": "https://your.app/hooks/linden" }'The webhook secret is returned once, in the create response. Store it securely — it is
never shown again. The target URL is validated against SSRF (private/metadata ranges are blocked,
https only, no redirects, no userinfo) both at registration and on every delivery.
Signature
Each delivery carries an X-TempFoxMail-Signature header of the form:
X-TempFoxMail-Signature: t=1735732800,v1=<hex hmac-sha256>The signature is HMAC-SHA256(secret, t + "." + rawBody). Compute it over the raw request body (before JSON parsing) and compare in constant time. Reject deliveries
whose timestamp is too old to prevent replay.
Verifying (Node.js)
import crypto from "node:crypto";
/** Express-style handler. Mount with a raw body parser so 'body' is a Buffer. */
export function verifyLindenWebhook(secret, rawBody, signatureHeader, toleranceS = 300) {
const parts = Object.fromEntries(
signatureHeader.split(",").map((kv) => kv.split("=")),
);
const t = Number(parts.t);
if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > toleranceS) {
return false; // stale or malformed timestamp
}
const expected = crypto
.createHmac("sha256", secret)
.update(t + "." + rawBody.toString("utf8"))
.digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(parts.v1 ?? "");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}Delivery & retries
Deliveries are retried with backoff on network errors and 5xx responses. The last failure is recorded
as a status plus a short machine reason — never your endpoint's response body. Respond 2xx quickly; do heavy work asynchronously.
Listing webhooks
Registered users can review their webhook-enabled inboxes in the account UI under Webhooks, or via GET /v1/account/webhooks.