Documentation

Webhook Documentation

Learn how to set up and handle webhooks to receive real-time notifications about scan results.

Overview

What are Webhooks?

Webhooks are HTTP POST requests sent by SIDEX to your application when specific events occur. Instead of polling our API to check for updates, webhooks deliver notifications in real-time when scans complete or fail.

Webhook Events

Currently, SIDEX supports the following webhook events:

scan.completedevent

Sent when a URL scan completes successfully with threat analysis

scan.failedevent

Sent when a URL scan fails due to errors or network issues

Subscription-Based Data Access

Webhook payloads are automatically sanitized based on your subscription plan. Each plan has access to different data dimensions. Dimensions not included in your plan will be returned as null.

Dimensions by Plan

Free
securitytrust
Starter
securitytrustcontent
Pro
securitytrustbusinesscontentinsight
Enterprise
securitytrustbusinesscontenttechnicalinsight

Dimension Details

security

Threat analysis, SSL info, brand impersonation detection, risk factors

treatLevelthreatScorethreatssslbrandImpersonationriskFactors
trust

SSL validation, domain WHOIS data, registrar information

ssldomainoriginalDomain
content

Page content analysis, forms detection, gambling/adult content detection

pageTitlemetaDescriptionlanguageformsgamblingadult
business

Business classification, company information, industry data

categorycompanyNamebusinessTypeindustryClassification
technical

HTTP status, IP geolocation, ASN information, security headers

httpStatusCodecontentTypeipAddressesipCountryasnasnOrg
insight

AI-generated summary, risk assessment, recommendations

summaryconfidenceriskAssessmentkeyFindingsrecommendations

Webhook Headers and Signature

Request Headers

All webhook requests include the following headers:

Content-Type

application/json

X-Sidex-Event

Event type (scan.completed or scan.failed)

X-Sidex-Signature

SHA-256 HMAC signature for request verification

X-Sidex-Delivery-Id

Unique identifier for this webhook delivery

Signature Verification

To verify webhook authenticity, compute the SHA-256 HMAC of the request body using your webhook secret:

const crypto = require('crypto');
const webhookSecret = 'your_webhook_secret';
const signature = crypto
  .createHmac('sha256', webhookSecret)
  .update(JSON.stringify(body))
  .digest('hex');

// Compare with X-Sidex-Signature header
if (signature === headerSignature) {
  // Webhook is authentic
}

Server Configuration

Timeout

Your webhook endpoint must respond within 30 seconds. Requests that exceed this timeout will be marked as failed.

Expected Response

Return a 2xx status code (200, 201, 204, etc.) to indicate successful processing. Any other status code will be recorded as a failed delivery.

Payload Examples

EVENTscan.completed

Scan Completed

Triggered when a URL scan completes successfully with analysis results.

Enterprise Plan Payload (All Dimensions)

{
  "event": "scan.completed",
  "data": {
    "id": "d323953c-ebda-4b3d-a95b-c7ae2c1814d2",
    "url": "https://example.com",
    "domain": "example.com",
    "originalUrl": "https://example.com",
    "originalDomain": "example.com",
    "status": "completed",
    "scanType": "deep",
    "timeout": 60,
    "redirectChain": [],
    "security": {
      "treatLevel": "safe",
      "threatScore": 10,
      "threats": {
        "phishing": 0,
        "malware": 0,
        "scam": 0,
        "deceptiveContent": 0,
        "adult": 0,
        "gambling": 0
      },
      "ssl": {
        "hasSSL": true,
        "valid": true,
        "issuer": "Let's Encrypt",
        "issueDate": "2024-09-01T00:00:00.000Z",
        "expireDate": "2025-09-01T00:00:00.000Z",
        "ageInDays": 120
      },
      "brandImpersonation": {
        "detected": false,
        "brand": null,
        "confidence": 0
      },
      "riskFactors": [],
      "suspiciousKeywords": []
    },
    "business": {
      "category": "technology",
      "companyName": "Example Inc.",
      "companyDomain": "example.com",
      "companyCountry": "US",
      "businessType": "technology",
      "industryClassification": "Software & Technology",
      "isGamblingBusiness": false
    },
    "technical": {
      "httpStatusCode": 200,
      "contentType": "text/html",
      "ipAddresses": [
        "93.184.216.34"
      ],
      "ipCountry": "US",
      "ipCountryName": "United States",
      "asn": "15133",
      "asnOrg": "Edgecast Inc."
    },
    "content": {
      "pageTitle": "Example Domain",
      "metaDescription": "This domain is for use in illustrative examples.",
      "language": "en",
      "forms": {
        "hasLoginForm": false,
        "requestsPersonalInfo": false,
        "hasUrgencyIndicators": false,
        "requestedInfoTypes": null
      },
      "gambling": {
        "related": false,
        "type": [],
        "confidence": 0
      },
      "adult": {
        "related": false,
        "type": [],
        "confidence": 0
      }
    },
    "trust": {
      "ssl": {
        "valid": true,
        "issuer": "Let's Encrypt",
        "issueDate": "2024-09-01T00:00:00.000Z",
        "expireDate": "2025-09-01T00:00:00.000Z",
        "ageInDays": 120
      },
      "domain": {
        "registeredAt": "1995-08-14T00:00:00.000Z",
        "expireDate": "2025-08-13T00:00:00.000Z",
        "ageInDays": 10800,
        "registrar": "IANA",
        "registrantCountry": "US",
        "status": [
          "active"
        ],
        "nameservers": [
          "a.iana-servers.net",
          "b.iana-servers.net"
        ]
      }
    },
    "insight": {
      "summary": "Legitimate website with no malicious content detected.",
      "confidence": 95,
      "riskAssessment": "LOW RISK: Official example domain maintained by IANA.",
      "keyFindings": [
        "Valid SSL certificate",
        "Long domain age",
        "No suspicious content"
      ],
      "riskFactors": [],
      "positiveIndicators": [
        "Established domain",
        "Clean reputation"
      ],
      "recommendations": [
        "Site is safe to visit"
      ]
    },
    "errorMessage": null,
    "errorCode": null,
    "retryCount": 0,
    "createdAt": "2025-01-06T10:00:00.000Z",
    "updatedAt": "2025-01-06T10:02:30.000Z",
    "completedAt": "2025-01-06T10:02:30.000Z"
  }
}

