# Sentry alerts on your phone: push notifications for errors, no code

> Send Sentry issue and metric alerts to your iPhone or Android phone as push notifications. A Sentry internal integration, one Pocket Alert webhook, working templates for the real payloads, an "Open in Sentry" button and an honest take on levels.

*19.10.2026*

<!-- source: https://pocketalert.app/blog/sentry-alerts-to-phone -->

Sentry catches the exception the moment it happens. Then it emails you, or posts to a Slack channel that also gets deploy messages, standup reminders and a few hundred other things. If the error hits at 2 a.m. or while you're away from the laptop, you find out when a user does.

Sentry alerts can do better than that, but Sentry has no push app of its own for alerts. What it does have is a webhook that fires when an alert rule matches. Point it at Pocket Alert and every alert becomes a push notification on your phone, with the error title, the culprit and a button that opens the issue. No server, no code.

## What you need

- A Sentry organization where you're allowed to create integrations and alerts.
- A Pocket Alert account with the app on your iPhone or Android phone. The Free plan includes one webhook, which is all this setup needs.
- An API key from [API Keys](/account/apikeys) if you want the "Open in Sentry" button (more on that below).

## How Sentry sends alerts to a webhook

Sentry has two ways to POST an alert to a URL, and they send different JSON:

- **Internal integration** (recommended by Sentry). You create a private integration with a webhook URL and turn on its **Alert Action** toggle. It then appears as an action in your alerts. Issue alerts arrive with the `Sentry-Hook-Resource: event_alert` header and the error under `data.event`; alerts on issues from Metric Monitors arrive as `metric_alert` with a ready-made title in `data.description_title`.
- **Webhooks (Legacy)**. A per-project plugin under project settings. It still works, but the settings page itself says Sentry strongly recommends an internal integration instead. Its payload is flat: `project_name`, `culprit`, `level`, `url`, `triggering_rules` and the raw `event`.

This guide uses the internal integration and gives a template for the legacy webhook at the end.

## Step 1: Create the Pocket Alert webhook

Pocket Alert names every webhook push `Webhook <name>`, so call it **Sentry** and the title on your lock screen reads "Webhook Sentry". The body comes from a template that pulls fields out of Sentry's JSON with `%path%` placeholders.

The quickest way is one API call, because the action button template can only be set through the API. It creates the webhook with the message template, a default level and an "Open in Sentry" button, then prints the receive URL:

```bash
jq -n \
  --arg msg $'%data.event.title%%data.description_title%\n%data.event.culprit%%data.description_text%\nRule: %data.triggered_rule%' \
  --arg act '[{"type":"view","label":"Open in Sentry","value":"%data.event.web_url%%data.web_url%"}]' \
  '{name: "Sentry", message: $msg, default_level: 1, actions: $act}' |
curl -sS https://api.pocketalert.app/v1/webhooks \
  -H "Token: YOUR_API_KEY" \
  -H 'Content-Type: application/json' \
  --data-binary @- |
jq -r '"Receive URL: https://p4a.me/wh/" + .url'
```

The template looks odd on purpose. One Sentry integration has one webhook URL, and both issue alerts and metric alerts go to it. A placeholder whose path doesn't exist in the payload renders as an empty string, so `%data.event.title%%data.description_title%` shows the error title for an issue alert and the alert title for a metric alert. The same trick gives the button the right link in both cases. For an issue alert `Rule:` shows the alert's name; on a metric alert that line stays empty.

If you'd rather click, create the webhook in the console at [Webhooks](/webhooks): name **Sentry**, **Default priority** High, and paste the message template:

```text
%data.event.title%%data.description_title%
%data.event.culprit%%data.description_text%
Rule: %data.triggered_rule%
```

You get the same pushes, just without the button. Copy the receive URL the console shows (`https://p4a.me/wh/...`).

## Step 2: Create the internal integration in Sentry

1. In Sentry go to **Settings > Developer Settings**, create a new integration and choose **Internal Integration**.
2. Give it a name like "Pocket Alert".
3. Paste the receive URL into **Webhook URL**.
4. Turn on **Alert Action**. This toggle is what puts the integration into the alert builder.
5. Save. Internal integrations install themselves on your organization; there's no OAuth step.

Leave the other webhook subscriptions (issue, error, comment) unchecked. Pocket Alert turns every request it receives into a push, and those resources would arrive as pushes with mostly empty lines.

## Step 3: Send alerts to it

Sentry's current alert builder lives under **Monitors > Alerts > Create Alert**:

1. **Source**: the projects you care about, or specific monitors.
2. **Environment**: pick `production`, so staging noise stays off your phone.
3. **When**: "A new issue is created" is the classic choice. "An issue escalates" and "A resolved issue regresses" are worth adding.
4. **Then**: **Send a notification via an integration**, and select the "Pocket Alert" integration.
5. **Throttling**: set something like 30 minutes, so a hot issue doesn't send a push for every event.

Before saving, click **Send Test Notification** on the If/Then block. A push titled "Webhook Sentry" should land on your phone within a second or two.

## What lands on your phone

For an issue alert, Sentry's payload carries the error under `data.event`. These are the fields the template uses, from Sentry's documented `event_alert` payload:

<div class="cmp-table-wrap">
<table class="cmp-table">
<thead><tr><th>Field</th><th>Example</th><th>Used for</th></tr></thead>
<tbody>
<tr><th><code>data.event.title</code></th><td>ReferenceError: heck is not defined</td><td>First line of the push</td></tr>
<tr><th><code>data.event.culprit</code></th><td>where the error was thrown</td><td>Second line</td></tr>
<tr><th><code>data.triggered_rule</code></th><td>Very Important Alert!</td><td>Which alert fired</td></tr>
<tr><th><code>data.event.web_url</code></th><td>https://sentry.io/organizations/…/issues/…/events/…/</td><td>"Open in Sentry" button</td></tr>
<tr><th><code>data.event.level</code></th><td>error</td><td>Optional, see below</td></tr>
</tbody>
</table>
</div>

A metric alert has no `data.event`. Its `action` is `critical`, `warning` or `resolved`, and `data.description_title` already includes the state, for example "Resolved: Too many errors", with `data.description_text` underneath ("1000 events in the last 10 minutes"). The button uses `data.web_url`.

Want the Sentry level in the text? Add `Level: %data.event.level%` to the template. It is text only; the next section explains why it doesn't change how loudly the push arrives.

## Levels: what actually decides how loud the push is

Pocket Alert has five levels: silent, low, default, high and critical. For webhooks the level is chosen in this order: a top-level `level` field in the incoming JSON, then the webhook's default level, then the application's default.

Sentry doesn't map onto that by itself, and a template can't translate values:

- The internal integration payload has no top-level `level`. Sentry's level sits in `data.event.level`, so Pocket Alert uses the webhook's **default level**. That's why the webhook above is created with `default_level: 1` (high), which shows on iPhone as a time-sensitive notification that gets through Focus.
- The legacy webhook does send a top-level `level`, but with Sentry's values: `fatal`, `error`, `warning`, `info`, `debug`. None of them is a Pocket Alert level, so it's ignored and the default level applies. The alert is still delivered.

If a fatal error in production should wake you up while everything else stays at high, split it on the Sentry side. On a paid plan, create a second Pocket Alert webhook named "Sentry critical" with `default_level: 2`, and a second internal integration pointing at it. Then use two If/Then blocks in the same alert:

- Block 1: **If none** of: Event level equals `fatal`. **Then** notify the "Pocket Alert" integration.
- Block 2: **If all** of: Event level equals `fatal`. **Then** notify "Pocket Alert critical".

Critical alerts get through Do Not Disturb on both iOS and Android (see [priority levels](https://info.pocketalert.app/features/priority-levels)). They're a paid feature: on the Free plan, critical is delivered as high.

## The legacy webhook, if you already use it

Projects that have **Webhooks (Legacy)** enabled under **Project Settings > Legacy Integrations** can point it at the same kind of Pocket Alert webhook. The payload is different, so use this template:

```text
%project_name%: %event.title%
%culprit%
Rule: %triggering_rules.0%
```

And this button template for the API call above:

```json
[{ "type": "view", "label": "Open in Sentry", "value": "%url%" }]
```

Use `%event.title%` rather than the top-level `%message%`. In the legacy payload `message` is the event's log message, which is empty for an ordinary exception. The legacy plugin only sends when an alert has the action that notifies the project's legacy integrations, and its settings page has a **Send Test Event** button.

## Honest limits

- **One title for everything.** Pocket Alert titles webhook pushes `Webhook <name>`; the error goes in the body. If you need the error as the push title, put a small function between Sentry and the [messages API](https://info.pocketalert.app/api/messages/create).
- **No signature check.** Internal integrations sign requests with `Sentry-Hook-Signature`, and Pocket Alert doesn't verify it. The random receive URL is the secret, so don't post it publicly. If it leaks, delete the webhook and create a new one.
- **JSON only.** Both Sentry mechanisms send JSON, so this is fine here, but a form-encoded sender would be rejected.
- **Daily limits.** The Free plan delivers 50 messages a day. With throttling on and production-only alerts that's plenty; an alert on "every event captured" will burn through it.

## If nothing arrives

- **Open the webhook history.** Every request to your Pocket Alert webhook is logged with headers, body, the rendered message and the status. If the request is there, the problem is the template; if it isn't, Sentry never sent it.
- **Check the Alert Action toggle.** Without it the integration doesn't appear under **Send a notification via an integration**.
- **Check the alert's history.** The alert's details page in Sentry lists recent runs. Filters such as environment or event level often exclude the event you expected.
- **Empty lines in the push** mean a path doesn't match the payload. Compare it with the body in the webhook history; field names are case-sensitive.
- **No button** means the URL path came out empty, and an invalid button is dropped while the message is still delivered.

## FAQ

### Do I need to write any code?

No. Sentry sends the webhook and Pocket Alert turns it into a push. The only command in this guide is the optional API call that adds the "Open in Sentry" button.

### Can I separate production and staging?

Yes. Filter the alert by environment, or create one alert per environment pointing to different integrations and webhooks, each going to its own Pocket Alert application so you can mute staging on its own.

### Does this work with self-hosted Sentry?

The internal integration and alert action are part of Sentry itself, so a self-hosted install that's recent enough to have them can send to Pocket Alert the same way, as long as it can reach `p4a.me` over the internet.

### What about Rollbar, Bugsnag and other trackers?

The same approach works for any tracker that posts JSON to a URL; only the template paths change. See [error tracking alerts](/use-cases/error-tracking-alerts) for the bigger picture and the [webhook tool](/tools/webhook) and the [template syntax](https://info.pocketalert.app/api/webhooks/settings) for how templates work.

### Is it free?

Pocket Alert's Free plan covers one webhook, one device and 50 messages a day, which is enough for production error alerts on a small app.

[Create a free account](/signup), paste the URL into Sentry, and the next production error will reach you first.
