Notification lifecycle
How a notification moves from creation through delivery (or cancellation / purge), from the caller's perspective. Status is computed at read time from timestamps and the live delivery state — there is no stored status field. How to call each step is in endpoints → notifications.
What the platform owns
The platform keeps a record for each message sent, with no stored status field. On each read it
computes the status by merging its own scheduledDateTime with the live delivery status. The
platform owns the encrypted content (messageContent, channelIdentifier, templateVariables);
delivery state (status, deliveryDateTime, isPurged) is reported by the backing messaging
provider.
End-to-end journey — immediate send
End-to-end journey — scheduled send + cancel
Notification states
SCHEDULED_DELIVERY is a computed state, not stored: it is returned whenever the record has a
non-null scheduledDateTime and the current status is not CANCELLED.
Timestamps
| Timestamp | Meaning |
|---|---|
createdAt | record inserted |
sentDateTime | the message was accepted for delivery (not yet delivered) |
scheduledDateTime | requested delivery window (set by the caller on send) |
deliveryDateTime | delivery confirmed |
sentDateTime means accepted, not received. For immediate sends sentDateTime ≈ createdAt; for
scheduled sends it is stamped at send time, when the scheduled job is queued.
Scheduling window
A scheduledDateTime must be more than 5 minutes and at most 35 days in the future. A
request outside those bounds returns 422 NOT022003. The notification record has already been
written at that point and remains with no sentDateTime.
Cancellation
Only a notification with a non-null scheduledDateTime can be cancelled: a cancel on a non-scheduled
notification returns 400 NOT100006, and a notification that is not in a cancellable status
returns 412 NOT012001. Both guards must pass.
Purge
POST /v1/notifications/{id}/purge requests deletion of the message body downstream:
- The message body is removed downstream on a best-effort basis — if removal is refused (too old, policy) the error is tolerated and the purge does not fail; the message is still marked purged.
- The platform record is not scrubbed. The encrypted
messageContent,channelIdentifier, andtemplateVariablesremain in the platform. Regulatory scrubbing of the platform record is a separate data-retention operation.
Allow-list
The notification allow-list is a safety gate for non-production environments: it stops notifications
reaching real recipients during development and testing. When enforced (the default), every
channelIdentifier on POST /v1/notifications must match an allow-list entry before any record is
written, else 403 NOT003002. The list is tenant-global — there is no clientId/brandId
scoping, so an allowed identifier is allowed for every tenant in the instance.
Journey summary
- Send — allow-list check → template substitution → record written (encrypted) → dispatched →
sentDateTimestamped. - Poll / read — status fetched live;
SCHEDULED_DELIVERYcomputed when applicable. - Cancel — must be scheduled (
400 NOT100006) and still cancellable (412 NOT012001) →CANCELLED. - Purge — message body removed downstream (best-effort); platform record unchanged;
isPurgedreflects the downstream record.