Free Plan Payload (Limited Dimensions)

Notice that business, technical, content, and insight are null for Free plan users.

{
  "event": "scan.completed",
  "data": {
    "id": "d323953c-ebda-4b3d-a95b-c7ae2c1814d2",
    "url": "https://example.com",
    "domain": "example.com",
    "originalUrl": "https://example.com",
    "originalDomain": "example.com",
    "status": "completed",
    "scanType": "deep",
    "timeout": 60,
    "redirectChain": [],
    "security": {
      "treatLevel": "safe",
      "threatScore": 10,
      "threats": {
        "phishing": 0,
        "malware": 0,
        "scam": 0,
        "deceptiveContent": 0,
        "adult": 0,
        "gambling": 0
      },
      "ssl": {
        "hasSSL": true,
        "valid": true,
        "issuer": "Let's Encrypt",
        "issueDate": "2024-09-01T00:00:00.000Z",
        "expireDate": "2025-09-01T00:00:00.000Z",
        "ageInDays": 120
      },
      "brandImpersonation": {
        "detected": false,
        "brand": null,
        "confidence": 0
      },
      "riskFactors": [],
      "suspiciousKeywords": []
    },
    "business": null,
    "technical": null,
    "content": null,
    "trust": {
      "ssl": {
        "valid": true,
        "issuer": "Let's Encrypt",
        "issueDate": "2024-09-01T00:00:00.000Z",
        "expireDate": "2025-09-01T00:00:00.000Z",
        "ageInDays": 120
      },
      "domain": {
        "registeredAt": "1995-08-14T00:00:00.000Z",
        "expireDate": "2025-08-13T00:00:00.000Z",
        "ageInDays": 10800,
        "registrar": "IANA",
        "registrantCountry": "US",
        "status": [
          "active"
        ],
        "nameservers": [
          "a.iana-servers.net",
          "b.iana-servers.net"
        ]
      }
    },
    "insight": null,
    "errorMessage": null,
    "errorCode": null,
    "retryCount": 0,
    "createdAt": "2025-01-06T10:00:00.000Z",
    "updatedAt": "2025-01-06T10:02:30.000Z",
    "completedAt": "2025-01-06T10:02:30.000Z"
  }
}
EVENTscan.failed

Scan Failed

Triggered when a URL scan fails due to network, validation, or processing errors.

Payload Structure

{
  "event": "scan.failed",
  "data": {
    "id": "a123456c-ebda-4b3d-a95b-c7ae2c1814d3",
    "url": "https://invalid-example.com",
    "status": "failed",
    "errorMessage": "Connection timeout: Unable to reach the domain"
  }
}

Field Descriptions

eventstring

The event type: scan.failed

data.idstring

Unique identifier for the scan

data.urlstring

The URL that was scanned

data.statusstring

Scan status: failed

data.errorMessagestring

Error message describing why the scan failed

