# BugSnag error alert notifications on your phone

> Get a push notification for new, reopened, frequent or spiking errors in a BugSnag project.

- Company: BugSnag (https://www.justpush.io/recipes/bugsnag)
- Event: `firstException` (Error)
- Tags: Developer tools, Monitoring
- Install: https://studio.justpush.io/recipes/bugsnag/error-alert
- Web page: https://www.justpush.io/recipes/bugsnag/error-alert

## Setup

1. Click Install in Studio and sign in. The recipe is added to your account and you get a personal webhook URL.
2. In BugSnag, open your project's Settings > Integrations and data forwarding and choose Webhook.
3. Paste your webhook URL (shown in Studio after install) as the webhook URL.
4. Under notifications, pick the Error triggers you want and save. Use Test to send a sample.
5. On the webhook integration, choose which **notifications** to send. This recipe handles:
6. **New errors** (`firstException`): 🐛 New error
7. **Reopened errors** (`reopened`): 🔁 Error reopened
8. **Frequent errors** (`errorEventFrequency`): 📈 Frequent error
9. **Error milestones** (`powerTen`): 🔟 Error milestone
10. **Every exception** (`exception`): ⚠️ Error (noisy, so use with care)
11. **Project spikes** (`projectSpiking`): 📈 Error spike
12. Comments, releases and rate-limit notices are ignored; see the [rate limit](../rate-limit) recipe for the last one.
13. BugSnag doesn't sign webhook requests, so keep your endpoint URL private.

## Code

Studio calls `handleRequest(request)` with the incoming webhook (`{ method, headers, body, query, raw }`) and sends the message object it returns. Returning `null` sends nothing.

```js
// BugSnag → error notifications
// Fires for the error triggers you pick on BugSnag's webhook integration: new errors,
// reopened errors, frequent errors, milestones, every exception, and project spikes.
// Docs: https://docs.bugsnag.com/product/integrations/data-forwarding/webhook/

// Each trigger, its title, and how loud to be.
const TRIGGERS = {
    firstException: { title: "🐛 New error", priority: 1 },
    reopened: { title: "🔁 Error reopened", priority: 0 },
    errorEventFrequency: { title: "📈 Frequent error", priority: 1 },
    powerTen: { title: "🔟 Error milestone", priority: 0 },
    exception: { title: "⚠️ Error", priority: 0 },
    projectSpiking: { title: "📈 Error spike", priority: 1 },
}

// Only link to real http(s) URLs.
function link(url, cta) {
    return typeof url === "string" && /^https?:\/\//.test(url) ? [{ cta, url }] : []
}

function handleRequest(request) {
    const body = request.body || {}
    const type = body.trigger?.type

    // Guard: only error triggers; comments, releases and rate-limit notices are skipped.
    if (!Object.prototype.hasOwnProperty.call(TRIGGERS, type)) {
        console.log(`Ignoring BugSnag trigger "${type ?? "unknown"}"`)
        return null
    }

    const trigger = TRIGGERS[type]
    const project = body.project?.name
    const error = body.error

    // A project spike has no single error, just a rate.
    if (type === "projectSpiking" || !error) {
        return {
            title: `${trigger.title}${project ? ` in ${project}` : ""}`,
            message: body.trigger.message ?? (body.trigger.rate ? `${body.trigger.rate} events` : "Spike detected"),
            topic: "BugSnag",
            priority: trigger.priority,
            buttons: link(body.project?.url, "View project"),
        }
    }

    const what = [error.exceptionClass, error.message].filter(Boolean).join(": ") || "Unknown error"
    const stage = error.app?.releaseStage
    const where = [error.context, stage].filter(Boolean).join(" · ")
    // Milestones and frequency alerts explain themselves ("1000th exception").
    const why = ["powerTen", "errorEventFrequency"].includes(type) && body.trigger.message ? ` (${body.trigger.message})` : ""
    // Handled warnings and info reports are one step quieter than real errors.
    const quieter = error.severity === "info" ? 2 : error.severity === "warning" ? 1 : 0

    return {
        title: `${trigger.title}${project ? ` in ${project}` : ""}`,
        message: what + (where ? ` — ${where}` : "") + why,
        topic: "BugSnag",
        priority: Math.max(-1, trigger.priority - quieter),
        buttons: link(error.url, "View error"),
    }
}
```

## BugSnag firstException webhook payload (sample)

```json
{
  "error": {
    "id": "66f8e1c2a7b9e10001a1b2c3",
    "app": {
      "type": "rails",
      "version": "4.12.0",
      "releaseStage": "production"
    },
    "url": "https://app.bugsnag.com/acme/web-app/errors/66f8e1c2a7b9e10001a1b2c4?event_id=66f8e1c2a7b9e10001a1b2c3",
    "status": "open",
    "context": "checkout#create",
    "errorId": "66f8e1c2a7b9e10001a1b2c4",
    "message": "undefined method `total' for nil",
    "severity": "error",
    "unhandled": true,
    "receivedAt": "2026-09-29T08:06:11.000Z",
    "firstReceived": "2026-09-29T08:06:11.000Z",
    "exceptionClass": "NoMethodError"
  },
  "account": {
    "id": "56b9ca7f17025f8756f69054",
    "url": "https://app.bugsnag.com/accounts/acme",
    "name": "Acme"
  },
  "project": {
    "id": "56b9ca7f17025f8756f69055",
    "url": "https://app.bugsnag.com/acme/web-app",
    "name": "Web App"
  },
  "trigger": {
    "type": "firstException",
    "message": "New error in production"
  }
}
```

## FAQ

### 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 BugSnag 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.
