Resend delivery problem notifications on your phone.

Get a High-priority push notification when Resend fails to send an email, and quieter ones when delivery is delayed or an email is suppressed.

How it works

Three steps to your first push

STEP 01

Install the recipe

One click in Studio gives you a personal webhook URL.

STEP 02

Paste your URL into Resend

Add it as a webhook for email.failed, email.delivery_delayed and email.suppressed.

STEP 03

Get a push on your phone

With the text, sound and buttons from the recipe.

Setup

How to set up the Resend email.failed, email.delivery_delayed and email.suppressed webhook

  1. Click Install in Studio and sign in. The recipe is added to your account and you get a personal webhook URL.
  2. In Resend, open Webhooks and click Add Webhook.
  3. Paste your webhook URL as the endpoint URL and select the email.failed, email.delivery_delayed and email.suppressed events.https://••••••••/•••••••• your personal URL, shown after install
  4. Save the webhook.
  5. When you add the webhook in Resend (**Webhooks → Add Webhook**), select any of:
  6. **email.failed**: Resend couldn't send the email at all, for example because you reached your daily quota, the API key or domain has a problem, or the recipient is invalid. High priority.
  7. **email.delivery_delayed**: the receiving server temporarily refused the email (full inbox, transient error). Resend keeps retrying. Normal priority; leave it unticked if you send a lot and it gets noisy.
  8. **email.suppressed**: Resend didn't send because the address is on a suppression list after an earlier bounce or complaint. Low priority.
  9. Resend signs every delivery with Svix headers (`svix-id`, `svix-timestamp`, `svix-signature`), but JustPush doesn't check that signature yet, so keep your endpoint URL private.
The code

What runs when the webhook arrives

Studio calls handleRequest(request) with the incoming webhook and sends the message it returns. It's yours after install; change anything.

transform.js
1// Resend → email.failed / email.delivery_delayed / email.suppressed
2// Fires when Resend can't send an email (quota, API key, domain problems), when delivery is
3// delayed by the receiving server, or when Resend suppresses an email to a blocked address.
4// Docs: https://resend.com/docs/webhooks/emails/failed
5
6// Each event, how to label it, and how loud to be.
7const EVENTS = {
8 "email.failed": { title: "❌ Email failed to send", priority: 1 }, // High: sending itself is broken
9 "email.delivery_delayed": { title: "⏳ Email delivery delayed", priority: 0 }, // Resend keeps retrying
10 "email.suppressed": { title: "🚫 Email suppressed", priority: -1 }, // expected: protects your reputation
11}
12
13// Suppression types worth spelling out.
14const SUPPRESSIONS = {
15 OnAccountSuppressionList: "address is on your suppression list",
16}
17
18// Look a key up without tripping over inherited names like "toString".
19function pick(table, key, fallback) {
20 return Object.prototype.hasOwnProperty.call(table, key) ? table[key] : fallback
21}
22
23// Only link to real http(s) URLs.
24function link(url, cta) {
25 return typeof url === "string" && /^https?:\/\//.test(url) ? [{ cta, url }] : []
26}
27
28// A trimmed string, or null.
29function text(value) {
30 return typeof value === "string" && value.trim() ? value.trim() : null
31}
32
34function recipients(to) {
35 const list = (Array.isArray(to) ? to : [to]).map(text).filter(Boolean)
36 if (!list.length) return null
37 return list[0] + (list.length > 1 ? ` +${list.length - 1} more` : "")
38}
39
40// "reached_daily_quota" → "reached daily quota"
41function humanise(value) {
42 const s = text(value)
43 return s ? s.replace(/_/g, " ") : null
44}
45
46function handleRequest(request) {
47 const body = request.body && typeof request.body === "object" ? request.body : {}
48 const data = body.data && typeof body.data === "object" ? body.data : null
49 const event = data ? pick(EVENTS, body.type, null) : null
50
51 // Guard: only delivery problems, so other Resend events on this integration stay quiet.
52 if (!event) {
53 console.log(`Ignoring Resend "${body.type ?? "unknown"}" event`)
54 return null
55 }
56
57 const subject = text(data.subject)
58 let reason = null
59 if (body.type === "email.failed") reason = humanise(data.failed?.reason)
60 if (body.type === "email.suppressed") {
61 reason = pick(SUPPRESSIONS, data.suppressed?.type, null) ?? "address is suppressed"
62 }
63
64 return {
65 title: event.title,
66 message: [recipients(data.to) ?? "A recipient", subject ? `"${subject}"` : null, reason]
67 .filter(Boolean)
68 .join(" · "),
69 topic: "Resend",
70 priority: event.priority,
71 // The dashboard URL pattern isn't in Resend's webhook docs; it's where the email opens in the app.
72 buttons: text(data.email_id)
73 ? link(`https://resend.com/emails/${encodeURIComponent(data.email_id)}`, "View email")
74 : [],
75 }
76}
Payload

The Resend email.failed webhook

This is what Resend sends to your URL for email.failed, email.delivery_delayed and email.suppressed. It is a sample, trimmed to the fields recipes use.

email.failed · sample.json
1{
2 "data": {
3 "to": [
5 ],
6 "from": "Acme <[email protected]>",
7 "tags": {
8 "category": "invoice"
9 },
10 "failed": {
11 "reason": "reached_daily_quota"
12 },
13 "subject": "Your invoice for September",
14 "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
15 "created_at": "2026-09-29T08:41:11.894Z",
16 "message_id": "<[email protected]>"
17 },
18 "type": "email.failed",
19 "created_at": "2026-09-29T08:41:12.126Z"
20}
FAQ

Resend delivery problem notifications: questions

Does this work on iPhone and Android?

Yes. Install the JustPush app from the App Store or Google Play and sign in. Every phone signed in to your account gets the notification.

Do I need to write code?

No. Install the recipe in Studio, paste your webhook URL into Resend and you are done. The code is there if you want to change the text, the sound or the buttons.

Can I change what the notification says?

Yes. After install the recipe's code is yours. Edit it in Studio and test it against the sample payload before you save.

What does it cost?

JustPush is free for 30 days. After that it's $19.99 a year, or $39.99 once. There is no extra charge for recipes.

Ready when you are

Resend on your phone in two minutes.

Install the recipe, paste one URL, done. Free for 30 days, no credit card required.