← All @molecule/* packages · App templates

@molecule/api-notifications-webhook

Provider bond · notifications · API (Node) · v1.0.1 · Apache-2.0

HTTP webhook notification provider

npm install @molecule/api-notifications-webhook

npm · Source on GitHub · Implements @molecule/api-notifications

How it works

@molecule/api-notifications-webhook is a provider bond on the API (Node) side: it implements the notifications core interface (@molecule/api-notifications) with a concrete vendor or library behind it.

Your code calls the core; you wire this provider once at startup. Swapping vendors later is one line in that wiring, not a rewrite.

import { setProvider } from '@molecule/api-notifications'
import { provider } from '@molecule/api-notifications-webhook'

setProvider('webhook', provider)

Works with: @molecule/api-notifications, @molecule/api-secrets

Secrets: NOTIFICATIONS_WEBHOOK_URL, NOTIFICATIONS_WEBHOOK_SECRET (optional)

Reference

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

Webhook notifications provider for molecule.dev.

Sends notifications as HTTP POST requests with optional HMAC signing.

Quick Start

import { setProvider } from '@molecule/api-notifications'
import { provider } from '@molecule/api-notifications-webhook'

setProvider('webhook', provider)

Type

provider

Installation

npm install @molecule/api-notifications-webhook @molecule/api-notifications @molecule/api-secrets

API

Interfaces

ProcessEnv

Environment variables consumed by the webhook notifications provider.

interface ProcessEnv {
  NOTIFICATIONS_WEBHOOK_URL: string
  NOTIFICATIONS_WEBHOOK_SECRET?: string
}

WebhookConfig

Configuration for the webhook notifications provider.

interface WebhookConfig {
  /** The webhook URL to POST to. Defaults to NOTIFICATIONS_WEBHOOK_URL env var. */
  url?: string
  /** Optional HMAC secret for request signing. Defaults to NOTIFICATIONS_WEBHOOK_SECRET env var. */
  secret?: string
  /** Request timeout in milliseconds. Defaults to 10000. */
  timeoutMs?: number
}

Functions

createProvider(config)

Creates a webhook notifications provider.

function createProvider(config?: WebhookConfig): NotificationsProvider
  • config — Optional configuration.

Returns: A NotificationsProvider that sends via HTTP webhook.

Constants

notificationsWebhookSecretDefinitions

Secret definitions required by the webhook notifications bond.

const notificationsWebhookSecretDefinitions: SecretDefinition[]

provider

The provider implementation.

const provider: NotificationsProvider

Core Interface

Implements @molecule/api-notifications interface.

Injection Notes

Requirements

Peer dependencies:

  • @molecule/api-notifications ^1.0.1
  • @molecule/api-secrets ^1.0.1

Environment Variables

  • NOTIFICATIONS_WEBHOOK_URL (required) — Notification webhook URL
    • Setup: HTTPS endpoint that receives notification POSTs from your app.
    • Example: https://example.com/hooks/notify
  • NOTIFICATIONS_WEBHOOK_SECRET (optional) — Notification webhook signing secret
    • Auto-generated at scaffold — no manual setup.

Runtime Dependencies

  • @molecule/api-notifications
  • @molecule/api-secrets

Wire format: the POST body is { subject, body, timestamp, metadata }metadata is nested under its own key (never spread at the top level), so a Notification.metadata object can safely use keys like subject/body/timestamp without colliding with the canonical envelope fields the receiver (and the HMAC signature, when a secret is configured) depends on.

  • Signature (when a secret is configured): the POST carries X-Signature-256: sha256=<hex> where <hex> is the HMAC-SHA256 of the EXACT raw JSON body, keyed by NOTIFICATIONS_WEBHOOK_SECRET (or config.secret). Receivers must compute the HMAC over the raw request bytes BEFORE parsing (a re-serialized body will not match) and compare timing-safely. No secret → no header.
  • send() never throws — it fails open. Missing URL, non-2xx, or timeout (default 10 s) resolve to { success: false, error }; check result.success when delivery matters.
  • URL/secret/timeout are captured on first use (lazy) and frozen — env changes after the first send require a restart or a fresh createProvider() instance.

E2E Tests

Integration checklist — drive the real flow (no mocks), adapt each item to this app's actual events/triggers, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip:

  • Each ops/event trigger the app defines (service down, new signup, a threshold crossed) actually calls notifyAll() and the message reaches every bonded channel. The sandbox CAPTURES outbound notifications instead of sending — read them with the read_activity tool and confirm the subject+body match the event that fired. Never mock the flow or modify production code to expose it.
  • MULTI-CHANNEL: with >1 channel bonded, notifyAll() returns one NotificationResult per channel and a single channel failing (success: false) does not swallow the others — every other channel still captured, its own result still success: true.
  • The body carries the real event data (no undefined placeholders) and nothing that must not leave the system — no secrets, tokens, or PII that an external channel (Slack/webhook) should never receive.
  • Triggers are not end-user SPAMMABLE — no public endpoint lets a caller fire unbounded notifications; the trigger is internal (an ops/system event) or rate-limited.