Feature: Webhooks
Relevant source files
The following files were used as context for generating this wiki page:Webhooks are an advanced, production-ready feature in MessageJS designed to provide real-time notifications about the status of messages after they have been sent. When a message's state changes (e.g., from sent to delivered or failed), the third-party provider (like Twilio or WhatsApp) can call a specific URL on the MessageJS server to update the message log. This allows for a complete, end-to-end view of the message lifecycle.
This functionality is mentioned as a key feature for production environments and advanced usage. The underlying data models are built to support these status updates, enabling robust tracking and analytics.
Sources: README.md:17, QUICK_START.md:131
Architecture for Status Updates
The MessageJS system is architected to receive asynchronous status updates from external messaging providers. The core of this design is the MessageLog data model, which acts as the single source of truth for a message's journey. When a provider sends a webhook, the MessageJS backend is responsible for parsing the payload, identifying the corresponding message using its externalMessageId, and updating its status in the database.
The following diagram illustrates the general data flow for a webhook status update.
This diagram shows how a message is first sent and later updated via a webhook call from the third-party provider.
Sources: packages/core/prisma/schema.prisma:73-89, README.md:41
Data Model Support
The database schema is explicitly designed to accommodate status updates from webhooks. The MessageLog table in the Prisma schema contains fields essential for tracking the message lifecycle.
Sources: packages/core/prisma/schema.prisma, packages/core/src/types/dataModels.ts
MessageLog Model
The MessageLog model includes several fields that are populated or updated by webhook events.
| Field | Type | Description |
|---|---|---|
id | String | The internal unique identifier for the message log. |
status | MessageStatus | The current lifecycle status of the message (e.g., QUEUED, SENT, DELIVERED). This is the primary field updated by webhooks. |
externalMessageId | String? | The unique ID from the third-party provider. This is used to map an incoming webhook event to the correct MessageLog entry. |
error | String? | Stores the error message if the status becomes FAILED or UNDELIVERED. |
timestamp | DateTime | The creation timestamp of the log entry. |
deliveredAt | Date? | A timestamp indicating when the message was delivered, which would be set by a delivered status webhook. |
Sources: packages/core/prisma/schema.prisma:73-89, packages/core/src/types/dataModels.ts:91-106
Message Status Lifecycle
The MessageStatus enum defines the possible states a message can be in. Webhooks are the mechanism that transitions a message from an initial state like SENT to a terminal state like DELIVERED or FAILED.
This diagram shows the possible state transitions for a message, many of which are triggered by webhook events.
The defined statuses are:
- QUEUED: The message has been accepted by the MessageJS API but not yet processed.
- SENT: The message has been successfully dispatched to the third-party provider.
- DELIVERED: The provider has confirmed the message was successfully delivered to the end-user's device.
- FAILED: The message failed to send from the MessageJS system or was rejected by the provider.
- UNDELIVERED: The provider confirmed the message could not be delivered to the recipient.
Sources: packages/core/prisma/schema.prisma:26-32, packages/core/src/types/dataModels.ts:81-87
Status Update Mechanisms
MessageJS is designed to handle message status updates via two potential mechanisms: a "push" model (webhooks) and a "pull" model (getStatus).
Webhook (Push Model)
This is the primary and most efficient method. The third-party provider initiates the communication by sending an HTTP request to a pre-configured endpoint on the MessageJS server whenever a message's status changes.
The sequence diagram below models this interaction.
This sequence shows a provider pushing a status update to MessageJS, which then updates its database.
GetStatus (Pull Model)
The IConnector interface defines an optional getStatus method. This suggests a "pull" mechanism where MessageJS could proactively query the third-party provider for the status of a message using its externalId. This could be used for providers that do not support webhooks or as a periodic check to ensure no status updates were missed.
// From packages/core/src/connectors/IConnector.ts
export interface IConnector {
// ... other methods
/**
* (Optional) Fetches the delivery status of a previously sent message from the
* third-party service, if the provider supports it.
*
* @param externalId The unique ID returned by the provider in the initial `SendResult`.
* @returns A promise that resolves with the message's current `MessageStatus`.
*/
getStatus?(externalId: string): Promise<MessageStatus>;
}
Sources: packages/core/src/connectors/IConnector.ts:68-76
Implementation and Configuration
While webhooks are cited as a feature and the system is designed to support them, the provided API_REFERENCE.md does not contain specific endpoints for users to configure webhook URLs for their projects or connectors. This indicates that while the backend processing logic is accounted for in the data models, the user-facing configuration may be managed through the dashboard or is a feature that is still under active development.
Sources: QUICK_START.md:131, API_REFERENCE.md
Summary
Webhooks are a critical feature in MessageJS for tracking the complete lifecycle of a message. The system's architecture, particularly the MessageLog data model and MessageStatus enum, is fundamentally designed to handle real-time status updates pushed from third-party providers. This enables accurate analytics, logging, and error handling. While the core components are in place, the specific API for user-side webhook configuration is not detailed in the current documentation, suggesting it is either handled outside the main REST API (e.g., in the dashboard) or is a planned enhancement.