Skip to main content

Webhooks API

Webhooks let you receive real-time notifications when events occur in Infracast. When a new critical finding is detected, a discovery job completes, or a report is ready, Infracast sends an HTTP POST to your configured endpoint. Webhooks are configured via the Integrations API.


Endpoints

MethodPathDescriptionPermission
GET/api/v1/tenants/{tenantID}/integrationsList integrations (including webhooks)tenant:read
POST/api/v1/tenants/{tenantID}/integrationsCreate a webhooktenant:update
GET/api/v1/tenants/{tenantID}/integrations/{integrationID}Get webhook configtenant:read
PUT/api/v1/tenants/{tenantID}/integrations/{integrationID}Update webhooktenant:update
DELETE/api/v1/tenants/{tenantID}/integrations/{integrationID}Delete webhooktenant:update

Creating a Webhook

curl -X POST https://api.infracast.io/api/v1/tenants/acme-corp/integrations \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "webhook",
"name": "Security Alerts — Slack Relay",
"config": {
"url": "https://your-app.com/infracast/webhook",
"secret": "your-webhook-signing-secret",
"events": [
"finding.created",
"finding.severity_changed",
"job.completed",
"job.failed"
],
"filters": {
"severity": ["CRITICAL", "HIGH"]
},
"headers": {
"X-Source": "infracast",
"X-Environment": "production"
}
}
}'

Configuration Fields

FieldTypeRequiredDescription
typestringMust be "webhook"
namestringHuman-readable name
config.urlstringHTTPS endpoint to POST events to
config.secretstringSigning secret for HMAC verification
config.eventsarrayEvent types to subscribe to
config.filtersobjectOptional filters to reduce event volume
config.headersobjectAdditional HTTP headers to include
config.timeout_secondsintRequest timeout (default: 30)

Response

{
"id": "intg-abc123def456",
"type": "webhook",
"name": "Security Alerts — Slack Relay",
"status": "active",
"config": {
"url": "https://your-app.com/infracast/webhook",
"events": ["finding.created", "finding.severity_changed", "job.completed", "job.failed"],
"filters": { "severity": ["CRITICAL", "HIGH"] }
},
"created_at": "2024-03-16T10:00:00Z"
}
Store Your Secret

The webhook secret is only returned on creation. Store it securely (e.g., in your secrets manager). You'll need it to verify webhook signatures.


Event Types

Finding Events

EventTrigger
finding.createdA new compliance finding is detected
finding.resolvedA previously open finding is no longer triggered
finding.severity_changedFinding severity upgraded or downgraded
finding.risk_acceptedFinding marked as accepted risk
finding.reopenedA resolved finding is detected again

Discovery Job Events

EventTrigger
job.createdA discovery job is created
job.startedA discovery job begins running
job.completedA discovery job finished successfully
job.failedA discovery job failed
job.cancelledA discovery job was cancelled

Report Events

EventTrigger
report.generatedA report is ready to download
report.failedReport generation failed
report.scheduledA scheduled report delivery is sent

Compliance Events

EventTrigger
compliance.score_changedOverall compliance score changed by ≥5%
compliance.control_failedA previously passing control is now failing
compliance.control_passedA previously failing control is now passing

Webhook Payload Format

All events share a common envelope structure:

{
"id": "evt-abc123def456",
"type": "finding.created",
"tenant_id": "acme-corp",
"timestamp": "2024-03-16T10:05:23Z",
"data": { ... }
}

finding.created Payload

{
"id": "evt-abc123def456",
"type": "finding.created",
"tenant_id": "acme-corp",
"timestamp": "2024-03-16T10:05:23Z",
"data": {
"finding": {
"id": "CIS-AWS-5.2-aws:us-east-1:aws.ec2.security_group:sg-0abc123",
"rule_id": "CIS-AWS-5.2",
"framework": "cis-aws",
"control_id": "5.2",
"severity": "HIGH",
"title": "Security group allows unrestricted SSH access",
"description": "Security group 'web-servers-sg' has an inbound rule for SSH from 0.0.0.0/0.",
"resource_id": "aws:us-east-1:aws.ec2.security_group:sg-0abc123",
"resource_type": "aws.ec2.security_group",
"resource_name": "web-servers-sg",
"region": "us-east-1",
"remediation": "Remove the 0.0.0.0/0 inbound rule for port 22.",
"created_at": "2024-03-16T10:05:23Z"
}
}
}

job.completed Payload

