Notifications API

FonProxy Notifications API reference documentation.

Notifications API

All endpoints require authentication (Authorization: Bearer <token> or API key).

All notification IDs are hashid-encoded.


List notifications

GET /notifications?page=1&limit=20&category=order

Query params:

ParamTypeDefaultDescription
pagenumber1Page number
limitnumber20Items per page (max 50)
categorystringFilter by category: general, auth, order, payment

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

GET /notifications/unread-count

Response:

{
  "unread": 3
}

Get single notification

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

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

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:

TypeFieldsDescription
headingtextSection heading
texttextParagraph text (may contain HTML for email)
mutedtextSmall muted/secondary text
codecode, label?Large monospace block (e.g. auth codes)
copyablevalue, label?Inline copyable value (e.g. proxy endpoint, URL)
buttontext, urlCall-to-action button / link
dividerHorizontal separator
key_valuelabel, valueLabel: value pair

Text fields containing notification.* keys should be resolved via the translation system on the frontend.


Notification categories

CategoryDescription
generalWelcome, system announcements
authAuth codes (email-only, not stored in DB)
orderOrder activated, expired, etc.
paymentTop-up completed, failed, etc.
adminAdmin broadcast notifications
referralReferral registration & income

Channel restrictions

Not all notifications are delivered to all channels:

NotificationemaildatabasetelegramNotes
Auth codeSecurity: codes never persisted
WelcomeAll channels
Order activatedAll channels
Admin broadcastAdmin-configurable channels
Referral signupAll channels
Referral incomeAll channels

Channel preferences

Users can enable or disable notification channels. Disabled channels are silently skipped when sending.

List channels

GET /notifications/channels

Auth: Required.

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

PATCH /notifications/channels/:channel

Auth: Required.

Path param: :channel — channel name (email, database, etc.)

Body:

{ "enabled": false }

Response: Full updated channels list (same shape as GET /notifications/channels).


Unsubscribe (public, no auth)

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.

GET /notifications/unsubscribe?token=<encrypted-token>

Returns: HTML page (200 on success, 400 on invalid token).

The token is AES-256-GCM encrypted and contains { userId, channel }. It is generated server-side and embedded in every outgoing email. No database lookup is needed to verify it — the encryption itself acts as the authentication.

Re-enabling email notifications is done from the authenticated /notifications/channels endpoint.

Notifications API — FonProxy