Search Stream Webhooks
Real-time delivery of phishing candidates and brand infringements directly to your security stack via high-availability webhooks.
The primary method for ingestion is a Webhook. We send a JSON payload via an HTTP POST request to a URL you configure in your portal.
Endpoint Requirements
- Accept HTTP POST requests.
- Accept
application/json. - Return 200 OK within 5 seconds.
- Be publicly accessible (or allowlist our egress IPs).
Retry Logic
If we don't receive a 200 OK, we attempt delivery 3 times with exponential backoff:
Since webhooks receive raw threat data, it is critical to verify requests originate from Datazag.
Signature Verification Required
Every request includes a X-SearchStream-Signature header. This is an HMAC-SHA256 hash of the raw request body.
IP Allowlisting Optional
Restrict traffic to our egress IPs for additional network security.
Caution for Developers
Do not rely solely on payload content. Always verify the signature against the **raw** request body before any middleware modifications (like JSON parsing) to prevent tampering.
Verify the signature using your unique Signing Secretavailable in your dashboard.
const crypto = require('crypto');
const SIGNING_SECRET = process.env.SEARCH_STREAM_SECRET;
function verifySignature(req) {
const signature = req.headers['x-searchstream-signature'];
if (!signature) return false;
const hmac = crypto.createHmac('sha256', SIGNING_SECRET);
const digest = hmac.update(req.rawBody).digest('hex');
const signatureBuffer = Buffer.from(signature);
const digestBuffer = Buffer.from(digest);
return (
signatureBuffer.length === digestBuffer.length &&
crypto.timingSafeEqual(signatureBuffer, digestBuffer)
);
}Example Payload
{
"alert_id": "evt_889234-ab12-44c1",
"timestamp": "2023-10-27T14:30:00Z",
"event_type": "phishing_candidate_detected",
"severity": "high",
"brand_monitored": "Acme Corp",
"threat_data": {
"url": "http://login-acmecorp-secure.com.badsite.net",
"domain": "badsite.net",
"ip_address": "203.0.113.45",
"asn": "AS12345 Example ISP",
"screenshot_url": "https://api.yourbrand.com/screenshots/123.png"
},
"detection_logic": {
"score": 95,
"triggers": [
"logo_match",
"keyword_stuffing",
"newly_registered_domain"
]
}
}Field Reference
| Field | Type | Description |
|---|---|---|
alert_id | string | Unique UUID for this event. Use this for deduplication in your SIEM. |
timestamp | string | ISO 8601 timestamp (UTC) of when the detection occurred. |
event_type | string | The classification of the event (e.g., phishing_candidate_detected). |
severity | string | Normalized risk level: low, medium, high, or critical. |
threat_data.url | string | The full URL where the threat was detected. |
threat_data.ip_address | string | The hosting IP address of the malicious site. |
detection_logic.score | integer | A confidence score from 0-100 indicating the likelihood of phishing. |
Structured Email Alerts
If your environment cannot support webhooks, we deliver structured alerts via email. This is common for legacy ticketing systems or manual security review.
Format
Multipart MIME (Text summary + .json attachment)
Subject
[Alert] Phishing Candidate Detected: <Domain> - <Level>
| Issue | Likely Cause | Solution |
|---|---|---|
| Signature Mismatch | Hashing parsed JSON instead of raw bytes. | Ensure your code reads the request body before any JSON parsing middleware runs. |
| 403 Forbidden | Firewall blocking our IPs. | Whitelist 192.0.2.10 and 192.0.2.11 on your WAF or firewall. |
| Timeouts / 5xx | Slow processing on your end. | Your endpoint must respond within 5 seconds. Offload heavy processing to a background job. |
| Duplicate Events | Retry logic. | If we don't receive a 200 OK, we retry 3 times. Ensure your system checks alert_id to handle duplicates. |
Integration Testing
You can trigger a manual test event from your dashboard at any time to verify your endpoint setup.