Skip to main content

Webhook

Sends HTTP POST notifications to external webhooks when requests pass through the pipeline. Useful for event tracking, auditing, and integration with external monitoring systems.

Overview​

The webhook middleware operates asynchronously (fire-and-forget) to avoid blocking the request pipeline. Failed webhook deliveries are logged but do not affect request processing.

Use cases:

  • Event logging to external systems
  • Request/response auditing
  • Real-time notifications for API activity
  • Integration with monitoring or alerting platforms

Configuration​

[middleware.my_webhook]
type = "webhook"
[middleware.my_webhook.options]
endpoint = "https://webhook.example.com/events"
apply = "left" # Optional: "left", "right", or "both" (default: "left")
timeout_secs = 5 # Optional: request timeout (default: 5)
redact_headers = ["authorization", "x-api-key"] # Optional: headers to redact
redact_metadata = ["jwt_token"] # Optional: metadata to redact

Options​

OptionTypeRequiredDefaultDescription
endpointstringYes-URL to POST webhook payloads
applystringNo"left"When to fire: "left" (request), "right" (response), or "both"
timeout_secsintegerNo5HTTP timeout for webhook POST
redact_headersarrayNo[]List of header names to redact (case-insensitive)
redact_metadataarrayNo[]List of metadata keys to redact (case-insensitive)
authentication_defobjectNo-Authentication configuration for webhook endpoint

Payload Structure​

Left Side (Request)​

{
"middleware": "webhook",
"name": "my_webhook",
"side": "left",
"request": {
"method": "POST",
"uri": "/api/patients",
"headers": {
"content-type": "application/json",
"authorization": "<redacted>"
},
"cookies": {},
"query_params": {},
"metadata": {
"user_id": "123"
},
"content_metadata": {
"content_type": "application/json",
"size": 1024
}
},
"extra": null
}

Right Side (Response)​

{
"middleware": "webhook",
"name": "my_webhook",
"side": "right",
"request": {
"method": "POST",
"uri": "/api/patients",
"headers": {
"content-type": "application/json",
"authorization": "<redacted>"
},
"cookies": {},
"query_params": {},
"metadata": {
"user_id": "123"
},
"content_metadata": {
"content_type": "application/json",
"size": 1024
}
},
"extra": null
}

Behavior​

Fire-and-Forget​

Webhook POSTs are spawned as background tasks and do not block the request pipeline:

  • Requests continue immediately without waiting for webhook response
  • Webhook failures are logged but don't affect the request
  • Response latency is unaffected by webhook delivery time

Redaction​

Sensitive data can be redacted before sending to webhooks:

[middleware.audit_webhook.options]
endpoint = "https://audit.example.com/events"
redact_headers = ["authorization", "x-api-key", "cookie"]
redact_metadata = ["jwt_token", "ssn"]

Redacted values appear as "<redacted>" in the payload.

Authentication​

Webhooks can include authentication for secured endpoints:

[middleware.secure_webhook.options]
endpoint = "https://secure-webhook.example.com/events"

[middleware.secure_webhook.options.authentication_def]
type = "basic"
username = "webhook_user"
password = "webhook_password"

Supported authentication types:

  • basic - HTTP Basic authentication
  • bearer - Bearer token authentication

Extra Metadata​

You can pass custom data to webhooks via request metadata. Use the key webhook.{instance_name}:

# Middleware named "audit_webhook"
[middleware.audit_webhook]
type = "webhook"

In a transform middleware (or other middleware that sets metadata):

{
"webhook.audit_webhook": "{\"tenant\":\"acme\",\"priority\":\"high\"}"
}

This appears in the webhook payload's extra field.

Error Handling​

  • Connection failures: Logged as warnings, request continues
  • Timeouts: After timeout_secs, the webhook task terminates, request continues
  • Non-2xx responses: Logged but ignored, request continues

All errors are logged to the harmony.webhook target:

WARN harmony.webhook: webhook post failed: connection refused

Examples​

Basic Event Logging​

[pipelines.api_with_logging]
description = "API with webhook event logging"
networks = ["default"]
endpoints = ["api"]
backends = ["backend"]
middleware = ["event_logger"]

[middleware.event_logger]
type = "webhook"
[middleware.event_logger.options]
endpoint = "https://logs.example.com/events"
apply = "left"

Request and Response Auditing​

[middleware.audit_both]
type = "webhook"
[middleware.audit_both.options]
endpoint = "https://audit.example.com/api/events"
apply = "both"
redact_headers = ["authorization"]
timeout_secs = 10

Authenticated Webhook​

[middleware.secure_notification]
type = "webhook"
[middleware.secure_notification.options]
endpoint = "https://secure.example.com/notify"
apply = "right"

[middleware.secure_notification.options.authentication_def]
type = "bearer"
token = "${WEBHOOK_TOKEN}"

Response-Only Webhook​

[middleware.response_tracker]
type = "webhook"
[middleware.response_tracker.options]
endpoint = "https://metrics.example.com/responses"
apply = "right"

Performance Considerations​

  • Webhook POSTs are non-blocking and run in background tasks
  • No impact on request latency (unless webhook blocks due to middleware order - always configure appropriately)
  • Failed webhooks do not retry automatically
  • For high-throughput systems, consider webhook endpoint capacity