Choose a delivery mode
ALERT_DELIVERY has two values and defaults to batched.
In batched mode each subscribed channel receives the owned app report first and the competitor report second. Subscription filters apply to both scopes independently, so an owned only channel receives one report and a competitor only channel receives the other. An empty scope produces no notification at all.
Batched delivery is durable. A flush claims a fixed snapshot of pending rows before sending, so a queue or process failure leaves that claim resumable with the same rows, timestamp and delivery identifiers. Later facts wait for a later claim rather than joining the retry. Re runs and multi market checks deduplicate the same fact before it is claimed, with the latest values winning.
There is no separate alert schedule.
CRON_DAILY controls when processing starts, while workload and retry duration decide when the report goes out.
Subscribe to events
Existing subscribers are unaffected by
action.opened until they opt into it on the settings page.
Webhook delivery
A webhook receives a JSON POST with two headers, plus a signature header when the subscription has a secret.
Verify the signature by computing an HMAC-SHA256 of the raw request body with your subscription secret and comparing it, in constant time, with the header value. Compute it over the bytes you received rather than over a re serialized object.
A granular event looks like this.
scope, which is owned_apps or competitors. The flat events array stays granular and contains only events for that scope, so a consumer that already handles granular events needs one extra branch rather than a rewrite.
link is present only when WEB_PUBLIC_URL is set. That variable is used for nothing else. When it is unset the link is null rather than a broken localhost guess.
Slack, Discord and ntfy all accept a plain webhook endpoint, and asobeast formats for the first two.
Email delivery
Email stays disabled until bothSMTP_HOST and SMTP_FROM are set. Neither one alone enables it.
To try it locally, run a throwaway SMTP sink. See Set up a development environment.
Read the delivery history
Every attempt on every channel is logged with its outcome and surfaced per channel on the settings page. Rows followRETENTION_DELIVERIES_DAYS, which defaults to 30 days.
Completed batch claims follow RETENTION_ALERT_EVENTS_DAYS, also 30 days by default. Claims that have not finished are retained regardless, so a stuck flush is never pruned out from under its retry.
Troubleshooting
- The webhook endpoint returns a non 2xx status. The delivery is logged as failed with the status. Fix the endpoint and use flush now to make an early claim of the facts currently pending.
- The signature does not verify. Compute the HMAC over the raw request body bytes. Re serializing the parsed JSON changes whitespace and key order, which changes the digest.
- Email never sends. Check that both
SMTP_HOSTandSMTP_FROMare set. One without the other leaves email disabled. - The relay rejects the sender. Many relays require the envelope sender to match an authorized domain. Set
SMTP_FROMto an address on the domain the relay accepts. - Deep links are missing.
WEB_PUBLIC_URLis unset, solinkisnullby design. - Reports arrive at an unpredictable hour. In batched mode the flush waits for every child job to settle, including retries.
CRON_DAILYsets the start, not the delivery time.
Related
Work the Action Center
Where
action.opened comes from.Compare a portfolio
Where the weekly digest comes from.