Guide to Front Webhooks: Features and Best Practices
Front webhooks notify your application about inbox activity: a message is received or sent, a conversation is moved, a tag is added, an assignee changes. If you're building an integration on Front, webhooks are how you react to conversation activity in real time.
This guide covers how Front's application webhooks work, the events you'll handle, how to verify the X-Front-Signature, the challenge handshake, and the best practices for production, plus how the legacy rule webhooks differ (so you don't conflate the two).
What are Front webhooks?
Front has two webhook systems. This guide covers application webhooks (the modern system used by partner and Core API apps), which sign deliveries with an X-Front-Signature keyed with your app's signing key. The older rule webhooks (a settings-based rule action) sign differently, covered at the end.
Application webhooks POST a JSON event to your endpoint, verify your endpoint with a challenge at subscription time, and retry a few times before auto-disabling.
Front webhook features
| Feature | Details |
|---|---|
| System | Application webhooks (modern); rule webhooks are legacy |
| Signature header | X-Front-Signature (base64 HMAC-SHA256) |
| Signed content | X-Front-Request-Timestamp + ":" + raw body |
| Signing key | App signing key |
| Handshake | X-Front-Challenge: echo the value within 10s |
| Retries | Up to 3x on 408/429/500/timeout, then auto-disables |
| Legacy rule webhooks | HMAC-SHA1 over the body only, keyed with the "API Secret", 5s timeout, no retries |
| SDK | No official server-side SDK (community only) |
Common events
Front application webhook events cover conversation and message activity:
| Event | Fires when |
|---|---|
inbound_received | An inbound message is received |
outbound_sent | An outbound message is sent |
conversation_moved | A conversation is moved (inbox/status change) |
message_delivery_failed | A message fails to deliver |
tag_added | A tag is added to a conversation |
assignee_changed | A conversation's assignee changes |
new_comment_added | A comment is added to a conversation |
Subscribe to the events you process, and consult Front's webhook reference for the full list.
Setting up Front webhooks
Create an application webhook subscription for your app. At subscription time Front sends a validation request with an X-Front-Challenge header; echo the challenge value back within 10 seconds as a 200 (as a text/plain body, a form challenge=<v>, or JSON {"challenge":"<v>"}). Copy your app's signing key into your environment for verifying deliveries.
Securing Front webhooks
Each delivery carries an X-Front-Signature (base64) and an X-Front-Request-Timestamp. To verify, build the message {timestamp}:{raw body}, compute a base64 HMAC-SHA256 with your app signing key, and compare in constant time. Always use the raw body.
const crypto = require("crypto");
const SIGNING_KEY = process.env.FRONT_APP_SIGNING_KEY;
function verify(rawBody, timestamp, signature) {
const message = `${timestamp}:${rawBody}`;
const expected = crypto
.createHmac("sha256", SIGNING_KEY)
.update(message)
.digest("base64");
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) => {
// Subscription handshake
const challenge = req.headers["x-front-challenge"];
if (challenge) return res.status(200).json({ challenge });
const timestamp = req.headers["x-front-request-timestamp"];
if (!verify(req.body.toString("utf8"), timestamp, req.headers["x-front-signature"])) {
return res.sendStatus(401);
}
res.sendStatus(200); // acknowledge fast
processQueue.add(JSON.parse(req.body)); // process asynchronously
});
The same check in Python:
import base64
import hashlib
import hmac
import os
SIGNING_KEY = os.environ["FRONT_APP_SIGNING_KEY"].encode()
def verify(raw_body: str, timestamp: str, signature: str) -> bool:
message = f"{timestamp}:{raw_body}".encode()
expected = base64.b64encode(hmac.new(SIGNING_KEY, message, hashlib.sha256).digest()).decode()
return hmac.compare_digest(expected, signature or "")
How legacy rule webhooks differ
Front's older rule webhooks (configured as a rule action, not an app) use a different scheme: base64 HMAC-SHA1 over the body only, keyed with the "API Secret" from the Webhooks app, a 5-second timeout, and no retries. Don't reuse the application-webhook verifier for these; the algorithm, the signed content, and the key source all differ.
Front webhook limitations and pain points
Two systems, two schemes
The Problem: Application webhooks use HMAC-SHA256 over timestamp:body keyed with the app signing key; rule webhooks use HMAC-SHA1 over the body keyed with the API Secret. Conflating them fails verification.
Why It Happens: Front has two generations of webhooks with different signing.
Workarounds:
- Know which system you're on. For apps, verify SHA256 over
timestamp:body; for rule webhooks, SHA1 over the body with the API Secret.
How Hookdeck Can Help: Hookdeck verifies each source with the correct scheme at the edge, so your application receives pre-verified events without branching on which Front system sent them.
The challenge handshake
The Problem: Application webhooks won't activate until you echo the X-Front-Challenge within 10 seconds, in one of the accepted formats.
Why It Happens: Front validates the endpoint before delivering events.
Workarounds:
- Detect
X-Front-Challengeand echo it fast (JSON{"challenge":"<v>"}works).
How Hookdeck Can Help: Hookdeck can complete the handshake and forward verified events to your endpoint, so activation isn't a manual step.
Limited retries then auto-disable
The Problem: Application webhooks retry up to 3 times (on 408/429/500/timeout) and then auto-disable. A short outage can drop events; a sustained one disables the subscription.
Why It Happens: Front's retry budget is small and it prunes failing subscriptions.
Workarounds:
- Acknowledge fast so transient issues don't burn the 3-attempt budget; monitor subscription status and re-enable.
How Hookdeck Can Help: Hookdeck accepts every delivery and retries to your downstream on a schedule you control, so Front's 3-attempt limit isn't your only safety net and a sustained outage doesn't disable the subscription.
Duplicates and raw-body handling
The Problem: Retries mean duplicates, and the signature is over timestamp:body, so re-serializing the body breaks verification.
Why It Happens: At-least-once delivery plus a timestamp-bound signature.
Workarounds:
- Verify against the raw body, and dedupe on the event/conversation ID.
How Hookdeck Can Help: Hookdeck deduplicates deliveries at the edge and verifies against the bytes as received. See our guide to webhook idempotency.
Best practices
Verify over timestamp:body with the app signing key
Build {timestamp}:{raw body}, base64 HMAC-SHA256 with the app signing key, and compare in constant time. Don't reuse this for legacy rule webhooks.
Echo the challenge fast
Detect X-Front-Challenge and return it within 10 seconds to activate the subscription.
Acknowledge fast, process asynchronously
Return 200 immediately and defer work to a queue so transient slowness doesn't burn the retry budget. See why to process webhooks asynchronously.
Dedupe and monitor status
Dedupe on the event/conversation ID, and watch for auto-disable after sustained failures.
Make Front webhooks production-ready
Hookdeck completes the challenge, verifies X-Front-Signature, deduplicates, and durably queues every conversation event
Conclusion
Front application webhooks verify with an X-Front-Signature (base64 HMAC-SHA256 over timestamp:body, keyed with the app signing key), activate via an X-Front-Challenge handshake, and auto-disable after 3 failed attempts. The trap to avoid is conflating them with the legacy rule webhooks, which use HMAC-SHA1 over the body with the API Secret.
Hookdeck completes the handshake, verifies the signature, deduplicates, and durably queues every event at the edge, so your app only ever processes verified, unique conversation events without disabling on a bad day.
Get started with Hookdeck for free and handle Front webhooks reliably in minutes.