Receive. Validate. Queue. Deliver.

Next-Gen Webhook
Execution Engine

Hookwal is an ultra-fast, secure, self-hosted single binary that transforms incoming webhooks and forms into reliable database actions, email notifications, and API triggers. No external message queue brokers required.

hookwald ~ daemon logs
[01:10:45.021] Initializing SQLite persistence layer...
[01:10:45.023] Scanning schema migrations: status_ok
[01:10:45.025] Hook endpoints loaded dynamically from database
[01:10:45.026] Background execution worker initialized (workers=8)
[01:10:45.028] SSRF Private Subnet blocker active on outbound requests

Core Capabilities

Hardened out-of-the-box mechanisms for enterprise reliability.

Dynamic Rate Limiting

Prevents payload floods by applying customizable rate caps (limit & window size) stored dynamically per-hook in the database.

Advanced Validation

Strict schema validations. Enforces nested key structures, minimum/maximum lengths, email pattern validations, and rejects payload pollution.

SSRF Defense Shield

A custom dialing context locks outbound actions, blocking private IP ranges, loopbacks, DNS-rebinding cheats, and redirects to secure subnets.

Ingress Anti-Spam

Combats spam using smart honeypot fields for silent bot rejection and natively supports Cloudflare Turnstile & Google reCAPTCHA checks.

HMAC Cryptography

Verifies incoming calls and cryptographically signs outbound HTTP calls with HMAC-SHA256 signatures for recipient verification.

Replay Engine & Tracing

Features a manual event replay API. Duplicates failed plans and maintains lineage tracking via parent-child relations.

Introduction

Hookwal is a secure, single-binary webhook ingestion and automation tool written in Go.

It processes incoming forms and payloads, validates them against JSON schemas, verifies CAPTCHA tokens, and queues them into a transaction-safe SQLite database. A background worker picks up the events, runs database insertions, triggers emails, or issues outbound HTTP calls with exponential backoff retries.

💡
Standalone Architecture: Hookwal does not require Redis or external task queues. SQLite handles the locking and scheduling of jobs transactionally.

Configuration File

Hookwal reads configurations from a local config.toml file. Below are the supported keys:

# Hookwal configuration template
port = "8080"
db_path = "hookwal.db"
admin_token = "super-secret-admin-token"
master_key = "32-byte-hexadecimal-key-for-credentials-encryption"
max_body_size = 1048576       # 1MB limit in bytes
allow_private_ips = false      # Enforce SSRF blocking

POST /hook/{token}

Ingests JSON payloads for a specific webhook. Validates schemas, HMAC signature keys, and rate limits.

POST /hook/{token}

Headers

Content-Type Must be application/json
Idempotency-Key Optional. Prevents double execution.
X-Signature Optional. HMAC key signature.

Interactive Code Snippet

curl -X POST http://localhost:8080/hook/token_ad88bae856b224abcc8676adff58b825 \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: idemp_123" \
  -d '{
    "name": "Alex",
    "email": "alex@binlogic.com",
    "message": "Scale check"
  }'
fetch('http://localhost:8080/hook/token_ad88bae856b224abcc8676adff58b825', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Idempotency-Key': 'idemp_123'
  },
  body: JSON.stringify({
    name: 'Alex',
    email: 'alex@binlogic.com',
    message: 'Scale check'
  })
})
.then(res => res.json())
.then(data => console.log(data));
package main

import (
	"bytes"
	"net/http"
)

func main() {
	payload := []byte(`{"name": "Alex", "email": "alex@binlogic.com"}`)
	req, _ := http.NewRequest("POST", "http://localhost:8080/hook/token_ad88bae856b224abcc8676adff58b825", bytes.NewBuffer(payload))
	req.Header.Set("Content-Type", "application/json")
	
	client := &http.Client{}
	client.Do(req)
}

POST /form/{token}

Ingests URL-encoded static form data. Filters bots through honeypots and validates CAPTCHAs before scheduling executions.

POST /form/{token}

HTML Integration Boilerplate

<!-- Hookwal public form integration -->
<form action="http://localhost:8080/form/token_ad88bae856b224abcc8676adff58b825" method="POST">
  <!-- Hidden Honeypot Input -->
  <input type="text" name="bot-field" style="display:none" autocomplete="off" />

  <label>Name</label>
  <input type="text" name="name" required />

  <label>Email</label>
  <input type="email" name="email" required />

  <!-- Cloudflare Turnstile token container -->
  <div class="cf-turnstile" data-sitekey="your-site-key"></div>

  <button type="submit">Send Message</button>
