Notifications API
Endpoints for listing, reading, and managing notification channels and preferences on FonProxy.

For authentication, error format, and common headers, see General API Info.
All notification IDs are ID.
Notifications
List Notifications Auth required
GET /notifications
Query Parameters
| Name | Type | Description | Required |
|---|---|---|---|
page | number | Page number (default: 1) | No |
limit | number | Items per page, max 50 (default: 20) | No |
category | string | Filter: general, auth, order, payment | No |
Response
{
"notifications": [
{
"id": "K4Xb9rPmYz",
"type": "order_activated",
"category": "order",
"subject": "notification.order_activated_subject",
"payload": {
"subject": "notification.order_activated_subject",
"blocks": [
{ "type": "heading", "text": "notification.order_activated_heading" },
{ "type": "text", "text": "notification.order_activated_text" },
{ "type": "divider" },
{ "type": "key_value", "label": "notification.order_activated_type", "value": "Residential Giga" },
{ "type": "key_value", "label": "notification.order_activated_quantity", "value": "10 GB" },
{ "type": "key_value", "label": "notification.order_activated_total", "value": "$5.00" },
{ "type": "divider" },
{ "type": "heading", "text": "notification.order_activated_getting_started" },
{ "type": "text", "text": "notification.order_activated_step_1" },
{ "type": "text", "text": "notification.order_activated_step_2" },
{ "type": "text", "text": "notification.order_activated_step_3" },
{ "type": "copyable", "value": "https://fonproxy.com/orders/K4Xb9rPmYz", "label": "notification.order_activated_order_link" },
{ "type": "button", "text": "notification.order_activated_view_order", "url": "https://fonproxy.com/orders/K4Xb9rPmYz" },
{ "type": "divider" },
{ "type": "muted", "text": "notification.order_activated_footer" }
]
},
"read": false,
"createdAt": "2026-03-22T10:00:00.000Z"
},
...
],
"total": 1,
"page": 1,
"pages": 1
}Get Unread Count Auth required
GET /notifications/unread-count
Response
{
"unread": 3
}Get Single Notification Auth required
GET /notifications/:id
Response
{
"id": "K4Xb9rPmYz",
"type": "welcome",
"category": "general",
"subject": "notification.welcome_subject",
"payload": {
"subject": "notification.welcome_subject",
"blocks": [
{ "type": "heading", "text": "notification.welcome_heading" },
{ "type": "text", "text": "notification.welcome_text" },
{ "type": "key_value", "label": "notification.welcome_email_label", "value": "user@example.com" },
{ "type": "divider" },
{ "type": "muted", "text": "notification.welcome_footer" }
]
},
"read": true,
"createdAt": "2026-03-22T09:00:00.000Z"
}Mark Notification as Read Auth required
PATCH /notifications/:id/read
Response
{
"id": "K4Xb9rPmYz",
"type": "welcome",
"category": "general",
"subject": "notification.welcome_subject",
"payload": { "..." : "..." },
"read": true,
"createdAt": "2026-03-22T09:00:00.000Z"
}Mark All Notifications as Read Auth required
PATCH /notifications/read-all
Response
{
"success": true
}Notification Block Types
The payload.blocks array contains structured content blocks that the frontend renders. Each block has a type and type-specific fields:
| Type | Fields | Description |
|---|---|---|
heading | text | Section heading |
text | text | Paragraph text (may contain HTML for email) |
muted | text | Small muted/secondary text |
code | code, label? | Large monospace block (e.g. auth codes) |
copyable | value, label? | Inline copyable value (e.g. proxy endpoint, URL) |
button | text, url | Call-to-action button / link |
divider | β | Horizontal separator |
key_value | label, value | Label: value pair |
Text fields containing notification.* keys should be resolved via the translation system on the frontend.
Notification Categories
| Category | Description |
|---|---|
general | Welcome, system announcements |
auth | Auth codes (email-only, not stored in DB) |
order | Order activated, expired, etc. |
payment | Top-up completed, failed, etc. |
admin | Admin broadcast notifications |
referral | Referral registration & income |
Channel Restrictions
Not all notifications are delivered to all channels:
| Notification | database | telegram | Notes | |
|---|---|---|---|---|
| Auth code | β | β | β | Security: codes never persisted |
| Welcome | β | β | β | All channels |
| Order activated | β | β | β | All channels |
| Admin broadcast | β | β | β | Admin-configurable channels |
| Referral signup | β | β | β | All channels |
| Referral income | β | β | β | All channels |
Channel Preferences
Users can enable or disable notification channels. Disabled channels are silently skipped when sending.
List Channels Auth required
GET /notifications/channels
Response
{
"channels": [
{
"name": "email",
"label": "Email",
"available": true,
"userControllable": true,
"enabled": true
},
{
"name": "database",
"label": "In-app notifications",
"available": true,
"userControllable": true,
"enabled": true
},
{
"name": "telegram",
"label": "Telegram",
"available": true,
"userControllable": true,
"enabled": true
}
]
}availableβ whether the channel is operationally configured on the server (e.g. SMTP set up for email).enabledβ whether this user has the channel turned on.userControllableβ whether the user is allowed to toggle it (some system channels may be read-only in future).
Update Channel Preference Auth required
PATCH /notifications/channels/:channel
Parameters
| Name | Type | Description | Required |
|---|---|---|---|
:channel | string | Channel name (email, database, etc.) | Yes |
Request Body
{ "enabled": false }Response
Full updated channels list (same shape as GET /notifications/channels).
Unsubscribe (Public)
Every email sent includes a one-click unsubscribe link in the footer. Clicking it disables the email channel for that user immediately and shows a branded confirmation page.
Unsubscribe via Token
GET /notifications/unsubscribe
Query Parameters
| Name | Type | Description | Required |
|---|---|---|---|
token | string | AES-256-GCM encrypted token containing { userId, channel } | Yes |
Returns an HTML page (200 on success, 400 on invalid token).
The token is generated server-side and embedded in every outgoing email. No database lookup is needed β the encryption itself acts as authentication.
Re-enabling email notifications is done from the authenticated /notifications/channels endpoint.