How delivery works
| Channel | Immediate alerts | Weekly digest |
|---|---|---|
| Email, Slack, Microsoft Teams, webhooks | Critical changes | Yes (skipped when nothing changed) |
| PagerDuty | Critical and high changes | Never |
| Jira | Critical and high changes, one issue request per change | No |
- Examples of critical changes: a certificate from a CA you have not authorised, a sensitive port opening, a new vulnerability on the CISA KEV catalog, removal of a registrar transfer lock.
- On MSP plans a channel can be scoped to one client workspace.
- Every confirmed channel has a Send test button, which delivers a sample
high-importance change for
test.example.com. - Delivery failures are recorded on the channel and shown in the app; they never block other channels.
Each address must confirm through a link before anything is sent to it.
Slack
Create an incoming webhook
for the channel and paste its https://hooks.slack.com/… URL.
Microsoft Teams
- In the Teams channel, open Workflows and choose the template Post to a channel when a webhook request is received.
- Finish the wizard and copy the HTTP POST URL it gives you. It will be on
*.logic.azure.com,*.powerplatform.comor*.webhook.office.com. - Add a Microsoft Teams channel in Attack Surface Scan and paste the URL.
Messages are Adaptive Cards (version 1.4) listing up to 20 changes, with a button that opens the app. Teams channels get critical alerts and the weekly digest, like Slack.
PagerDuty
- In PagerDuty, open the service, Integrations → Add integration → Events API V2.
- Copy the 32-character Integration Key (routing key).
- Add a PagerDuty channel in Attack Surface Scan and paste the key.
Critical and high changes trigger events immediately (up to 20 per delivery); the digest is
never sent to PagerDuty. Critical maps to PagerDuty severity critical and high to
error. Each event's dedup_key is afs- followed by 32 hex characters
derived from the target, the change kind and its new value, so a repeat of the same change updates
the open incident instead of paging again. Resolve events are not sent: resolve the incident in
PagerDuty once the next scan confirms the fix.
Jira (via Jira Automation)
No Jira credentials are stored with us. Jira Automation receives a webhook and creates the issue on your side, with your project, issue type and fields. One request is sent per critical or high change.
- In Jira, Project settings → Automation → Create rule. Choose the trigger Incoming webhook with No issues from the webhook. Copy the webhook URL, and the secret if one is shown.
- Add the action Create issue. Set Summary to
{{webhookData.summary}}and Description to{{webhookData.description}}. - Under Additional fields, paste:
{ "fields": { "priority": { "name": "{{webhookData.priority}}" }, "labels": {{webhookData.labels.asJsonStringArray}} } } - Add a Jira channel in Attack Surface Scan and paste the URL (it starts with
https://automation.atlassian.com/orhttps://api-private.atlassian.com/automation/webhooks/), plus the secret if you have one. The secret is sent in theX-Automation-Webhook-Tokenheader.
Atlassian changes the Automation UI and webhook URL format from time to time; check Atlassian's current documentation if a step does not match what you see.
Payload
{
"summary": "Critical: Port 5432 (PostgreSQL) started answering on db.example.com",
"description": "…",
"priority": "Highest",
"importance": "critical",
"labels": ["attack-surface-scan", "port-opened"],
"target": "db.example.com",
"kind": "port.opened",
"dedupKey": "afs-…",
"changeId": "3f0c…",
"scanId": "…",
"detectedAt": "2026-09-28T09:11:04.000Z",
"url": "https://attacksurfacescan.com/app/…"
}
priority is Highest, High, Medium or Low.
Avoiding duplicate issues (optional)
The description includes the dedupKey. Before Create issue, add a
Lookup issues action with the JQL
labels = attack-surface-scan AND text ~ "{{webhookData.dedupKey}}" AND statusCategory != Done
then a condition that {{lookupIssues.size}} equals 0, so a repeat of an
open change does not create a second issue.
Generic webhooks
Any HTTPS endpoint on a public hostname. Literal IP addresses, localhost,
.internal and .local names are rejected, redirects are not followed, and the
request times out after 10 seconds. The default JSON body:
{
"subject": "Critical change on example.com",
"body": "Port 5432 (PostgreSQL) started answering on db.example.com",
"changes": [
{
"changeId": "3f0c…",
"target": "db.example.com",
"kind": "port.opened",
"importance": "critical",
"title": "Port 5432 (PostgreSQL) started answering",
"before": "closed",
"after": "open",
"scanId": "…",
"detectedAt": "2026-09-28T09:11:04.000Z"
}
]
}
importance is one of critical, high, medium or
low. kind is one of:
| Area | Change kinds |
|---|---|
| Hosts and inventory | subdomain.added subdomain.removed asset.added asset.removed candidate.found |
| DNS and domains | dns.changed domain.expiring domain.lock_changed lookalike.registered |
| Services and software | port.opened port.closed tech.added tech.removed vuln.new |
| Certificates | cert.issued cert.misissued cert.issuer_changed cert.expiring cert.renewed cert.stale monitor.unreachable |
| Findings and score | finding.new finding.resolved score.changed |
| Reputation | reputation.listed reputation.cleared |
OCSF format for SIEMs
Set the webhook's format to OCSF (SIEM) to receive each delivery as a JSON array of Open Cybersecurity Schema Framework 1.3.0 Detection Finding events (class 2004), which Amazon Security Lake, Splunk, Microsoft Sentinel and other SIEMs ingest without a custom parser. Abridged example (the real event also carries the class, category, activity, severity and status names, a message, product metadata and finding times):
[
{
"class_uid": 2004,
"category_uid": 2,
"activity_id": 1,
"type_uid": 200401,
"severity_id": 5,
"status_id": 1,
"time": 1790586664000,
"metadata": {
"version": "1.3.0",
"uid": "3f0c…",
"event_code": "port.opened"
},
"finding_info": {
"uid": "afs-…",
"title": "Port 5432 (PostgreSQL) started answering"
},
"resources": [{ "type": "Host", "name": "db.example.com" }],
"unmapped": { "importance": "critical", "before": "closed", "after": "open", "scan_id": "…" }
}
]
| Field | Value |
|---|---|
severity_id | critical 5, high 4, medium 3, low 2 |
status_id | 1 (new) |
time | Detection time, epoch milliseconds |
metadata.uid | The change ID |
metadata.event_code | The change kind |
finding_info.uid | The same dedup key PagerDuty and Jira receive |
resources | The affected host |
unmapped | importance, before, after, scan_id |
Pulling instead of pushing
For scheduled pulls into a data warehouse or GRC tool, use the REST API (Growth and above) or the CSV exports on the Compliance page.