Webhook System Overview
Webhooks let your application receive real-time HTTP notifications whenever events occur in HappyColis. Instead of polling the API, you register an endpoint and HappyColis pushes event payloads to it as they happen.
Architecture
The queue is per-integration and processed in order. If a delivery fails, the queue enters a BLOCKED state and no further messages are sent to that subscriber until the situation is resolved.
Message Format
Every HTTP POST to your endpoint carries a JSON body with two top-level keys:
json
{
"header": {
"organizationId": "550e8400-e29b-41d4-a716-446655440000",
"messageId": "7b3f1c82-4d9a-4e2b-9c01-2a3b4c5d6e7f",
"webhookId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"type": "order/created",
"date": "2026-03-16T12:00:00.000Z"
},
"body": {
// event-specific payload
}
}Header fields
| Field | Type | Description |
|---|---|---|
organizationId | UUID | The organization that owns the resource that triggered the event |
messageId | UUID | Unique identifier for this delivery attempt (use for dedup) |
webhookId | UUID | ID of the webhook subscription that received this message |
type | string | Webhook event type (see Available Events) |
date | ISO 8601 | Timestamp when the message was enqueued |
Body
The body is the raw Kafka event payload for that domain event. Its structure depends on the event type.
Dispatch Flow Detail
- Kafka consumer —
NotificationProcessorControllersubscribes to allORGANIZATION_TOPICSvia the NestJS Microservices@EventPatterndecorator. - Formatter registry — each Kafka topic is mapped to a
WebHookFormatterInterfacein the formatter registry (seeapps-notification-processor.module.ts). TheDefaultTopicDataFormatterextractsorganizationIdfrom the payload and maps it to the correctWebhookType. - Subscriber lookup —
IntegrationWebhooksQueryreturns allIntegrationWebhookEntityrows matching the organization and event type. - Queue enqueue —
QueueProcessor.process()persists anIntegrationQueueMessageEntityand emits aMessageInterfaceto theapplications.message.processinternal Kafka topic. - HTTP delivery —
QueueProcessor.send()fetches the application'sclientSecret, builds the signed payload, and POSTs it to the subscriber'sendPoint. - Result handling — a 2xx response marks the message delivered and advances the queue. Any other response or exception marks the queue
BLOCKED.
Available Events
Order Events
| Type | Description |
|---|---|
order/created | Order has been created |
order/updated | Order has been updated |
order/completed | Order has been completed |
order/cancelled | Order has been cancelled |
Delivery Order Events
| Type | Description |
|---|---|
delivery_order/created | Delivery order created |
delivery_order/updated | Delivery order updated (defined in enum but not currently dispatched — no Kafka mapping) |
delivery_order/opened | Delivery order opened for fulfillment |
delivery_order/pending | Delivery order is pending |
delivery_order/cancelled | Delivery order cancelled |
delivery_order/completed | Delivery order completed |
delivery_order/fulfillment_accepted | Fulfillment accepted by warehouse |
Shipment Events
| Type | Description |
|---|---|
shipment/created | Shipment created |
shipment/completed | Shipment completed (delivered) |
shipment/shipping_event | Carrier tracking event received |
Stock Reference Events
| Type | Description |
|---|---|
stock_reference/created | Stock reference created |
stock_reference/updated | Stock reference updated |
stock_reference/movement_created | Stock movement recorded |
stock_reference/movement_updated | Stock movement updated |
stock_reference/fulfillment_event | Fulfillment event on stock |
stock_reference/sku_updated | SKU updated |
stock_reference/status_updated | Status changed |
Product Events
| Type | Description |
|---|---|
product/created | Product created |
product/updated | Product updated |
product/status_updated | Product status changed |
product/image/created | Image added to product |
product/image/removed | Image removed from product |
Variant Events
| Type | Description |
|---|---|
variant/created | Variant created |
variant/updated | Variant updated |
variant/status_updated | Variant status changed |
variant/source_updated | Variant source changed |
variant/model_changed | Variant model changed |
variant/tag/added | Tag added to variant |
variant/tag/removed | Tag removed from variant |
variant/price/added | Price added to variant |
variant/price/removed | Price removed from variant |
variant/image/created | Image added to variant |
variant/image/removed | Image removed from variant |
Transfer Order Events
| Type | Description |
|---|---|
transfer_order/created | Transfer order created |
transfer_order/updated | Transfer order updated |
transfer_order/cancelled | Transfer order cancelled |
transfer_order/completed | Transfer order completed |
transfer_order/opened | Transfer order opened |
Location Events
| Type | Description |
|---|---|
location/created | Location created |
location/activated | Location activated |
location/updated | Location updated |
location/deactivated | Location deactivated |
location/type_changed | Location type changed |
location/fulfillment_service_integration/created | Fulfillment service integration created |
location/fulfillment_service_integration/accepted | Fulfillment service integration accepted |
location/fulfillment_service_integration/errored | Fulfillment service integration errored |
location/fulfillment_service_integration/rejected | Fulfillment service integration rejected |
Collection & Catalog Events
| Type | Description |
|---|---|
collection/created | Collection created |
collection/updated | Collection updated |
catalog/created | Catalog created |
catalog/updated | Catalog updated |
Vendor Events
| Type | Description |
|---|---|
vendor/created | Vendor created |
vendor/updated | Vendor updated |
Next Steps
- Signature Verification — verify that webhook requests are genuine
- Subscription Management — create and remove webhook subscriptions