Skip to content

Player notifications

Player notifications are a durable, recipient-scoped inbox. They are separate from the operator console notification feed. A game client reads or acknowledges its own inbox with reserved RPC methods; authoritative server game logic creates notifications through the server-runtime API.

KIND_NOTIFICATION (27) is a reliable server-to-client UTF-8 JSON envelope containing a committed notification. It is best-effort and at least once: deduplicate by id, then use notifications.list after reconnect or a gap. A full local queue can drop the live copy without losing the durable inbox item.

notifications.list({ "limit": 50, "cursor": "optional opaque cursor" })

Returns status=0 and JSON { "notifications": [Notification], "cursor": string|null }. Items are newest first. limit is clamped to 1–100; omit it for 50. Guests receive "authentication required"; malformed JSON receives "invalid JSON body".

notifications.mark_read({ "ids": ["notification-id"] })

Returns status=0 and { "read_ids": [string] }. It only changes the caller’s items and is idempotent: missing or already-read ids are omitted. The client cannot mark another player’s inbox item read.

{
"id": "opaque-stable-id",
"code": 7,
"subject": "Daily reward",
"content": { "coins": 10 },
"sender": "server",
"created_at_unix_ms": 1730000000000,
"read_at_unix_ms": null
}
// Send generic RPC "notifications.list"; decode its correlated response.
// Bind UCitadelClientSubsystem::OnNotificationReceived to receive raw JSON
// from KIND_NOTIFICATION and deduplicate it by its `id` field.
  • A notification is committed before its live envelope is attempted.
  • Reusing the same producer (recipient, delivery_key) is idempotent and does not produce another live envelope.
  • Delivery is local-node only in this release. Cross-node forwarding, campaigns, external push, deletion, and retention are not implemented.