Apprise API
You are an expert at deploying, configuring, and driving the Apprise API — a lightweight
container that exposes the Apprise notification library over HTTP.
Overview
- One gateway, 100+ services — a single
POST fans out to Discord, Slack, Telegram, ntfy, Gotify, email, SMS, Matrix, and more
- Two modes — stateless (URLs in the request) and stateful (URLs saved under a
{KEY})
- Universal URL syntax — every service is a URL:
discord://webhook_id/webhook_token
- Tag routing — group URLs by tag, then notify a subset with AND/OR tag expressions
- Attachments — multipart upload, remote HTTP URL, or a JSON
{url, filename} object
- Webhook payload mapping — remap third-party JSON fields into
title/body with ?:field=
- Ops-ready —
/status health check, /metrics for Prometheus, read-only rootless containers
Quick Start
docker run --name apprise -p 8000:8000 \
-v ./config:/config -v ./attach:/attach \
-e APPRISE_STATEFUL_MODE=simple -e APPRISE_ADMIN=y \
-d caronc/apprise:latest
# Stateless — URLs travel with the request
curl -X POST -d 'urls=discord://id/token' -d 'body=Deploy finished' \
http://localhost:8000/notify
# Stateful — save once under a key, then notify by key
curl -X POST -d 'urls=discord://id/token' -d 'urls=mailto://user:pass@gmail.com' \
http://localhost:8000/add/my-alerts
curl -X POST -d 'body=Deploy finished' http://localhost:8000/notify/my-alerts
Core Concepts
Stateless vs stateful. Stateless (/notify) keeps credentials in the caller and stores
nothing. Stateful (/add/{KEY} then /notify/{KEY}) keeps credentials on the server, so
callers only need a key. APPRISE_STATEFUL_MODE selects hash (default), simple, or
disabled; APPRISE_CONFIG_LOCK=yes freezes saved config for read-only production use.
Keys. 1–128 chars, alphanumeric plus _ and -. Treat a key as a secret on any shared
or internet-facing server. Default key is apprise (APPRISE_DEFAULT_CONFIG_ID).
Tags. TagA, TagB is OR; TagA TagB (or TagA+TagB) is AND; combine as
TagA TagC, TagB. Pass tag= on /notify/{KEY} to route to a subset of saved URLs.
Endpoints
| Path |
Method |
Purpose |
/status |
GET |
Health check — 200 healthy, 417 degraded |
/notify |
POST |
Stateless notify — urls, body, title, type, format, attach |
/add/{KEY} |
POST |
Save config — urls or config + format (text/yaml) |
/get/{KEY} |
POST |
Read config back (alias /cfg/{KEY}) |
/del/{KEY} |
POST |
Delete saved config |
/notify/{KEY} |
POST |
Notify a saved config — adds tag |
/json/urls/{KEY} |
GET |
List saved URLs and tags as JSON |
/details |
GET |
All supported service URLs (Accept: application/json) |
/metrics |
GET |
Prometheus metrics |
Documentation
API server
- Introduction — what the API is and when to use it
- Deployment — Docker, Compose, Kubernetes, hardening, reverse proxy
- API Usage — stateless and stateful request walkthroughs
- Endpoints — compact endpoint and payload reference
- Integrations — webhook payload mapping, third-party senders
- Environment Variables — every
APPRISE_* setting
- Response Codes — 200/204/400/405/424/431/500 meanings
- OpenAPI — Swagger spec and how to serve it
- Reference Index — reference-section map
- Upstream README — full caronc/apprise-api README
Notification URLs & config
- Universal URL Syntax — how Apprise URLs are structured
- Configuration — TEXT vs YAML config files and tagging
- Supported Services — service catalogue index
- apprise:// scheme — point the CLI/library at this API
- Tag Matching — AND/OR tag expression rules
- Attachments — file, URL, and JSON attachment forms
- Formatting — text, markdown, and HTML bodies
Getting started & CLI
- Getting Started — Apprise fundamentals
- Installation — installing Apprise itself
- Quick Start — first notification
- CLI / CLI Usage —
apprise command arguments
- CLI Persistent Storage — CLI-side state
Troubleshooting
- Q&A Index — troubleshooting map
- Error Lookup — diagnosing failed notifications
- Special Characters — escaping credentials in URLs
- Data Overflow — message truncation and splitting
- Formatting Issues — body renders wrong
- Resource Usage — memory/worker tuning
- PyInstaller — bundling Apprise into a binary
Guides
- Guides Index · Home Assistant · Fail2Ban
Common Workflows
Stand up a hardened stack — read docs/deployment.md, mount /config, /attach,
/plugin, set APPRISE_STATEFUL_MODE, APPRISE_WORKER_COUNT, and TZ, then verify with
curl -f http://host:8000/status.
Lock down a production server — set APPRISE_CONFIG_LOCK=yes and APPRISE_API_ONLY=yes,
restrict plugins with APPRISE_ALLOW_SERVICES / APPRISE_DENY_SERVICES, and put basic auth
or mTLS on a reverse proxy in front (see docs/deployment.md).
Accept a third-party webhook — map the sender's fields onto Apprise's with the : prefix:
POST /notify/{KEY}?:subject=title&:payload=body. Dot and bracket notation reach nested
values (?:event.title=title). See docs/integrations.md.
Debug a failing notification — check the response code against docs/response-codes.md
(424 means partial failure), then docs/error-lookup.md, and confirm URL escaping in
docs/special-characters.md.
Upstream Sources
Sync & Update
When user runs sync: run .github/workflows/scripts/sync-skill.sh skills/apprise-api to
refetch every source in sync.json into docs/.
When user runs diff: run the same script with --dry-run to report upstream drift without
writing.
1---2name: apprise-api3description: Expert at the Apprise API (caronc/apprise-api) — the self-hosted, containerized notification gateway that fans one HTTP request out to 100+ services (Discord, Slack, Telegram, ntfy, Gotify, email, SMS, Matrix, Pushover). Use when deploying the caronc/apprise container, writing docker-compose or Kubernetes manifests for it, saving stateful configuration keys, building Apprise notification URLs, tagging and routing notifications, sending attachments, mapping third-party webhook payloads, or tuning APPRISE_* environment variables. Triggers on mentions of apprise, apprise-api, appriseit, caronc/apprise, notification gateway, /notify endpoint, apprise:// URLs.4---56# Apprise API78You are an expert at deploying, configuring, and driving the **Apprise API** — a lightweight9container that exposes the Apprise notification library over HTTP.1011## Overview1213- **One gateway, 100+ services** — a single `POST` fans out to Discord, Slack, Telegram, ntfy, Gotify, email, SMS, Matrix, and more14- **Two modes** — *stateless* (URLs in the request) and *stateful* (URLs saved under a `{KEY}`)15- **Universal URL syntax** — every service is a URL: `discord://webhook_id/webhook_token`16- **Tag routing** — group URLs by tag, then notify a subset with AND/OR tag expressions17- **Attachments** — multipart upload, remote HTTP URL, or a JSON `{url, filename}` object18- **Webhook payload mapping** — remap third-party JSON fields into `title`/`body` with `?:field=`19- **Ops-ready** — `/status` health check, `/metrics` for Prometheus, read-only rootless containers2021## Quick Start2223```bash24docker run --name apprise -p 8000:8000 \25 -v ./config:/config -v ./attach:/attach \26 -e APPRISE_STATEFUL_MODE=simple -e APPRISE_ADMIN=y \27 -d caronc/apprise:latest2829# Stateless — URLs travel with the request30curl -X POST -d 'urls=discord://id/token' -d 'body=Deploy finished' \31 http://localhost:8000/notify3233# Stateful — save once under a key, then notify by key34curl -X POST -d 'urls=discord://id/token' -d 'urls=mailto://user:pass@gmail.com' \35 http://localhost:8000/add/my-alerts36curl -X POST -d 'body=Deploy finished' http://localhost:8000/notify/my-alerts37```3839## Core Concepts4041**Stateless vs stateful.** Stateless (`/notify`) keeps credentials in the caller and stores42nothing. Stateful (`/add/{KEY}` then `/notify/{KEY}`) keeps credentials on the server, so43callers only need a key. `APPRISE_STATEFUL_MODE` selects `hash` (default), `simple`, or44`disabled`; `APPRISE_CONFIG_LOCK=yes` freezes saved config for read-only production use.4546**Keys.** 1–128 chars, alphanumeric plus `_` and `-`. Treat a key as a secret on any shared47or internet-facing server. Default key is `apprise` (`APPRISE_DEFAULT_CONFIG_ID`).4849**Tags.** `TagA, TagB` is OR; `TagA TagB` (or `TagA+TagB`) is AND; combine as50`TagA TagC, TagB`. Pass `tag=` on `/notify/{KEY}` to route to a subset of saved URLs.5152## Endpoints5354| Path | Method | Purpose |55| --- | --- | --- |56| `/status` | GET | Health check — `200` healthy, `417` degraded |57| `/notify` | POST | Stateless notify — `urls`, `body`, `title`, `type`, `format`, `attach` |58| `/add/{KEY}` | POST | Save config — `urls` or `config` + `format` (text/yaml) |59| `/get/{KEY}` | POST | Read config back (alias `/cfg/{KEY}`) |60| `/del/{KEY}` | POST | Delete saved config |61| `/notify/{KEY}` | POST | Notify a saved config — adds `tag` |62| `/json/urls/{KEY}` | GET | List saved URLs and tags as JSON |63| `/details` | GET | All supported service URLs (`Accept: application/json`) |64| `/metrics` | GET | Prometheus metrics |6566## Documentation6768**API server**69- **[Introduction](docs/api-introduction.md)** — what the API is and when to use it70- **[Deployment](docs/deployment.md)** — Docker, Compose, Kubernetes, hardening, reverse proxy71- **[API Usage](docs/usage.md)** — stateless and stateful request walkthroughs72- **[Endpoints](docs/endpoints.md)** — compact endpoint and payload reference73- **[Integrations](docs/integrations.md)** — webhook payload mapping, third-party senders74- **[Environment Variables](docs/environment-variables.md)** — every `APPRISE_*` setting75- **[Response Codes](docs/response-codes.md)** — 200/204/400/405/424/431/500 meanings76- **[OpenAPI](docs/openapi.md)** — Swagger spec and how to serve it77- **[Reference Index](docs/reference-index.md)** — reference-section map78- **[Upstream README](docs/readme-upstream.md)** — full caronc/apprise-api README7980**Notification URLs & config**81- **[Universal URL Syntax](docs/universal-syntax.md)** — how Apprise URLs are structured82- **[Configuration](docs/configuration.md)** — TEXT vs YAML config files and tagging83- **[Supported Services](docs/services.md)** — service catalogue index84- **[apprise:// scheme](docs/apprise-url-scheme.md)** — point the CLI/library at this API85- **[Tag Matching](docs/tag-matching.md)** — AND/OR tag expression rules86- **[Attachments](docs/attachments.md)** — file, URL, and JSON attachment forms87- **[Formatting](docs/formatting.md)** — text, markdown, and HTML bodies8889**Getting started & CLI**90- **[Getting Started](docs/getting-started.md)** — Apprise fundamentals91- **[Installation](docs/getting-started-installation.md)** — installing Apprise itself92- **[Quick Start](docs/getting-started-quick-start.md)** — first notification93- **[CLI](docs/cli.md)** / **[CLI Usage](docs/cli-usage.md)** — `apprise` command arguments94- **[CLI Persistent Storage](docs/cli-persistent-storage.md)** — CLI-side state9596**Troubleshooting**97- **[Q&A Index](docs/qa.md)** — troubleshooting map98- **[Error Lookup](docs/error-lookup.md)** — diagnosing failed notifications99- **[Special Characters](docs/special-characters.md)** — escaping credentials in URLs100- **[Data Overflow](docs/data-overflow.md)** — message truncation and splitting101- **[Formatting Issues](docs/qa-formatting-issues.md)** — body renders wrong102- **[Resource Usage](docs/qa-resource-usage.md)** — memory/worker tuning103- **[PyInstaller](docs/qa-pyinstaller.md)** — bundling Apprise into a binary104105**Guides**106- **[Guides Index](docs/guides.md)** · **[Home Assistant](docs/guide-home-assistant.md)** · **[Fail2Ban](docs/guide-fail2ban.md)**107108## Common Workflows109110**Stand up a hardened stack** — read `docs/deployment.md`, mount `/config`, `/attach`,111`/plugin`, set `APPRISE_STATEFUL_MODE`, `APPRISE_WORKER_COUNT`, and `TZ`, then verify with112`curl -f http://host:8000/status`.113114**Lock down a production server** — set `APPRISE_CONFIG_LOCK=yes` and `APPRISE_API_ONLY=yes`,115restrict plugins with `APPRISE_ALLOW_SERVICES` / `APPRISE_DENY_SERVICES`, and put basic auth116or mTLS on a reverse proxy in front (see `docs/deployment.md`).117118**Accept a third-party webhook** — map the sender's fields onto Apprise's with the `:` prefix:119`POST /notify/{KEY}?:subject=title&:payload=body`. Dot and bracket notation reach nested120values (`?:event.title=title`). See `docs/integrations.md`.121122**Debug a failing notification** — check the response code against `docs/response-codes.md`123(`424` means partial failure), then `docs/error-lookup.md`, and confirm URL escaping in124`docs/special-characters.md`.125126## Upstream Sources127128- **Repository**: https://github.com/caronc/apprise-api129- **Documentation**: https://appriseit.com/api/130- **Docs source**: https://github.com/caronc/apprise-docs (`locales/en/`)131- **Core library**: https://github.com/caronc/apprise132133## Sync & Update134135When user runs `sync`: run `.github/workflows/scripts/sync-skill.sh skills/apprise-api` to136refetch every source in `sync.json` into `docs/`.137When user runs `diff`: run the same script with `--dry-run` to report upstream drift without138writing.