Skip to content
GitHubDiscord

Webhook (lexigram-webhook)

Webhook management for the Lexigram Framework — subscription CRUD, delivery tracking, HMAC verification, and dead-letter queue


lexigram-webhook provides outbound webhook management with subscription CRUD, fan-out delivery with exponential backoff retry, HMAC-SHA256 signing, dead-letter queue, and event bus bridge. It supports in-memory and SQL persistence backends, secret rotation with grace periods, and automatic subscription disable after consecutive failures.


Terminal window
uv add lexigram-webhook
# Optional extras
uv add "lexigram-webhook[sql]"
from lexigram import Application
from lexigram.di.module import Module, module
# Import the module from the package
from lexigram.webhook import WebhookModule
@module(imports=[WebhookModule.configure()])
class AppModule(Module):
pass
app = Application(modules=[AppModule])
if __name__ == "__main__":
app.run()

Zero-config usage: Call WebhookModule.configure() with no arguments to use defaults.

application.yaml
webhook:
store_backend: "memory"
retry_max_attempts: 5
retry_base_delay: 1.0
delivery_timeout_seconds: 30.0
signature_algorithm: "sha256"
Section titled “Option 2 — Profiles + Environment Variables (recommended)”
Terminal window
export LEX_WEBHOOK__ENABLED=true
# Environment variables for each field
from lexigram.webhook.config import WebhookConfig
from lexigram.webhook import WebhookModule
config = WebhookConfig(store_backend="memory", retry_max_attempts=5)
WebhookModule.configure(config)
FieldDefaultEnv varDescription
store_backend"memory"LEX_WEBHOOK__STORE_BACKEND"memory" or "sql" (requires [sql] extra)
retry_max_attempts5LEX_WEBHOOK__RETRY_MAX_ATTEMPTSDelivery attempts before dead-letter
retry_base_delay1.0LEX_WEBHOOK__RETRY_BASE_DELAYInitial retry delay in seconds
retry_max_delay60.0LEX_WEBHOOK__RETRY_MAX_DELAYMaximum retry delay ceiling in seconds
retry_backoff_factor2.0LEX_WEBHOOK__RETRY_BACKOFF_FACTORExponential backoff multiplier
secret_length32LEX_WEBHOOK__SECRET_LENGTHSecret bytes (hex output is 2×)
secret_rotation_grace_hours24LEX_WEBHOOK__SECRET_ROTATION_GRACE_HOURSGrace window where both old and new secrets are valid
delivery_timeout_seconds30.0LEX_WEBHOOK__DELIVERY_TIMEOUT_SECONDSHTTP request timeout per attempt
disable_after_consecutive_failures50LEX_WEBHOOK__DISABLE_AFTER_CONSECUTIVE_FAILURESAuto-disable threshold
failure_window_hours24LEX_WEBHOOK__FAILURE_WINDOW_HOURSWindow for counting consecutive failures
signature_algorithm"sha256"LEX_WEBHOOK__SIGNATURE_ALGORITHMHMAC algorithm: "sha256" or "sha512"
enable_adminTrueLEX_WEBHOOK__ENABLE_ADMINRegister the admin panel contributor
delivery_log_retention_days30LEX_WEBHOOK__DELIVERY_LOG_RETENTION_DAYSDays to retain delivery logs (0 = indefinite)
signature_header"X-Webhook-Signature"LEX_WEBHOOK__SIGNATURE_HEADERHMAC signature header name
event_type_header"X-Webhook-Event-Type"LEX_WEBHOOK__EVENT_TYPE_HEADEREvent type header name
event_id_header"X-Webhook-Event-ID"LEX_WEBHOOK__EVENT_ID_HEADEREvent ID header name
timestamp_header"X-Webhook-Timestamp"LEX_WEBHOOK__TIMESTAMP_HEADERDelivery timestamp header name
MethodDescription
WebhookModule.configure(config)Configure with explicit WebhookConfig
WebhookModule.stub()Minimal config for testing
  • Subscription CRUD — Create, list, update, deactivate webhook subscriptions
  • Secret rotation — Automatic secret generation with grace period for rotation
  • Fan-out delivery — Concurrently delivers events to all matching active subscriptions
  • Exponential backoff retry — Configurable retry attempts with exponential delay
  • Dead-letter queue — Failed deliveries after max attempts are preserved for inspection
  • Auto-disable — Subscriptions automatically deactivated after consecutive failures
  • HMAC-SHA256 signingsha256=hex_digest format, compatible with Stripe/GitHub
  • Timing-attack prevention — Uses compare_digest for constant-time signature verification
  • Event bus bridge — Forward domain events as webhook events to external consumers
  • Admin panel integration — WebhookAdminContributor for subscriptions, deliveries, DLQ
async with Application.boot(modules=[WebhookModule.configure()]) as app:
# your test code
...
FileWhat it contains
src/lexigram/webhook/module.pyWebhookModule class with factory methods
src/lexigram/webhook/di/bundle_provider.pyWebhookBundleProvider — wires webhook protocols into DI container
src/lexigram/webhook/config.pyWebhookConfig dataclass
src/lexigram/webhook/subscription/service.pyWebhookSubscriptionService — subscription CRUD with secret rotation
src/lexigram/webhook/delivery/service.pyWebhookDeliveryService — fan-out, retry, auto-disable
src/lexigram/webhook/delivery/sender.pyWebhookSender — single HTTP delivery attempt
src/lexigram/webhook/delivery/dead_letter.pyDeadLetterManager — DLQ inspection and re-queue
src/lexigram/webhook/verification/hmac.pyHMACSignatureVerifier — constant-time signature verification
src/lexigram/webhook/bridge/event_bus.pyEventBusWebhookBridge — domain event → webhook forward