Set up ntfy

FreqTrade publishes messages to your ntfy server via webhooks. FreqDroid subscribes to the same topics and displays native OS notifications. Works on Android and iOS.

← Back to overview · Add the Python callback →

FreqTrade bot  →  POST  →  ntfy server  →  stream  →  FreqDroid  →  notification

Step 1 — Run an ntfy server

You can use the public ntfy.sh server for testing, but for production use with trading data a self-hosted instance is strongly recommended.

docker run -p 80:80 -v /var/cache/ntfy:/var/cache/ntfy binwiederhier/ntfy serve

docker-compose

services:
  ntfy:
    image: binwiederhier/ntfy
    command: serve
    ports:
      - "80:80"
    volumes:
      - ntfy-cache:/var/cache/ntfy
volumes:
  ntfy-cache:

Put this behind a reverse proxy (nginx, Caddy, Traefik) with TLS so the URL is https://ntfy.example.com. HTTPS is required for notifications to work reliably on Android 9+ and iOS.

See the ntfy self-hosting docs for full configuration options.

Step 2 — Note your topic names

FreqDroid derives a topic name for each bot automatically:

topic = "freqdroid-" + botName.lowercase()
                               .replace(' ', '-')
                               .filter { alphanumeric or '-' }
Bot name in appntfy topic
MyBotfreqdroid-mybot
Binance BTCfreqdroid-binance-btc
bot_1freqdroid-bot1

The Settings screen shows the computed topic as a hint.

Step 3 — Configure FreqTrade webhooks

In your FreqTrade config.json, add a webhook section that POSTs to your ntfy topic. Use "format": "raw" so FreqTrade sends plain text. See the full event list and template tokens on the overview page.

"webhook": {
    "enabled": true,
    "url": "https://ntfy.example.com/freqdroid-mybot",
    "format": "raw",
    "retries": 3,
    "retry_delay": 0.2,
    "allow_custom_messages": true,
    "entry": {
        "data": "Entry placed (#{trade_id})\n{direction} {pair} @ {open_rate:.6f} | stake {stake_amount:.2f} {stake_currency}"
    },
    "entry_fill": {
        "data": "Trade opened (#{trade_id})\n{pair} @ {open_rate:.6f} | stake {stake_amount:.2f} {stake_currency}"
    },
    "entry_cancel": {
        "data": "Entry cancelled (#{trade_id})\n{pair} entry order cancelled"
    },
    "exit": {
        "data": "Exit placed (#{trade_id})\n{pair} @ {limit:.6f}"
    },
    "exit_fill": {
        "data": "Trade closed (#{trade_id})\n{pair} | profit {profit_amount:.2f} {stake_currency} ({profit_ratio:.2%})"
    },
    "exit_cancel": {
        "data": "Exit cancelled (#{trade_id})\n{pair} exit order cancelled"
    },
    "protection_trigger": {
        "data": "Pair locked: {pair}\n{reason}\nLocked until {lock_end_time}"
    },
    "protection_trigger_global": {
        "data": "Protection triggered: {reason}\nAll pairs locked until {lock_end_time}"
    },
    "strategy_msg": {
        "data": "{msg}"
    },
    "status": {
        "data": "Status: {status}"
    },
    "startup": {
        "data": "{status}"
    },
    "warning": {
        "data": "Warning: {status}"
    },
    "exception": {
        "data": "Exception: {status}"
    }
}

If you wire up the Python callback, drop entry_fill and exit_fill from this block — the callback emits richer messages via dp.send_msg(), and keeping the built-in fills would give you double notifications.

Restart FreqTrade after editing config.json. Test with:

curl -d "Test message (#1)" https://ntfy.example.com/freqdroid-mybot

Step 4 — Enable notifications in FreqDroid

  1. Open the app, tap the hamburger menu, then SettingsNotification Server.
  2. At the top, choose the ntfy transport.
  3. Toggle Enable notifications on (in the parent Settings screen).
  4. Enter your ntfy server base URL (e.g. https://ntfy.example.com) — no trailing slash, no topic name.
  5. If your server requires Basic Auth, enter Username and Password.
  6. On Android 13+, grant the notification permission when prompted.
  7. Choose a delivery mode (see below) and tap Save.

Delivery modes (Android)

Delivery on iOS

iOS uses BGAppRefreshTask to poll ntfy in the background at the configured interval. iOS controls exact timing — the interval is a minimum, not a guarantee. The app also polls when it comes to the foreground.


Troubleshooting

No notifications arriving

Notifications stop after a while (Live mode)

The app maintains a long-lived HTTP streaming connection. If the server closes the connection, the app automatically reconnects with exponential back-off (2 s up to 60 s). No action needed.

ntfy requires authentication

Enter your credentials in the Username and Password fields below the server URL. The app sends a Basic auth header when both fields are non-empty. ntfy access tokens are not supported — use a dedicated ntfy user with a password.

Tapping a notification doesn’t open the trade

The notification text must contain #<trade_id> (e.g. (#123)). Make sure your webhook templates include #{trade_id} — see the example above.