Skip to main content
app.webhook() lets you receive messages through HTTP POST requests instead of the app.messages stream. It handles two webhook formats through the same method: Detection is by payload shape (JSON vs protobuf), not headers. Your handler receives the same (space, message) pair either way.

Configuring a webhook secret

Native Spectrum webhooks require a signing secret for HMAC verification. Pass it to Spectrum():
The webhookSecret option can also be supplied via the SPECTRUM_WEBHOOK_SECRET environment variable (the explicit option takes precedence). A native delivery that arrives without a configured secret is answered 500.

Receiving deliveries

Call app.webhook() from your HTTP server’s POST route. The method has two overloads:
The handler is invoked fire-and-forget — it runs after the HTTP response is sent. A throw is logged, never surfaced. Dedupe on message.id for exactly-once side effects.
Pass the raw body bytes. The HMAC is computed over the exact bytes on the wire. If your framework parses the body to JSON and you re-stringify it, the bytes change and verification fails.

Framework adapters

First-party adapters mount the endpoint for you and handle raw-body parsing correctly. Install the adapter package and its framework only when you use it.

What the SDK handles

  • Signature verification. Native webhooks are verified with HMAC-SHA256 over v0:<timestamp>:<rawBody>, with a 5-minute replay window. Bad signature returns 401, missing headers return 400.
  • Payload deserialization. Native webhook JSON is deserialized into normal and objects, including reactions and grouped items.
  • Attachment rehydration. Native webhooks carry attachment metadata only. read() and stream() fetch the bytes lazily via the platform.
  • Format detection. Native vs Fusor is detected per request by payload shape — JSON for native, protobuf for Fusor.

Delivery semantics

app.webhook() is stateless and request-scoped — it does not feed app.messages, and it never opens the streaming connection. Both formats deliver at-least-once, so dedupe on message.id for exactly-once side effects. For more on Spectrum’s webhook delivery model, see the Webhooks documentation.