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
typestring✅Must be "webhook"
namestring✅Human-readable name
config.urlstring✅HTTPS endpoint to POST events to
config.secretstring✅Signing secret for HMAC verification
config.eventsarray✅Event types to subscribe to
config.filtersobject❌Optional filters to reduce event volume
config.headersobject❌Additional HTTP headers to include
config.timeout_secondsint❌Request 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​