Skip to main content

Notifications

Send an alert to your phone, chat, or inbox when Outpost updates containers, finds new images, or can't finish an update, and stay undisturbed when there's nothing to report.

Why Use This Feature?

  1. Delivers to 11 services, from ntfy and Telegram to email and plain webhooks, so alerts land in an app you already watch.
  2. Lets each destination pick its own events so failures can reach your phone while a team chat gets every update.
  3. Groups each check's results into one alert per event, listing every container involved, so a busy night doesn't flood you.
  4. Seals tokens, passwords, and webhook URLs with the encryption key so neither the dashboard nor the API shows them again.
  5. Stays silent when every container is current so the alerts you get are worth reading.

Add a Destination

Each destination is one place alerts go, such as an ntfy topic, a Telegram chat, or an email inbox.

Outpost Notifications page listing the Email, Homelab chat, and My phone destinations with their services, event counts, and last sends, where the last email failed to sign in
The Notifications page with three destinations
  1. Open Notifications, under Settings in the sidebar, and select Add notification. On a phone, Notifications is in the account menu.
  2. Choose a Service. Its fields appear below it, as described in Services.
  3. Enter a Name you'll recognize, like the device or chat it goes to, of up to 80 characters. Each destination needs its own name, and names that differ only in letter case count as the same.
  4. Fill in the service's fields.
  5. Under Events, check the events this destination should hear about. All five start checked, and at least one is needed.
  6. Select Add notification.
Add notification dialog with ntfy selected, the name Work laptop, a topic URL, an empty optional access token, and all five events checked
Adding an ntfy destination

The new destination appears under Destinations, newest first. It is recommended to select Send test next to it right away, as described in Send a Test.

info

The service can't be changed after the destination is added. To move alerts to another service, add a new destination and remove the old one.

Services

The dialog offers these services, in this order:

ServiceFieldsWhat to enter
ntfyTopic URL, Access token (optional)The full topic URL on ntfy.sh or your own server, such as https://ntfy.sh/my-alerts. The token is only for topics that need one.
Reverse Proxy for ntfyContext URL, Context token (optional)The https:// URL of the context, with its interpreter set to outpost. The token is only for contexts that need one.
TelegramBot token, Chat IDA bot token from @BotFather, such as 123456:ABC-DEF, and a user, group, or channel the bot can post to.
DiscordWebhook URLThe URL from the channel's Integrations settings, starting with https://discord.com/api/webhooks/.
SlackWebhook URLThe URL of an incoming webhook in your Slack app, starting with https://hooks.slack.com/.
GotifyServer URL, App tokenYour Gotify server's URL, and the token of an application you made in it.
PushoverUser key, App tokenYour user key, and the API token of an application you made in Pushover.
MatrixHomeserver URL, Room ID, Access tokenAn https:// homeserver, a room ID such as !room:example.com, and the Matrix access token of an account that's already in the room. Room aliases that start with # aren't accepted, because sending needs the room ID.
EmailSMTP server, Port, Security, Username (optional), Password (optional), From, ToAn SMTP server and the addresses to send from and to, as described in Email.
AppriseApprise URL, Service URLs (optional)The notify URL of your Apprise API server with its config key, such as http://apprise:8000/notify/alerts. Service URLs, separated by spaces, are only for a stateless server.
WebhookURL, Bearer token (optional)Any http:// or https:// endpoint that accepts a JSON POST, as described in Webhook Payload. The token is sent as Authorization: Bearer.

Secret Fields

These secret fields are sealed with the encryption key when you save, and the dashboard and the API never show them again:

  • Tokens and keys — The ntfy Access token, the Reverse Proxy for ntfy Context token, the Telegram Bot token, the Gotify and Pushover App token, the Pushover User key, the Matrix Access token, and the webhook Bearer token.
  • URLs that work like passwords — The Discord and Slack Webhook URL, the Apprise URL and Service URLs, and the webhook URL.
  • Passwords — The email Password.

Every other field, such as a topic URL, a chat ID, or an email address, is saved as entered and shown when you edit the destination.

Email

  • SMTP server and Port — The server Outpost hands each alert to. Port starts at 587.
  • Security — STARTTLS, the default, switches the connection to TLS and won't send without it. TLS uses TLS from the start, usually on port 465, and None sends without encryption.
  • Username and Password — Leave Username blank when the server doesn't need a login, and Outpost won't sign in.
  • From and To — The sender's address, and one or more recipients separated by commas.
Add notification dialog with Email selected, showing the SMTP server, Port, Security, Username, Password, From, and To fields filled in
The email fields

Each alert arrives as a plain-text email, with the alert's title, such as Outpost: Update failed, as the subject.

Choose Events

Each destination gets only the events checked under Events, so you can send failures to one place and everything to another:

EventKeySent when
Saved secrets were removedsecrets-removedOutpost started without its encryption key and removed the secrets the old key sealed. Only destinations that still work can get it.
Sign-in lockedsign-in-lockedTen failed sign-ins from one address within 15 minutes paused sign-in from it. Each address is reported at most once every 15 minutes.
Containers updatedupdates-appliedA check updated one or more containers.
New images availableupdates-availableA check found newer images for monitor-only containers. Every check sends it again until you apply the update.
Update failedupdate-failedAn update failed or was rolled back, or a whole check couldn't run, such as when Docker can't be reached.

