Skip to main content
When the webhook is on in your competitor alert settings, Clustr POSTs every competitor alert to your URL, one request per alert, and a recap after each team refresh. Turn it on and set the URL and secret with Update Competitor Alerts, and send a sample with Test Competitor Alert Webhook. Two events reach this URL: The competitor report has its own webhook, configured separately: competitor_monitoring.report_ready.

Request

Every request is a POST with a JSON body and these headers: Header names are case-insensitive. Any 2xx answer counts as delivered.

competitor_monitoring.account_alert

One per account per monitoring run, for the Defense and Attack alerts: the account and every person a competitor engaged there in the alert’s period. Only their people’s own actions count: a like or comment by someone at the account on the competitor’s post never alerts. A pleasantry (“Congrats!”) counts as a like. Defense alerts on its rule. Attack alerts on its rule only when their sales team is prospecting the account (account.reading is prospecting), and on any pitch. On both, a comment on a post that shows buying intent alerts on its own.

competitor_monitoring.alert

One schema for all three alert types. Every field is always present: a field that does not apply to the alert type is null, never missing. direction is outbound when the competitor’s salesperson engaged the person’s post, and inbound when the person engaged the salesperson’s post. Attack covers every non-customer account, and account_scope says which kind it is, so you can route them apart: target for the accounts on your target account list, other for every other account a competitor engages with (someone matching your buyer titles). Slack posts and emails say the same as “Target account” or “Other account”. To stop the alerts on other accounts, set attack_other_accounts to false with Update Competitor Alerts. account_scope and account.is_target are new fields (as is account.clustr_account_id): a receiver that ignores unknown keys keeps working. The owner comes from your CRM and nothing else: the company owner field for Attack, and the CS owner field (company_cs in Set Owner Field Mappings) for Defense. Clustr reads it from your CRM when it sends the alert. If your CRM cannot be reached at that moment, it uses the owner from the last CRM sync instead.

defense_interaction

Someone at one of your customers interacted with a competitor’s salesperson. Every retained interaction alerts, likes included, in both directions. Each interaction alerts once.

attack_critical_comment

A competitor’s salesperson left a comment classified as critical (a meeting request, a comparison, an objection handled, and so on) on the post of someone at a non-customer account.

attack_engagement_threshold

A non-customer account reached your threshold: at least attack_threshold_interactions interactions over attack_threshold_days days (10 in 30 by default), with one competitor’s team (attack_threshold_scope per_competitor, the default) or with all your competitors together (all_competitors). There is no cooldown: the alert is sent again after every collection run while the account stays at or above the threshold, each time with a new alert_id.
A sample sent with Test Competitor Alert Webhook has the same shape, an attack_critical_comment with made-up values, plus "test": true.

competitor_monitoring.team_refresh

Sent once after each finished team refresh of a competitor. The same recap is posted once to each distinct Slack channel you configured. A follow-up employment check (a profile checked again a few days after a refresh could not place it) that finds a leaver or a role change sends one too, with joiners at 0.

Signature

When a webhook secret is saved, every request carries X-ClustR-Signature:
v1 is the hex HMAC-SHA256 of <t>.<raw body>, keyed with your secret. It is computed on each attempt, over the exact bytes sent, so verify against the raw request body before parsing it. Compare in constant time, and reject a t older than a few minutes to stop replays.
Without a saved secret the requests are sent unsigned.

Delivery and retries

Webhooks go through a queue, so they leave Clustr within a few seconds, not in the same instant as the Slack post.
  • Up to 3 attempts. A failed attempt is retried after 5 seconds, then after 20 seconds. After the third failure the delivery is dropped.
  • Within one attempt, a 408, 429, 500, 502, 503 or 504 answer is retried a few times with a short backoff before the attempt counts as failed.
  • 30-second timeout per request.
  • Once per alert. An alert is queued at most once per URL. A retry can still deliver the same alert twice if your endpoint timed out after processing it, so dedupe on alert_id (or id for a team refresh).
A broken webhook never holds up the Slack posts, and a Slack failure never holds up the webhook.