Skip to content

Notification channels

Add an email, bot or webhook channel so Calends has somewhere to send automatic reminders.

The same reminder goes to every enabled channel. Under Settings → Notification channels, click Add channel, pick a type, fill in the fields and save. Each channel has its own name and Enabled toggle; its Test button sends a test message to that channel only, and works before you’ve saved.

Channel URLs and tokens are stored on the server and available to the signed-in app, but never sent to the public page. Full backups include them.

A ledger that has never set up channels but has a “notification email” from older versions uses that address as its only email channel.

  1. Under Settings → Notification channels, click Add channel.
  2. Choose a type, complete its fields below and click Test. This sends a real message.
  3. Save after a successful test and leave the channel enabled.
Field Details
Email address Where to send.

Email goes through Cloudflare Email Sending, which needs the EMAIL binding and a MAIL_FROM sender address at deploy time, on a domain verified in Cloudflare. If the server isn’t set up for it, sending fails with an error saying email isn’t configured; use another channel instead. Setup is in Cloudflare Workers + D1.

Docker deployments can’t send email.

Field Details
Bot Token Create a bot with @BotFather to get a token like 123456:ABC….
Chat ID Your user ID or a group ID. Send your bot a message first, then use @userinfobot to find your ID.

Messages use Telegram’s HTML formatting, up to 4000 characters.

Field Details
Webhook URL Group settings → Bots → Add custom bot; copy the https://open.feishu.cn/open-apis/bot/v2/hook/… address.
Signing secret Optional. Required if the bot has signature verification on.

Sent as a message card with a button that opens the app.

Field Details
Webhook URL Group settings → Bots → Custom bot; copy the https://oapi.dingtalk.com/robot/send?access_token=… address.
Signing secret Optional. Required if the bot’s security setting uses signing; starts with SEC.

If the bot’s security setting uses custom keywords instead, choose a word that always appears in reminders.

Field Details
Webhook URL Group chat → Add group bot; copy the https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=… address.

Sent as a Markdown message, up to 4000 characters.

Field Details
Device Key Install Bark on your iPhone and copy the key from the app.
Server Optional, for a self-hosted Bark server; https://api.day.app by default.
Field Details
Topic Pick a name that’s hard to guess, and subscribe to the same topic in the ntfy app.
Server Optional; https://ntfy.sh by default.
Access token Optional, for self-hosted or protected servers; sent as Authorization: Bearer.
Field Details
SendKey SCT… for ServerChan Turbo, or sctp… for ServerChan³. Calends picks the right endpoint from the prefix.

Pushes to WeChat.

Field Details
Webhook URL Channel settings → Integrations → Webhooks; copy the https://discord.com/api/webhooks/… address.

Sent as an embed.

Field Details
Webhook URL Turn on Incoming Webhooks in a Slack app and copy the https://hooks.slack.com/services/… address.
Field Details
URL Where reminders are sent.
Extra header Optional, a single header as Name: value, e.g. Authorization: Bearer ….

Calends sends a POST with JSON:

{
"subject": "Subscription reminder: …",
"intro": "You're spending … a month on subscriptions, with N active.",
"kind": "daily",
"sections": [
{ "heading": "Upcoming charges", "rows": [{ "title": "…", "amount": "…", "sub": "…" }] }
],
"text": "plain-text version",
"markdown": "Markdown version",
"url": "https://calends.example.com/admin"
}

kind is daily (daily reminder), monthly (monthly bill preview) or test. text and markdown are the fully formatted message, ready to forward elsewhere; sections is the structured data if you’d rather format it yourself.

  • Click Test next to the channel; on failure you’ll see the error the service returned.
  • Many bot APIs return HTTP 200 even on errors, so Calends checks the error code in the response body (errcode for DingTalk and WeCom, code for Lark and ServerChan, ok for Telegram) and shows the reason.
  • If a required field is empty, you’re told which field the channel is missing.