Briefing reply setup (Resend Inbound)
Users can reply to the morning briefing email — "done 1 and 3, push the rest to tomorrow, and have Jordyn draft the reply for the Banner email" — and Jordyn acts on it. All the code ships enabled-but-dormant: nothing changes until the two environment variables below are set. This page is the exact switch-on procedure.
How it works (30 seconds)
- When
BRIEFING_REPLY_DOMAINis set, each briefing's Reply-To becomes a per-user address likebriefing+<userId>.<hmac>@reply.jordyn.app. The HMAC token identifies the user; the From header is never trusted on its own. - Resend Inbound receives mail for that domain and POSTs the parsed email (svix-signed) to the webhook.
- The webhook verifies the signature, strips the quoted original, interprets the reply against that user's current briefing items, executes only done/snooze (through the same code path as the email's one-tap links), and emails back a confirmation. Free-text asks ("draft the reply") are never executed from email — they become a to-do plus a one-tap "have Jordyn do it now" link in the confirmation.
- Inbound is rate-limited to 20 replies per user per day.
Setup steps
-
Resend dashboard: add the inbound domain. Resend dashboard, then Inbound (under Receiving), then Add domain. Use a dedicated subdomain:
reply.jordyn.app. Do not use the sending domain itself — its MX records are already spoken for. -
Add the MX record at the DNS provider. The Resend dashboard shows the exact record after you add the domain. It is an MX record on
reply.jordyn.apppointing at Resend's inbound host (currently shown in the dashboard as aninbound.resend.com-style host, priority 10). Copy the host and priority from the dashboard rather than from this page, and wait for the domain to show Verified. -
Add the webhook. Resend dashboard, then Webhooks, then Add webhook.
- URL:
https://jordyn.app/api/inbound/briefing - Event: the inbound "email received" event.
Copy the webhook signing secret (starts with
whsec_) — it is shown when the webhook is created.
- URL:
-
Set the environment variables in Vercel (Project, then Settings, then Environment Variables, Production):
BRIEFING_REPLY_DOMAIN=reply.jordyn.appRESEND_INBOUND_SECRET= thewhsec_...signing secret from step 3. Redeploy so the new variables take effect.
-
Verify.
- Trigger a briefing (or wait for the morning cron) and confirm the email's Reply-To is
briefing+...@reply.jordyn.appand the footer shows the "just reply to this email" hint. - Reply "done 1" from the account's own inbox. Within a minute a confirmation email ("Got it — your briefing reply, handled") should arrive and the item should be done on the Today page.
- A request to
https://jordyn.app/api/inbound/briefingwithout the env vars set answers 503; with them set but without a valid svix signature it answers 401. Both are correct.
- Trigger a briefing (or wait for the morning cron) and confirm the email's Reply-To is
Rollback
Remove BRIEFING_REPLY_DOMAIN (or both variables) and redeploy. Briefings immediately revert to the old Reply-To (support@jordyn.app), the hint line disappears, and the webhook answers 503. No data changes are needed.
Notes and limits
- The reply interpreter only ever marks items done or moves to-dos to tomorrow — the same two operations as the email's one-tap links, executed through the same function. It cannot delete, send, or edit anything.
- If the From address doesn't match the account's profile email, the reply is still processed (people reply from aliases) but a warning is logged. The security boundary is the HMAC token in the To address plus the svix webhook signature, not the From header.
- Replies that can't be matched to a current briefing item are answered honestly ("Couldn't match") and change nothing.