Wrong codes, rejected passkeys, and wrong passwords on the Security page count toward the sign-in limit too, as described in Web Dashboard. Wrong setup codes have their own count and never send Sign-in locked.

When Alerts Are Sent

  • One alert per event — A check sends at most one alert for each event, listing every container it applies to. A check where every container is up to date or skipped sends nothing.
  • Every check — Scheduled checks, checks started from the dashboard or the API, and single-container checks all send alerts.
  • Titles — Services that show a title get the event's name after Outpost:, such as Outpost: Containers updated.
  • Priority — Update failed, Saved secrets were removed, and Sign-in locked are sent as high priority, and the others as default. ntfy gets 4 or 3, Gotify 8 or 5, Pushover 1 or 0, Apprise warning or info, and Discord a red or blue message.

The title and message of two typical alerts read like this:

Example alerts
text
Outpost: Containers updated
Updated 2 containers: web (ghcr.io/example/web:latest), worker (ghcr.io/example/worker:latest).

Outpost: Update failed
Couldn't update 1 container: api (ghcr.io/example/api:2) was rolled back: New container is unhealthy; rolled back to the previous container.

Send a Test

Select Send test next to a destination to check its settings without waiting for an update. It sends this message right away:

Test notification
text
Outpost: Test notification
This is a test from Outpost. Alerts for the events you chose will look like this.
  • A notification in the corner then says Test sent to and the destination's name, or The test to … couldn't be sent: followed by the reason, such as HTTP 401: unauthorized or No answer within 10 seconds.
  • The test counts as the destination's last send, so its status changes too.
  • Send test is unavailable while a destination waits for removed secrets, as described in Lost Encryption Key.
Destinations list where the My phone row shows last sent just now, with a Test sent to My phone. notification in the corner
A destination after Send test

Delivery Status

Each row under Destinations shows the destination's name, its service, how many events it gets, and how its last send went:

  • not sent yet — Nothing has been sent to it, not even a test.
  • last sent and a time — The service accepted the last alert or test.
  • Last attempt failed, a time, and a reason — The service refused the send or didn't answer. This shows in red on its own line, with the same reasons a failed test shows.

Alerts go out in the background, so a slow service never holds up a check or a sign-in. Each send has 10 seconds to finish.

A failed send never affects the check or sign-in that caused it, and Outpost doesn't retry it. The reason stays on the row until the next send works.

Edit a Destination

  1. Select Edit next to the destination.
  2. Change its Name, its fields, or its Events. The Service is fixed.
  3. Select Save.
Edit Email dialog with the service fixed to Email, the SMTP server, Port, Security, Username, From, and To fields filled in, and the Password field showing Saved with Remove saved value below it
Editing a destination with a saved secret
  • Saved secrets — Saved secret fields show Saved and stay empty, because Outpost never shows them again. Leave a saved secret blank to keep it, or type a new value to replace it.
  • Optional secrets — Select Remove saved value below an optional secret, such as an ntfy Access token, to delete it when you save, or Keep saved value to undo that. After a lost key, a removed optional secret offers Continue without this value instead, which resumes alerts without it, and Require this value undoes that.
  • When changes apply — The next alert uses the new settings.
Edit Email dialog after a lost key, where the empty Password field's hint says a lost key removed it and Continue without this value shows below it
Editing a destination after a lost key

Remove a Destination

Select Remove next to the destination, then Remove in the dialog that asks to confirm. Alerts stop going to it right away, and its name is free to use again.

Remove Email? dialog saying alerts stop going to this destination and that it can be added again later, with Cancel and Remove buttons
Confirming a removal

Lost Encryption Key

Outpost seals secret fields with the encryption key in keys/installation.key, inside the data directory. If it starts without that file, it makes a new key, and the secrets the old key sealed can't be opened anymore:

  • Secrets removed — Each destination's secret fields are removed, but the destination stays with its name, service, events, and other fields.
  • Alerts paused — A destination that lost a secret is skipped until you enter it again with Edit. Its row says what's missing, such as Enter the bot token again. Alerts are paused until you do.
  • Notice — The Saved secrets were removed notice at the top of the dashboard lists each one, such as Set up the Homelab chat notification again, which opens Notifications. Dismiss hides the notice, but the destination stays paused until its secrets are entered again.
  • Alert — Destinations without secret fields, such as an ntfy topic without a token, keep working and get the Saved secrets were removed alert if they chose it.
Notifications page under the Saved secrets were removed notice, which links to the authenticator app, the Email and Homelab chat notifications, and two registry sign-ins, where the paused Email and Homelab chat rows ask for their password and bot token again with Send test unavailable, and My phone isn't paused
Destinations paused after a lost key

See Backup and Recovery for everything a lost key removes, and for keeping the key with your backups.

Webhook Payload

