Insights and alerts
Insights show what Slipmark caught across your repositories. Alerts tell you when something needs a person.
Insights
Open the Insights tab on your dashboard and pick a period. Everything is worked out from your own ledger: the runs recorded and the gate results Slipmark Cloud worked out for them. Insights for public repositories are free on every plan. Team and Business add private repositories.
| Measure | What it means |
|---|---|
| Runs and refusals | Every recorded CI run per week, split into passed and refused. A rising refusal line usually means agents are attesting before the code settles. |
| Stale verdicts caught | Verdicts whose files changed after the verdict was given, or were deleted. Each one is a review that would otherwise have looked green while covering different code. |
| Pull request coverage | The share of pull requests whose latest run had every verdict current and passing. |
| Pass rate by agent | For each agent name, how many of its verdicts were verified, refused as stale, or not passing. |
| By rule | For each rule: how many pull requests it applied to, how many met it first time, and how many meet it now. An override counts as not met. A low first-time number points at a rule or an agent that needs attention. |
| Overrides | How many failing checks were approved anyway, by whom, and against which rules. |
Stale verdicts caught is the number to watch. Each one is a verdict from your agents that looked valid but was about a different version of the file than the one being merged.
Slack alerts
Team and Business accounts can send alerts to a Slack channel.
In Slack, create an incoming webhook for the channel you want. Slack's guide is at api.slack.com/messaging/webhooks. You get a URL that starts with
https://hooks.slack.com/.On your Slipmark dashboard, open the Settings tab, paste the URL and save. Only admins can do this. We accept
hooks.slack.comaddresses only, and once saved the URL is never shown in full again. To change other settings later, leave the URL field blank and the current webhook is kept.Choose which alerts you want.
| Alert | Sent when |
|---|---|
| Refused verdicts on the default branch | A push to the repository's default branch ran Slipmark and the gate refused. Stale or failing verdicts reached the code you ship. |
| Slipmark policy failed | A pull request did not meet one of your rules. |
| Override | An admin approved a failing check. The alert names who and why. |
Each alert links to the run, so the person on call can see exactly which file and which verdict caused it. To stop alerts, use Disconnect Slack on the Settings tab, or delete the webhook in Slack.
Webhooks and integrations
On the Settings tab, paste a webhook URL or a PagerDuty key under Webhooks and integrations. Slipmark recognises where it points and sends each event in that app's own format. You can add up to ten destinations, and each one picks its own events. For example, failures go to the security on-call in PagerDuty, everything goes to an engineering channel in Teams, and a full feed goes to your SIEM.
| Paste | You get |
|---|---|
| Microsoft Teams Workflows webhook | An Adaptive Card with the result, the facts and an Open in Slipmark button. In Teams, use the “Post to a channel when a webhook request is received” workflow. |
| Slack incoming webhook | A formatted message. Add several to route events to different channels. |
| Discord channel webhook | A coloured embed: red for failures, green for recoveries. |
| Google Chat space webhook | A message with a link to the record. |
| PagerDuty Events API v2 integration key | An incident when a pull request fails your rules or refused verdicts reach the default branch. It resolves on its own when the PR passes, the branch recovers or an admin approves. Rule changes show as change events, so they appear on the timeline without paging anyone. |
| Email addresses, up to five, separated by commas | A short email with the result, the fix and buttons for the pull request and the proof record. Sent from alerts@slipmark.dev. |
| Zapier, Make, n8n or any HTTPS URL | Signed JSON, described below. This connects Slipmark to Jira, Linear, Sheets and thousands of other apps with no code. |
Every failure message says what to do about it: which rule, which files, which agent needs to sign them off, and the command that records a fresh verdict. Messages link straight to the pull request and the proof record.
The Slipmark Slack app
On the Settings tab, Add to Slack installs the Slipmark app and lets you pick a channel. It does more than an incoming webhook:
- Each pull request gets one thread. Failures, passes and overrides for that PR go in the thread, and the top message always shows where it stands now, so the channel stays readable.
- A failing pull request has an Approve with reason button. It opens a box for the reason, and the approval is made exactly as if it were made on Slipmark Cloud: by a GitHub admin of the account, written to the account log, and shown on the GitHub check.
- The first time someone presses it, Slack asks them to link their Slack user to their GitHub account. Slipmark checks they are an admin each time, not just once.
To remove it, use Remove on the destination. That also revokes the app's access to your workspace.
Choosing what each destination gets
Open Edit on any destination to change these without removing it.
| Setting | What it does |
|---|---|
| Events | Which events it gets. Leave all unticked for everything. |
| Repositories | Only events from these repositories. Names or patterns, for example payments-* or acme/api. Empty means all. |
| Rules | Only rule events (failed, passed, override, rule changed) that involve these rules. Other events still arrive. Empty means all. |
| Notify | Who to ping when something needs a person: failures, refusals and overrides. In Slack, @here, @channel, a member ID such as U012AB3CD or a user group ID such as S012AB3CD. In Discord, @here, a user ID or &roleid. In Google Chat, @all or a user ID. Passes and summaries never ping anyone. |
Send a test lets you pick any event and sends an example of it, marked “Test”, so you can see the real format before anything happens.
Weekly summary
Tick Weekly summary on a destination and every Monday at 8am UK time it gets one message: runs and the trend from last week, pull requests checked and blocked, stale verdicts caught, the rule missed most often, and every override with its reason. Nothing is sent for a week with no runs.
Events
| Event | Sent when |
|---|---|
run.refused_on_default | The gate refused on a push to the default branch. |
run.recovered_on_default | The default branch passes again after a refusal. |
policy.failed | A pull request did not meet one of your rules. |
policy.passed | A pull request that was failing now meets every rule. |
override.created | An admin approved a failing check, with their reason. |
rule.changed | A rule was added, turned on or turned off. |
digest.weekly | Mondays, the weekly summary described above. Only to destinations that ticked it, or that take every event. |
ping | A destination was added, or you pressed Send a test event. Sent only to that destination. |
Retries and the delivery log
A destination has 10 seconds to answer with a 2xx status. If it doesn't, Slipmark tries again after 1 minute, 5 minutes, 30 minutes, 2 hours, 5 hours, 10 hours and 10 hours: eight attempts over about 28 hours. Redirects are not followed. The Settings tab lists the last 25 deliveries with their status and error, and a Redeliver button. A destination that fails 25 times in a row with no success for 24 hours is paused, and you're told in Slack if it's connected. Adding, removing, pausing and resuming destinations is recorded in the account log. Delivery records are kept for 30 days.
Generic webhook format
Every event is a JSON POST with the same envelope:
POST /your/endpoint
content-type: application/json
webhook-id: evt_5f0c2b8e9d6a41f3b2c7e1a0
webhook-timestamp: 1792693443
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4=
x-slipmark-event: policy.failed
{
"id": "evt_5f0c2b8e9d6a41f3b2c7e1a0",
"type": "policy.failed",
"timestamp": "2026-10-22T09:14:03.120Z",
"account": "your-org",
"data": {
"repo": "your-org/api",
"pr_number": 412,
"head_sha": "9f3c…",
"run_url": "https://app.slipmark.dev/r/your-org/api/runs/…",
"unmet": [{ "rule": "Auth changes need a security review", "missing": ["src/auth/session.ts"] }]
}
}The id stays the same when a delivery is retried or redelivered, so you can use it to ignore duplicates.
Checking the signature
Slipmark signs to the Standard Webhooks specification, the same scheme used by Svix and others. Use an official library for your language with the whsec_ secret from the Settings tab. It checks the signature and rejects messages older than five minutes.
import { Webhook } from "standardwebhooks";
const wh = new Webhook(process.env.SLIPMARK_WEBHOOK_SECRET); // whsec_…
// rawBody must be the exact bytes received, before any JSON parsing.
const event = wh.verify(rawBody, {
"webhook-id": req.headers["webhook-id"],
"webhook-timestamp": req.headers["webhook-timestamp"],
"webhook-signature": req.headers["webhook-signature"],
});Without a library: base64-decode the secret after whsec_, compute HMAC-SHA256 of <webhook-id>.<webhook-timestamp>.<raw body>, base64-encode it, and compare it in constant time with the value after v1,. Requests also carry the older X-Slipmark-Signature: t=<unix>,v1=<hex> header, an HMAC of <t>.<raw body> keyed with the whole secret string, for integrations built before October 2026. Rotate secret issues a new secret straight away.