cURL Example

curl -X POST https://your-webhook-url.com/webhook \
  -H "Content-Type: application/json" \
  -H "X-Sidex-Event: scan.completed" \
  -H "X-Sidex-Signature: abc123..." \
  -H "X-Sidex-Delivery-Id: del_xyz789" \
  -d '{
  "event": "scan.completed",
  "data": {
    "id": "d323953c-ebda-4b3d-a95b-c7ae2c1814d2",
    "url": "https://example.com",
    "domain": "example.com",
    "originalUrl": "https://example.com",
    "originalDomain": "example.com",
    "status": "completed",
    "scanType": "deep",
    "timeout": 60,
    "redirectChain": [],
    "security": {
      "treatLevel": "safe",
      "threatScore": 10,
      "threats": {
        "phishing": 0,
        "malware": 0,
        "scam": 0,
        "deceptiveContent": 0,
        "adult": 0,
        "gambling": 0
      },
      "ssl": {
        "hasSSL": true,
        "valid": true,
        "issuer": "Let's Encrypt",
        "issueDate": "2024-09-01T00:00:00.000Z",
        "expireDate": "2025-09-01T00:00:00.000Z",
        "ageInDays": 120
      },
      "brandImpersonation": {
        "detected": false,
        "brand": null,
        "confidence": 0
      },
      "riskFactors": [],
      "suspiciousKeywords": []
    },
    "business": {
      "category": "technology",
      "companyName": "Example Inc.",
      "companyDomain": "example.com",
      "companyCountry": "US",
      "businessType": "technology",
      "industryClassification": "Software & Technology",
      "isGamblingBusiness": false
    },
    "technical": {
      "httpStatusCode": 200,
      "contentType": "text/html",
      "ipAddresses": [
        "93.184.216.34"
      ],
      "ipCountry": "US",
      "ipCountryName": "United States",
      "asn": "15133",
      "asnOrg": "Edgecast Inc."
    },
    "content": {
      "pageTitle": "Example Domain",
      "metaDescription": "This domain is for use in illustrative examples.",
      "language": "en",
      "forms": {
        "hasLoginForm": false,
        "requestsPersonalInfo": false,
        "hasUrgencyIndicators": false,
        "requestedInfoTypes": null
      },
      "gambling": {
        "related": false,
        "type": [],
        "confidence": 0
      },
      "adult": {
        "related": false,
        "type": [],
        "confidence": 0
      }
    },
    "trust": {
      "ssl": {
        "valid": true,
        "issuer": "Let's Encrypt",
        "issueDate": "2024-09-01T00:00:00.000Z",
        "expireDate": "2025-09-01T00:00:00.000Z",
        "ageInDays": 120
      },
      "domain": {
        "registeredAt": "1995-08-14T00:00:00.000Z",
        "expireDate": "2025-08-13T00:00:00.000Z",
        "ageInDays": 10800,
        "registrar": "IANA",
        "registrantCountry": "US",
        "status": [
          "active"
        ],
        "nameservers": [
          "a.iana-servers.net",
          "b.iana-servers.net"
        ]
      }
    },
    "insight": {
      "summary": "Legitimate website with no malicious content detected.",
      "confidence": 95,
      "riskAssessment": "LOW RISK: Official example domain maintained by IANA.",
      "keyFindings": [
        "Valid SSL certificate",
        "Long domain age",
        "No suspicious content"
      ],
      "riskFactors": [],
      "positiveIndicators": [
        "Established domain",
        "Clean reputation"
      ],
      "recommendations": [
        "Site is safe to visit"
      ]
    },
    "errorMessage": null,
    "errorCode": null,
    "retryCount": 0,
    "createdAt": "2025-01-06T10:00:00.000Z",
    "updatedAt": "2025-01-06T10:02:30.000Z",
    "completedAt": "2025-01-06T10:02:30.000Z"
  }
}'

Best Practices

1. Verify Webhook Signatures

Always verify the X-Sidex-Signature header using your webhook secret to ensure requests originate from SIDEX.

2. Handle Null Dimensions

Dimensions not included in your subscription plan will be null. Always check for null values before accessing dimension data.

3. Handle Retries Idempotently

Webhooks may be retried if delivery fails. Design your handler to idempotently process events using the scan ID and X-Sidex-Delivery-Id as unique identifiers.

4. Respond Quickly

Process webhooks asynchronously and respond with a 2xx status code immediately. Store the payload for background processing.

5. Monitor Delivery Status

In the SIDEX dashboard, monitor webhook delivery logs and retry failed deliveries from the Webhook Logs page.

For support or questions, please contact our team.