Announcements API

HTTP reference for the in-app announcement feed, the unread badge count, marking entries as read, and the public media and email-unsubscribe endpoints.

All paths are relative to https://api.aleex-rank.ai/api/v2 and authenticate with X-API-Key: rk_... (see REST API). Announcements are product news and notifications surfaced in-app. The feed and unread count power a notifications badge; marking an entry as read clears it.

Feed

GET  /announcements
GET  /announcements/unread-count
POST /announcements/{id}/read

These three endpoints are authenticated and scoped to the current user.

GET /announcements returns published announcements, newest first, each annotated with the caller’s per-user read flag. Paginate with page and per_page (capped at 50):

{
  "success": true,
  "data": {
    "items": [
      {
        "id": 31,
        "title": "Scheduled pentests are here",
        "summary": "Re-run a completed pentest automatically.",
        "body_html": "<p>Open a completed pentest and choose <strong>Schedule</strong>.</p>",
        "product": "platform",
        "version": "2.8.0",
        "cta_label": "Read the docs",
        "cta_url": "https://docs.aleex-rank.ai/platform/scheduled",
        "published_at": "2026-06-20 10:00:00",
        "read": false
      }
    ],
    "pagination": {"total": 1, "count": 1, "per_page": 20, "current_page": 1, "total_pages": 1}
  }
}

GET /announcements/unread-count returns the badge number — the count of published announcements the user hasn’t read yet:

{"success": true, "data": {"unread": 3}}

POST /announcements/{id}/read marks a single entry as read (this is what clears the badge). It returns 404 if the announcement doesn’t exist or isn’t published:

{"success": true, "data": {"read": true}}

Public endpoints

GET  /announcements/media/{id}
GET  /announcements/unsubscribe
POST /announcements/unsubscribe

These three require no credential — they back announcement emails and embedded media.

GET /announcements/media/{id} is a read-only proxy that streams an announcement image (for example a GIF) from the private media bucket. It responds with the raw image bytes and a long-lived Cache-Control: public, max-age=31536000, immutable header, or 404 if the media id is unknown. Only registered media ids are served, so arbitrary storage paths can’t be requested.

GET/POST /announcements/unsubscribe is the one-click email opt-out for product update emails, authorized by an HMAC token rather than a session. The link carries the user id and token as query parameters (?u={user_id}&t={token}):

  • GET renders a confirmation page and changes nothing, so email prefetching never opts a user out.
  • POST performs the opt-out. It backs both the confirmation page’s button and RFC 8058 one-click unsubscribe, where the mail provider posts directly to the URL.