{
"id": "evt-xyz789",
"type": "job.completed",
"tenant_id": "acme-corp",
"timestamp": "2024-03-16T10:03:07Z",
"data": {
"job": {
"id": "job-abc123def456",
"name": "Full AWS Discovery",
"plugins": ["aws"],
"status": "completed",
"stats": {
"nodes_discovered": 1247,
"nodes_updated": 312,
"findings_created": 34,
"findings_resolved": 12,
"duration_seconds": 187
},
"started_at": "2024-03-16T10:00:00Z",
"completed_at": "2024-03-16T10:03:07Z"
}
}
}

compliance.score_changed Payload

{
"id": "evt-score001",
"type": "compliance.score_changed",
"tenant_id": "acme-corp",
"timestamp": "2024-03-16T10:05:30Z",
"data": {
"framework": "nist-800-53",
"previous_score": 87,
"current_score": 79,
"delta": -8,
"triggered_by": "job-abc123def456",
"new_failures": 4,
"new_passes": 0
}
}

report.generated Payload

{
"id": "evt-rpt001",
"type": "report.generated",
"tenant_id": "acme-corp",
"timestamp": "2024-03-16T10:01:30Z",
"data": {
"report": {
"id": "rpt-abc123",
"type": "framework",
"framework": "pci-dss",
"format": "pdf",
"download_url": "https://api.infracast.io/api/v1/tenants/acme-corp/reports/rpt-abc123/download",
"download_expires": "2024-03-23T10:01:30Z",
"size_bytes": 2847392
}
}
}

Signature Verification

Infracast signs every webhook request using HMAC-SHA256. Always verify the signature before processing the payload to ensure the request is authentic.

Signature Header

X-Infracast-Signature: sha256=2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
X-Infracast-Timestamp: 1710590400
X-Infracast-Event: finding.created

Verification (Python)

import hmac
import hashlib
import time

def verify_webhook(secret: str, payload: bytes, signature: str, timestamp: str) -> bool:
# Reject requests older than 5 minutes
if abs(time.time() - int(timestamp)) > 300:
return False

# Compute expected signature
message = f"{timestamp}.{payload.decode('utf-8')}"
expected = hmac.new(
secret.encode('utf-8'),
message.encode('utf-8'),
hashlib.sha256
).hexdigest()

# Compare (constant-time)
return hmac.compare_digest(f"sha256={expected}", signature)

# In your webhook handler:
@app.route('/infracast/webhook', methods=['POST'])
def handle_webhook():
if not verify_webhook(
secret=os.environ['WEBHOOK_SECRET'],
payload=request.data,
signature=request.headers['X-Infracast-Signature'],
timestamp=request.headers['X-Infracast-Timestamp']
):
return "Unauthorized", 401

event = request.json
if event['type'] == 'finding.created':
finding = event['data']['finding']
if finding['severity'] in ('CRITICAL', 'HIGH'):
send_slack_alert(finding)

return "OK", 200

Verification (Node.js)

const crypto = require('crypto');

function verifyWebhook(secret, payload, signature, timestamp) {
// Reject old requests
if (Math.abs(Date.now() / 1000 - parseInt(timestamp)) > 300) return false;

const message = `${timestamp}.${payload}`;
const expected = crypto
.createHmac('sha256', secret)
.update(message)
.digest('hex');

return crypto.timingSafeEqual(
Buffer.from(`sha256=${expected}`),
Buffer.from(signature)
);
}

Filtering Events

Reduce webhook noise with event filters:

{
"config": {
"url": "https://your-app.com/webhook",
"events": ["finding.created"],
"filters": {
"severity": ["CRITICAL", "HIGH"],
"frameworks": ["nist-800-53", "fedramp-high"],
"resource_types": ["aws.s3.bucket", "aws.ec2.security_group"]
}
}
}

Retry Policy

If your endpoint returns a non-2xx status or times out, Infracast retries with exponential backoff:

AttemptDelay
1 (initial)Immediate
230 seconds
35 minutes
430 minutes
52 hours

After 5 failed attempts, the event is marked as permanently failed and the webhook is automatically disabled if failure rate exceeds 50%.

tip

Respond with 200 OK immediately and process events asynchronously (queue them). This prevents timeouts from triggering retries for events you did receive.


Other Integration Types

Beyond webhooks, Infracast supports direct integrations with popular tools via the same Integrations API:

Integration Typetype valuePurpose
Webhook (HTTP)webhookCustom HTTP endpoint
SlackslackSlack channel alerts
PagerDutypagerdutyIncident creation
ServiceNowservicenowTicket creation
JirajiraIssue creation
Microsoft TeamsteamsTeams channel alerts
EmailemailEmail notifications

Next Steps