Platform — notifications endpoints
How to call the platform notification routes. The formal schema is the OpenAPI specification
(Notification API, openapi/source/platform/notifications/notifications.yml); this page is
the call contract. The notification journey
(states + timestamps) is in notification lifecycle.
All routes require a bearer token (B2B JWT) with CLIENT role and an ACTIVE party. The
global /v1 prefix applies.
Route summary
| Method | Path | Code | Purpose |
|---|---|---|---|
POST | /v1/notifications | 201 | Send a notification |
GET | /v1/notifications | 200 | List notifications for the party |
GET | /v1/notifications/{notificationId} | 200 | Get a single notification |
DELETE | /v1/notifications/{notificationId} | 200 | Cancel a scheduled notification |
POST | /v1/notifications/{notificationId}/purge | 200 | Purge message from the provider |
POST /v1/notifications — send a notification
Sends a notification to the party. The platform stores the encrypted message content, then
dispatches it via the provider configured for the requested contactChannel.
Body — SendNotificationRequest:
| Field | Type | Required | Notes |
|---|---|---|---|
messageType | MARKETING | VERIFICATION | GENERAL | yes | Controls template lookup |
contactChannel | SMS | EMAIL | DEVICE | yes | Channel for delivery |
channelIdentifier | string | yes | Phone number, email, or device token; leading + stripped before storage |
messageContent | string | no | Required when no templateId is supplied |
templateId | string (UUID) | no | When set, messageContent is derived from the template |
templateVariables | object | no | Key/value pairs substituted into {{var}} placeholders |
scheduledDateTime | ISO 8601 datetime | no | Future delivery window; see scheduling limits below |
Response — SendNotificationResponse:
{
"notification": {
"notificationId": "b3d5f1a2-4e6c-4b8d-9f3e-1a2b3c4d5e6f",
"vendorId": "SMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"messageType": "GENERAL",
"contactChannel": "SMS",
"channelIdentifier": "+61 4XX XXX X12", // masked
"status": "NEW",
"scheduledDateTime": null,
"createdAt": "2026-05-25T08:00:00.000Z",
"deliveryDateTime": null,
},
"vendorId": "SMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
}
Scheduling limits (provider-enforced): scheduledDateTime must be more than 5 minutes
in the future and no more than 35 days ahead. Violation → 422 NOT022003.
Allow-list gate: when the allow-list is enforced (default), the channelIdentifier must
appear in the allow list for the matching notificationType. Blocked identifiers return
403 NOT003002 before any row is written.
GET /v1/notifications — list notifications
Returns notifications for the authenticated party, ordered by createdAt descending. The
platform reads its own records first, then enriches each with live status from the provider.
The status filter is applied after enrichment.
Query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number (1-based) |
limit | integer | 20 | Items per page; capped at 100 |
contactChannel | SMS | EMAIL | DEVICE | — | Filter by channel |
messageType | MARKETING | VERIFICATION | GENERAL | — | Filter by type |
channelIdentifier | string | — | Filter by exact (decrypted) channel identifier |
status | NEW | DELIVERED | SCHEDULED_DELIVERY | ERROR | CANCELLED | — | Filter by status; applied after provider enrichment |
Response — GetNotificationsResponse:
{
"notifications": [
{
"notificationId": "b3d5f1a2-...",
"messageType": "GENERAL",
"contactChannel": "SMS",
"channelIdentifier": "+61 4XX XXX X12",
"status": "DELIVERED",
"scheduledDateTime": null,
"createdAt": "2026-05-25T08:00:00.000Z",
"vendorId": "SMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"deliveryDateTime": "2026-05-25T08:00:05.000Z",
},
],
"pagination": {
"currentPage": 1,
"totalPages": 1,
"totalCount": 1,
"limit": 20,
"hasNext": false,
"hasPrevious": false,
},
}
Notifications that cannot be enriched from the provider are silently excluded from the response.
GET /v1/notifications/{notificationId} — get notification
Returns full detail for a single notification including messageContent (decrypted) and
isPurged.
Response — GetNotificationDetailResponse:
{
"notification": {
"notificationId": "b3d5f1a2-...",
"messageType": "GENERAL",
"contactChannel": "SMS",
"channelIdentifier": "+61 4XX XXX X12",
"status": "DELIVERED",
"scheduledDateTime": null,
"createdAt": "2026-05-25T08:00:00.000Z",
"vendorId": "SMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"deliveryDateTime": "2026-05-25T08:00:05.000Z",
"messageContent": "Your OTP is 123456.",
"templateId": "otp-sms-v1",
"initiatingUserId": "usr_abc123",
"isPurged": false,
"errorDetails": null,
},
}
404(NOT004001) if the notification does not exist for the tenant.
DELETE /v1/notifications/{notificationId} — cancel a scheduled notification
Cancels a notification that is pending scheduled delivery. The platform requires the
notification to have a non-null scheduledDateTime; if it does not, 400 NOT100006 is
returned before reaching the provider. The provider additionally requires the message to be
in scheduled or accepted status; if not, 412 NOT012001 is returned.
Returns the updated NotificationSummary after cancellation.
400(NOT100006) ifscheduledDateTimeis null (platform guard).404(resource not found) if the notification does not exist for the tenant.412(NOT012001) if the provider rejects the cancellation (message not in a cancellable status).
POST /v1/notifications/{notificationId}/purge — purge notification
Requests deletion of the message body from the provider's records (best-effort). The
platform row — including the encrypted messageContent — is not deleted or scrubbed.
isPurged in the response reflects the provider's record, not the platform row.
Returns NotificationSummary with isPurged: true when the provider confirms.
404(resource not found) if the notification does not exist for the tenant.
Enumerations
| Enum | Values |
|---|---|
contactChannel | SMS, EMAIL, DEVICE |
messageType | MARKETING, VERIFICATION, GENERAL |
status (computed) | NEW, DELIVERED, SCHEDULED_DELIVERY, ERROR, CANCELLED |
status is not stored on the platform row. It is computed at read time: if scheduledDateTime
is set and the provider status is not CANCELLED, the status is SCHEDULED_DELIVERY;
otherwise the provider's own status is used.
Errors
| HTTP | Code | When |
|---|---|---|
400 | NOT100006 | Cancel attempted on a non-scheduled notification (scheduledDateTime is null) |
403 | NOT003002 | channelIdentifier not in the allow list (when the allow-list is enforced) |
404 | NOT004001 | Notification not found — read (GET /{id}) only |
404 | GEN004001 | Notification not found on cancel / purge, or template not found during send (RESOUCE_NOT_FOUND; the domain NOT004002 is unused) |
412 | NOT012001 | Provider rejects cancel (message not in scheduled/accepted status) |
422 | NOT022003 | scheduledDateTime outside the provider-enforced window (>now+5min and ≤now+35d) |
500 | NOT100004 | Provider returned no vendorId after send |