The Webhook and Reverse Proxy for ntfy services get each alert as JSON in a POST, with Content-Type: application/json. When a token is set, it's sent as Authorization: Bearer too.

Webhook body
json
{
  "version": 1,
  "app": "outpost",
  "event": "update-failed",
  "title": "Update failed",
  "message": "Couldn't update 1 container: api (ghcr.io/example/api:2) was rolled back: New container is unhealthy; rolled back to the previous container.",
  "priority": 4,
  "tags": ["whale", "warning"],
  "occurredAt": "2026-10-26T04:01:12.503Z",
  "details": {
    "containers": [
      {
        "container": "api",
        "image": "ghcr.io/example/api:2",
        "status": "rolled-back",
        "detail": "New container is unhealthy; rolled back to the previous container"
      }
    ],
    "finishedAt": "2026-10-26T04:01:12.480Z"
  }
}
FieldDescription
versionThe payload format, 1.
appAlways outpost.
eventThe key from Choose Events, or test for Send test.
titleThe event's name, such as Update failed, without the Outpost: prefix.
messageThe same text the other services show.
priority4 for high-priority events, otherwise 3.
tagsntfy tag names, listed below.
occurredAtWhen the event happened, as an ISO 8601 time in UTC.
detailsData about the event, listed below.
eventtagsdetails
secrets-removedkey, warningitems, the list of secrets to enter again.
sign-in-lockedlockaddress, the address that reached the limit.
updates-appliedwhale, white_check_markcontainers, the results that were updated, and finishedAt.
updates-availablewhalecontainers, the results that were available, and finishedAt.
update-failedwhale, warningcontainers, the failed and rolled-back results, and finishedAt. A whole check that couldn't run sends error, startedAt, and finishedAt instead.
testbellAn empty object.

Each entry in containers has the container, image, status, and detail of one result, as the report records it.

API Routes

The Notifications page calls these routes. They work only for a browser that is signed in to the dashboard, so an access token gets 403 with the code session_required and can't read or change where alerts go.

MethodPathDescription
GET/api/v1/notificationsLists every destination, newest first.
GET/api/v1/notifications/eventsLists the events in the dialog's order, with defaultEnabled for the ones a new destination starts with.
POST/api/v1/notificationsAdds a destination and answers 201 with it.
PUT/api/v1/notifications/:notificationIdChanges a destination's name, fields, and events, and answers with it. clearSecrets lists optional secrets to clear, saved or removed by a lost key, each once and never with a new value for the same field.
DELETE/api/v1/notifications/:notificationIdRemoves a destination and answers 204.
POST/api/v1/notifications/:notificationId/testSends the test message and answers {"delivered":true}, or {"delivered":false} with a message.
  • CSRF — Changes need the sign-in's CSRF token in the X-CSRF-Token header, like every change the dashboard makes.
  • No secret values — Answers never include a secret value. secrets names the saved secret fields, and secretsMissing names the ones a lost key removed.
  • Errors — A taken name gets 409 with the code notification_exists, and an unknown ID gets 404 with notification_not_found. A body that breaks a rule gets 422 with invalid_request, and issues names each field, such as settings.url.

Request Body

POST /api/v1/notifications
json
{
  "service": "ntfy",
  "name": "My phone",
  "settings": {
    "url": "https://ntfy.sh/my-alerts",
    "token": "tk_..."
  },
  "events": ["update-failed", "sign-in-locked"]
}
  • service — A key from the table below. PUT can leave it out, since the service can't change.
  • name — 1 to 80 characters, unique without regard to letter case.
  • settings — The service's fields, each as a string, the email port included, where a blank optional field counts as unset. On PUT, a saved secret that is left out or blank keeps its value, while any other field that is left out is cleared.
  • clearSecrets — On PUT, the optional secrets to clear, such as ["token"]: saved ones, or ones a lost key removed, each listed once. A field can't be cleared and given a new value at once.
  • events — One or more event keys, each listed once.
Serviceservicesettings keys
ntfyntfyurl, token
Reverse Proxy for ntfyntfy-reverse-proxyurl, token
TelegramtelegrambotToken, chatId
DiscorddiscordwebhookUrl
SlackslackwebhookUrl
Gotifygotifyurl, token
PushoverpushoveruserKey, appToken
MatrixmatrixhomeserverUrl, roomId, accessToken
Emailemailhost, port, security (starttls, tls, or none), username, password, from, to
Appriseappriseurl, urls
Webhookwebhookurl, token

Response Body

A destination in a response
json
{
  "id": "ntf-1b3d5f7a9c0e2b48",
  "name": "My phone",
  "service": "ntfy",
  "settings": {
    "url": "https://ntfy.sh/my-alerts"
  },
  "secrets": {
    "token": true
  },
  "secretsMissing": [],
  "events": ["update-failed", "sign-in-locked"],
  "lastAttemptAt": null,
  "lastError": null,
  "createdAt": "2026-10-26T09:12:40.118Z",
  "updatedAt": "2026-10-26T09:12:40.118Z"
}

lastAttemptAt and lastError are what the row's status shows, with lastError set to null after a send that worked.