@molecule/api-channel-messenger
v1.0.2
Published
Facebook Messenger channel bond — implements @molecule/api-channel for sendMessage via the Send API, X-Hub-Signature-256 webhook verification, and inbound entry/messaging parsing.
Readme
@molecule/api-channel-messenger
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.tsJSDoc, not this file.
Facebook Messenger channel provider for molecule.dev.
Implements the framework-agnostic {@link ChannelProvider} interface
over the Messenger Send API and webhook envelope. Bond under the
named-multi-provider 'channel' category at app startup:
Quick Start
import { setProvider } from '@molecule/api-channel'
import { provider } from '@molecule/api-channel-messenger'
setProvider('messenger', provider)Type
provider
Installation
npm install @molecule/api-channel-messenger @molecule/api-channel @molecule/api-secretsAPI
Interfaces
MessengerActor
Subset of the Messenger Sender/Recipient shape used during inbound
normalization.
interface MessengerActor {
/** Page-scoped user identifier. */
id: string
}MessengerConfig
Configuration for the Messenger channel provider.
The page access token authorizes Send API calls; the app secret signs
inbound webhooks via X-Hub-Signature-256. Both are deliberately
accepted only via this config (or the CHANNEL_MESSENGER_PAGE_ACCESS_TOKEN
/ CHANNEL_MESSENGER_APP_SECRET env vars) and are NEVER included in
error messages, log lines, or normalized payloads.
interface MessengerConfig {
/**
* Page access token (`EAA…`). Required for outbound `sendMessage`.
* Defaults to the `CHANNEL_MESSENGER_PAGE_ACCESS_TOKEN` env var.
*
* Treat as a secret — providers redact this value in any user-facing
* output.
*/
pageAccessToken?: string
/**
* Facebook app secret used to verify `X-Hub-Signature-256` on inbound
* webhook requests. Defaults to the `CHANNEL_MESSENGER_APP_SECRET` env
* var.
*
* If unset, {@link MessengerChannelProvider.verifyWebhookSignature}
* returns `false`.
*/
appSecret?: string
/**
* Graph API base URL. Override only for tests or alternative regional
* endpoints. Defaults to `https://graph.facebook.com`.
*/
apiBaseUrl?: string
/**
* Graph API version to target. Defaults to `'v22.0'`.
*/
apiVersion?: string
/**
* Per-request timeout in milliseconds. Defaults to 10000.
*/
timeoutMs?: number
/**
* Optional default `messaging_type` applied to outbound sends. Defaults
* to `'RESPONSE'` (replies to user-initiated conversations within the
* 24-hour window). Override to `'UPDATE'` or `'MESSAGE_TAG'` when
* sending unsolicited messages — note the Messenger Platform policy
* restrictions.
*/
defaultMessagingType?: MessengerMessagingType
}MessengerInboundAttachment
Subset of an inbound Messenger attachment object.
interface MessengerInboundAttachment {
/** Attachment kind (`'image'`, `'video'`, `'audio'`, `'file'`, …). */
type?: string
/** Optional payload object — typically `{ url }`. */
payload?: { url?: string; sticker_id?: number }
}MessengerInboundDelivery
Subset of an inbound Messenger delivery object.
interface MessengerInboundDelivery {
/** Mids of the messages confirmed delivered. */
mids?: string[]
/** Watermark — all messages sent before this timestamp are delivered. */
watermark?: number
}MessengerInboundMessage
Subset of an inbound Messenger message object.
interface MessengerInboundMessage {
/** Provider-assigned message identifier (mid). */
mid?: string
/** Plain-text body. */
text?: string
/** Quick-reply payload, when the user clicked a quick reply. */
quick_reply?: { payload?: string }
/** Attachments (images, files, …) included with the message. */
attachments?: MessengerInboundAttachment[]
/** Whether the message was an echo of one this app sent. */
is_echo?: boolean
}MessengerInboundPostback
Subset of an inbound Messenger postback object — the payload returned
when a user taps a button on a button_template or persistent menu.
interface MessengerInboundPostback {
/** Opaque payload originally set on the button. */
payload?: string
/** Visible title shown on the button when it was tapped. */
title?: string
}MessengerInboundRead
Subset of an inbound Messenger read object.
interface MessengerInboundRead {
/** Watermark — all messages sent before this timestamp are read. */
watermark?: number
}MessengerMessagingEntry
A single messaging entry inside an inbound webhook envelope.
interface MessengerMessagingEntry {
/** Sender of the inbound event. */
sender?: MessengerActor
/** Recipient (typically the page receiving the event). */
recipient?: MessengerActor
/** Unix timestamp in milliseconds. */
timestamp?: number
/** Inbound user message. */
message?: MessengerInboundMessage
/** Inbound button-tap postback. */
postback?: MessengerInboundPostback
/** Delivery confirmation. */
delivery?: MessengerInboundDelivery
/** Read receipt. */
read?: MessengerInboundRead
}MessengerSendApiResponse
Successful Send API response shape used by the provider.
interface MessengerSendApiResponse {
/** Page-scoped recipient identifier (echoed). */
recipient_id?: string
/** Messenger-assigned outbound message id. */
message_id?: string
}MessengerWebhookEntry
A single entry inside an inbound webhook envelope.
interface MessengerWebhookEntry {
/** Page identifier the events belong to. */
id?: string
/** Unix timestamp in milliseconds. */
time?: number
/** Per-conversation events. Typically a single-element array. */
messaging?: MessengerMessagingEntry[]
}MessengerWebhookPayload
Top-level Messenger webhook envelope.
interface MessengerWebhookPayload {
/** Always `'page'` for Messenger Platform webhooks. */
object?: string
/** Per-page event groups. */
entry?: MessengerWebhookEntry[]
}ProcessEnv
Environment variables consumed by the Messenger channel provider.
interface ProcessEnv {
/** Page access token (`EAA…`). Required for outbound sends. */
CHANNEL_MESSENGER_PAGE_ACCESS_TOKEN: string
/** Facebook app secret used to verify inbound webhook signatures. */
CHANNEL_MESSENGER_APP_SECRET: string
}Types
MessengerMessagingType
Messenger messaging_type values accepted on the Send API.
type MessengerMessagingType = 'RESPONSE' | 'UPDATE' | 'MESSAGE_TAG'Classes
MessengerChannelProvider
Concrete Messenger Platform implementation of {@link ChannelProvider}.
Functions
createProvider(config)
Convenience factory for the named-multi-provider bond pattern.
function createProvider(config?: MessengerConfig): MessengerChannelProviderconfig— Optional Messenger config.
Returns: A new {@link MessengerChannelProvider} instance.
Constants
channelMessengerSecretDefinitions
Secret definitions required by the Messenger channel bond.
const channelMessengerSecretDefinitions: SecretDefinition[]provider
Lazily-instantiated singleton instance for app-startup wiring. Reads configuration from environment variables on first use.
const provider: ChannelProviderCore Interface
Implements @molecule/api-channel interface.
Injection Notes
Requirements
Peer dependencies:
@molecule/api-channel^1.0.1@molecule/api-secrets^1.0.1
Environment Variables
CHANNEL_MESSENGER_PAGE_ACCESS_TOKEN(required) — Messenger page access token- Setup: Create a Meta app with the Messenger product and generate a Page access token for your page.
- Get it here: https://developers.facebook.com/apps
CHANNEL_MESSENGER_APP_SECRET(required) — Meta app secret- Setup: Your Meta app → App settings → Basic → App secret.
- Get it here: https://developers.facebook.com/apps
Runtime Dependencies
@molecule/api-channel@molecule/api-secretsWebhook subscription needs a GET echo the bond does not provide. When you register the webhook URL in the Meta console, Meta first sends
GET ?hub.mode=subscribe&hub.verify_token=<your token>&hub.challenge=<n>. Your route must check the verify token you chose in the console and respond200with the rawhub.challengevalue. Only POST deliveries go throughverifyWebhookSignature()/parseInbound().24-hour messaging window: outside 24h since the user's last message, the Send API rejects standard sends — Meta requires an approved message tag for out-of-window messages. Expect and surface that API error.
E2E Tests
Integration checklist — drive the real UI (live preview, no mocks), adapt each item to this app's actual screens/flows, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip:
- [ ] Each channel-notifying flow the app defines (a Slack/Discord alert on
a new order, a status-change message) actually produces a message. The
sandbox CAPTURES channel messages instead of sending — read them with the
read_activitytool (filter type 'channel'); never mock the flow or modify production code to expose the message. - [ ] The captured message targets the configured channel/provider name and
carries the app's real content (readable text, no
undefinedplaceholders, no secrets). - [ ] A failed send (unbonded or misconfigured provider) is visible in logs/UI — never silently swallowed.
