Notifications & digests

When something lands in one of your flows, AppMate tells you — by email, in Slack, or both. Alerts are per-submission and near-instant; an optional daily or weekly digest rolls the same data up into one message. Everything is configured in Settings → Profile.

Per-submission alerts

Every new submission fires an alert to the app's owner. Six submission types are covered:

  • Waitlist signup — someone joins a waitlist.
  • Feedback message
  • Report
  • Crash report
  • Contact message
  • Feature request — a new wishlist idea, and also a new comment on an existing idea.

The alert names the app, carries a short preview of what was written, adds context rows where the flow has them (reply-to email, category, rating, device…), and links straight to that submission list in the dashboard.

Alerts are best-effort and fire after the response is sent, so a misconfigured channel can never make a submission fail. Channels are dispatched independently too — a broken Slack webhook doesn't suppress the email, and vice-versa.

Channels

Two channels exist today: email (delivered through Resend) and Slack. They're independent — enable either or both. The per-type toggles are a shared gate: if you mute “crash report”, no channel fires for crashes.

Email and Slack are the current channels. There is no Telegram, SMS, or webhook channel yet.

Connecting Slack

There are two ways to point AppMate at a Slack channel.

1. Add to Slack (one click)

AppMate ships a single Slack app. Hit Add to Slack, authorise it, and pick the channel you want — Slack hands back an Incoming Webhook scoped to that channel and AppMate stores it for you, along with the channel name for display. The only scope requested is incoming-webhook: no bot token is stored and AppMate never reads your Slack messages.

2. Paste an Incoming Webhook

Or do it by hand: create a Slack app, enable Incoming Webhooks, pick a channel, and paste the resulting URL into the field in Settings → Profile. Save, then use Send test to post a test message to the saved webhook and confirm the connection end-to-end.

text
https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX

Account channel vs. per-app channel

The webhook you set in Settings → Profile is your account default— every app you own posts there. Each app can also have its own webhook, set on the app's Settingspage (the same two routes work there: an “Add to Slack” button, or a pasted URL).

  • A per-app webhook winswhen it's set — it's an explicit “route this app here”, and it's active whether or not the account-level Slack toggle is on.
  • With no per-app webhook, alerts fall back to the account channel — but only when you've enabled Slack on your profile.
  • Your per-type toggles still apply either way, and the message always names the app and links to its dashboard.

So a multi-app owner can send each app's alerts to its own channel, with anything unrouted landing in the account default.

Webhook validation (SSRF guard)

Slack webhook URLs are user-supplied and AppMate POSTs to them server-side, so they're validated before they're ever stored or used. A URL is accepted only if all of the following hold:

  • the scheme is https:;
  • the host is exactly hooks.slack.com;
  • the path starts with /services/;
  • the whole URL is at most 300 characters.

Anything else is rejected, so a crafted value can't make the server reach an internal address. The check runs when preferences are saved, when they're read back, and again at send time. A saved config with no usable webhook is also forced “off” rather than left looking enabled while doing nothing.

Daily & weekly digests

A digest is an opt-in roll-up of what came in over the window — for each of your apps, a count per submission type (“3 feedback messages, 1 waitlist signup”), the grand total, and a link to your dashboard. Apps with nothing new are left out, and if nothing came in at all the digest isn't sent — no empty “nothing happened” mail.

  • Daily covers the last 24 hours; weekly covers the last 7 days.
  • Delivered over the same channels as alerts — email and your account Slack webhook. (Per-app webhooks are for real-time alerts; digests use the account channel.)
  • Counts cover the same six types as alerts. Digests are not filtered by the per-type toggles.
  • Both are off by default — tick them in Settings → Profile.

Sends are scheduled by an in-process cron. The default schedule is a standard cron expression evaluated in UTC:

text
DIGEST_DAILY_CRON    0 17 * * *     # daily  — 17:00 UTC
DIGEST_WEEKLY_CRON   0 8 * * 1      # weekly — Mondays, 08:00 UTC

Each window is claimed exactly once, so running several server replicas never produces duplicate digests. Self-hosters can override either expression, set DIGEST_DISABLED=1 to turn the in-process scheduler off, and drive sweeps from an external cron by POSTing to /api/cron/digest?period=daily|weekly with the CRON_SECRET as a bearer token.

Notification preferences

Everything above lives in one card under Settings → Profile:

  • Email me — the master switch for the email channel.
  • Post to Slack— the account Slack channel, plus the “Add to Slack” button, the webhook field and Send test.
  • Which submissions — one toggle per type, applied across every channel.
  • Digest — daily and weekly checkboxes.

Alerts go to your sign-in email. Super-admins get one extra field, Send alerts to, which redirects email alerts to a different address — useful when the account email is a shared alias with no real mailbox.

Notifications only reach the app's owner, and only while that account is active.

See the wishlist and the API reference for what the individual flows collect.