Honeypot Webhooks: Send Attack Detections to Any API
The ReportedIP honeypot server can now push every attack it catches into whatever tooling you already run. Version 1.3.0 turns its webhooks into a configurable router — choose the HTTP method, headers, and body, and post detections straight to your SIEM, Slack, Discord, or AbuseIPDB.
If you are already running a honeypot node, update to 1.3.0 and configure an endpoint in the admin panel. The full setup is documented in the honeypot server documentation.
What honeypot webhooks do
A webhook is an HTTP(S) endpoint that receives a request every time the honeypot flags an attack. The feature first shipped in 1.2.0 to forward detections to the ReportedIP community API and external collectors. With 1.3.0 the same detections can fan out to any HTTP API — Splunk, Elastic, a Slack or Discord channel, or a second threat database.
Delivery happens after the trap response has already been sent to the attacker, so adding a webhook never slows the honeypot down. Each of the 36 built-in analyzers — SQL injection, XSS, path traversal, brute force and the rest — can trigger one. When a single request trips several analyzers, the detections are aggregated into one delivery with merged categories and the highest severity.
Route detections to any API, not just ReportedIP
This is the headline change in 1.3.0. A webhook is no longer locked to a fixed JSON shape. Each endpoint now defines its own request, so it can speak whatever the target API expects:
- HTTP method —
POST,PUT,PATCH, orGET. - Custom headers — one per line, for API keys and auth; they override the defaults.
- Body format — structured
json, URL-encodedform, or a free-form custom template. - Placeholders —
{{ip}},{{categories}},{{severity}},{{timestamp}}and the other request and detection fields, each with a{{..._url}}(URL-encoded) and{{..._json}}(JSON-escaped) variant.
Built-in AbuseIPDB mapping
Reporting to a second database used to mean writing a translation layer, because every service numbers its threat categories differently. 1.3.0 ships a dedicated {{abuseipdb_categories}} placeholder that maps ReportedIP categories (IDs 24–58) to their nearest AbuseIPDB IDs. A direct report to the AbuseIPDB v2 API becomes a one-line body template:
POST https://api.abuseipdb.com/api/v2/report
Header: Key: <your-abuseipdb-api-key>
Body (form): ip={{ip}}&categories={{abuseipdb_categories}}&comment={{comment_url}}
Presets for AbuseIPDB, Slack, Discord, and a generic JSON target pre-fill the method, headers, and body — pick one, drop in your key or URL, and send a test. Test deliveries use the loopback IP 127.0.0.1, so verifying an AbuseIPDB webhook never files a real report against a live address.
How to set up a webhook
Webhooks are managed in the admin panel under Webhooks, stored in a honeypot_webhooks table that the schema migration extends automatically. Three controls decide what each endpoint receives:
- Category filters — restrict delivery to specific threat category IDs, mapped to the same threat categories used across ReportedIP.
- Analyzer filters — restrict delivery to named detection engines, for example
SqlInjection. - Secret key — optional; turns on HMAC-SHA256 signing of the payload.
Empty filters mean every detection is delivered. When both filters are set, the webhook fires when either one matches. The admin panel tracks the last result, timestamp, and a consecutive-failure counter per endpoint, so a broken target is obvious at a glance.
The default JSON payload
If you keep the JSON body format, each request carries Content-Type: application/json, an X-ReportedIP-Event header (detection or test), and — when a secret is set — an X-ReportedIP-Signature header. The body groups the honeypot, the request, and one or more detections:
{
"event": "detection",
"generated_at": "2026-06-12T14:00:00+00:00",
"honeypot": {
"name": "reportedip-honeypot-server",
"version": "1.3.0",
"host": "your-honeypot.example.com",
"profile": "wordpress"
},
"request": {
"ip": "203.0.113.50",
"method": "POST",
"uri": "/wp-login.php",
"user_agent": "sqlmap/1.7"
},
"detections": [
{
"analyzer": "SqlInjection",
"categories": [16, 45],
"category_names": ["SQL Injection", "Code Injection"],
"comment": "SQL injection attempt detected: ...",
"severity": 85
}
]
}
Verifying the signature
When a secret is configured, the signature is an HMAC-SHA256 over the raw request body, sent as sha256=<hmac>. Compute the same value on your side and compare it in constant time:
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
$valid = hash_equals($expected, $_SERVER['HTTP_X_REPORTEDIP_SIGNATURE'] ?? '');
This is the same pattern GitHub and Stripe use for their webhooks, so existing receiver code is easy to adapt. Always hash the raw bytes before any JSON parsing, otherwise re-serialization will change the signature.
Why this matters for SOC and homelab operators
A honeypot only earns its keep if someone sees what it catches. Forcing operators to log into a separate dashboard meant honeypot detections lived apart from every other security signal. Flexible webhooks close that gap: attacks land in the same pane of glass as your firewall, WAF, and application logs, with structured fields you can correlate, alert on, or forward to a blocklist — and now to a second reputation database in the same step.
It also fits how people already run these nodes. If you protect a fleet of servers — the kind of setup described in securing a server cluster with ReportedIP — a webhook lets a single honeypot feed a central collector that the rest of the cluster reads from.
Update notes: 1.2.0 to 1.3.0
All three releases shipped on 12 June 2026. 1.2.0 introduced webhooks and fixed Cloudflare IPv6 detection, a HeaderAnomaly false positive on legitimate IPv6 addresses, and report-queue handling of permanent API rejections.
1.2.1 followed as a hotfix: a missing autoloader entry caused an HTTP 500 on the Webhooks admin page right after updating. 1.3.0 then rebuilt the webhook layer into the flexible router described above, added the AbuseIPDB mapping and presets, merged multiple detections per request, and grew the test suite to 363 tests. If you are on any earlier build, go straight to 1.3.0.
FAQ
Can the honeypot report to AbuseIPDB?
Yes. Use the AbuseIPDB preset, or build a webhook with the form body format and the {{abuseipdb_categories}} placeholder, which maps ReportedIP categories to AbuseIPDB IDs. Add your AbuseIPDB key as a custom header and the honeypot posts straight to the v2 report endpoint.
Do webhooks slow down the honeypot?
No. The request is sent after the trap response has already gone back to the attacker, so what the attacker sees is never delayed by webhook delivery.
How do I know a payload really came from my honeypot?
Set a secret on the webhook. Every request then carries an X-ReportedIP-Signature header containing an HMAC-SHA256 of the raw body. Recompute it with your secret and compare in constant time before trusting the payload.
Get the honeypot server
The honeypot server is open source (BSL 1.1, converting to Apache 2.0 in 2030) and ships zero external dependencies — PHP 8.2, SQLite, done.
- Read the honeypot server docs — install, configure, and the full webhook reference.
- View the 1.3.0 release on GitHub — changelog and source.
- Turn detections into a blocklist — feed the community blacklist into your edge.