</form>

POST /admin/hooks

Registers a new webhook endpoint. Protect with Bearer token authentication.

POST /admin/hooks Admin Token

Request Payload Schema

{
  "name": "Contact Lead Form",
  "allowed_domains": ["binlogic.com"],
  "honeypot_field": "bot-field",
  "captcha_secret": "0xMockSecretKey",
  "rate_limit_limit": 10,
  "rate_limit_window_ms": 60000,
  "validation_schema": "{\"email\":{\"type\":\"string\",\"required\":true,\"format\":\"email\"}}",
  "actions": [
    {
      "type": "postgres_insert",
      "config": "{\"credentials_id\": \"conn_supabase\", \"table\": \"leads\"}"
    }
  ]
}

POST /admin/events/{id}/replay

Triggers a manual replay of a previously stored event, cloning payload inputs and scheduling brand new executions.

POST /admin/events/{id}/replay Admin Token

Successful Response (201 Created)

{
  "status": "queued",
  "event_id": "event_new_replay_12345",
  "parent_event_id": "event_original_failed_9988"
}

GET /admin/jobs/{id}

Inspects execution records and outputs for a specific event pipeline.

GET /admin/jobs/{id} Admin Token

Health Checks & Metrics

Hookwal provides diagnostic routes for system state visibility:

GET /health/live

Confirms runtime binary execution. Returns 200 OK.

GET /health/ready

Confirms SQLite connection and write-read viability. Returns 200 OK or 503 Service Unavailable.

GET /metrics

Exposes real-time Prometheus statistics on request volume, queue depths, execution latencies, and worker pools.

Hookwal Architecture

A resilient pipeline engineered for security, concurrency, and audit transparency.

Live Event Pipeline Visualizer

Animate dynamic event ingestion and queue scheduling flows.

🌐
HTTP Ingest
🛡️
Rate & Spam Guard
JSON Validator
💾
SQLite Queue
⚙️
Worker Pipeline
🚀
SSRF-Protected Target

SQLite Schema Blueprint

Explore relational database configurations and audit tables.

Column Type Constraints Description
id TEXT PRIMARY KEY Unique webhook identifier (e.g. hook_e1bb5ace...).
name TEXT NOT NULL Friendly name of the webhook path.
token TEXT UNIQUE Secure path token prefix used in HTTP routes.
allowed_origins TEXT - JSON array of whitelisted origin domain strings.
validation_schema TEXT - JSON Schema validation constraints.
honeypot_field TEXT - Hidden field name criteria for anti-bot spam.
captcha_secret TEXT - Verify token key for Turnstile/reCAPTCHA.
rate_limit_limit INTEGER DEFAULT 60 Dynamic request limit in a given time window.
rate_limit_window_ms INTEGER DEFAULT 60000 Dynamic window duration in milliseconds.
Column Type Constraints Description
id TEXT PRIMARY KEY Unique identifier mapping (e.g. event_8044955c...).
webhook_id TEXT REFERENCES webhooks(id) Target webhook configuration ID mapping.
payload TEXT NOT NULL Raw incoming request JSON payload.
headers TEXT - JSON formatted string of processed headers.
idempotency_key TEXT - Unique key to avoid double-processing.
status TEXT NOT NULL queued, running, succeeded, retry_scheduled, dead_letter.
parent_event_id TEXT - Lineage tracking pointer referencing original replayed event.
Column Type Constraints Description
id TEXT PRIMARY KEY Unique action identifier mapping.
webhook_id TEXT REFERENCES webhooks(id) Link to parent webhook configuration.
type TEXT NOT NULL Action class: postgres_insert, send_email, http_request.
position INTEGER NOT NULL Sequential sorting index for pipelined actions.
config TEXT - JSON configuration parameters for the action template.
Column Type Constraints Description
id TEXT PRIMARY KEY Unique run execution ID (exec_...).
event_id TEXT REFERENCES events(id) Pointer to the processed event metadata.
attempt INTEGER DEFAULT 1 Current retry count (capped by max_attempts).
status TEXT NOT NULL queued, running, succeeded, failed, retry_scheduled.
error_code TEXT - Standard internal classified error reference code.
sanitized_error TEXT - Sanitized user-facing error message description.
output TEXT - Returned output response from target server/database.
Column Type Constraints Description
id TEXT PRIMARY KEY Unique credentials key mapping (e.g. conn_smtp).
type TEXT NOT NULL Credential class type mapping.
encrypted_data TEXT NOT NULL AES-GCM-256 encrypted base64 payload data string.