{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://goodgo.vn/schemas/events/notification.requested.schema.json", "title": "notification.requested", "description": "Emitted when a domain action requests delivery of a user-facing notification. Consumed by the notifications worker pool, which fans out to email / SMS / Zalo OA / FCM / in-app channels per user preferences.", "type": "object", "additionalProperties": false, "required": [ "notificationId", "userId", "category", "template", "params", "channels", "requestedAt" ], "properties": { "notificationId": { "type": "string", "minLength": 1, "description": "UUIDv7 of the persisted Notification aggregate (also used as idempotency key by the consumer)." }, "userId": { "type": "string", "minLength": 1 }, "category": { "type": "string", "enum": [ "auth", "kyc", "listing", "payment", "subscription", "inquiry", "lead", "agent", "residential", "system" ] }, "template": { "type": "string", "minLength": 1, "description": "Template key resolved by TemplateService (e.g. 'listing.approved.email.vi')." }, "params": { "type": "object", "description": "Template substitution parameters. Shape depends on template; consumer is responsible for validation against the template manifest.", "additionalProperties": true }, "channels": { "type": "array", "minItems": 1, "items": { "type": "string", "enum": ["email", "sms", "zalo", "fcm", "in_app"] }, "description": "Channels requested by the producer. The consumer further filters by user notification preferences before dispatch." }, "locale": { "type": "string", "enum": ["vi", "en"], "description": "Preferred locale; falls back to user's stored locale, then 'vi'." }, "priority": { "type": "string", "enum": ["low", "normal", "high", "critical"], "default": "normal" }, "dedupeKey": { "type": "string", "minLength": 1, "description": "Optional consumer-side dedupe key (collapses duplicate logical notifications inside the BullMQ queue, in addition to envelope-level eventId dedupe)." }, "requestedAt": { "type": "string", "format": "date-time" } } }