Announcements - BevvyTech/BrewskiDocs GitHub Wiki

Announcements

Overview

  • Endpoint Group: Tools / Announcements
  • Purpose: Manage global announcements, blog posts, tutorials, and adverts that are surfaced to Brewski teams.
  • Availability:
    • Creation and management requires membership in a super user team (teams.role = su).
    • Reading, acknowledging, and hiding announcements is available to any authenticated user.

Endpoint Summary

Method Path Description
GET /announcements List announcements with pagination and optional filters.
POST /announcements Create a new announcement or blog post.
GET /announcements/:id Fetch a single announcement.
PATCH /announcements/:id Update an existing announcement.
DELETE /announcements/:id Permanently remove an announcement.
POST /announcements/:id/image Upload or replace the feature image.
DELETE /announcements/:id/image Remove the current feature image.
GET /announcements/:id/content Retrieve full body content for end users.
POST /announcements/:id/acknowledge Mark the announcement as acknowledged for the current user.
POST /announcements/:id/hide Hide a blog, tutorial, or advert for the current user.

Authentication

  • Requires a valid bearer access token (Authorization: Bearer <token>).
  • POST, PATCH, DELETE, and image management endpoints require an active super user team membership.
  • GET /announcements, GET /announcements/:id/content, POST /announcements/:id/acknowledge, and POST /announcements/:id/hide are available to any authenticated user.

Request

Query Parameters (GET /announcements)

  • page (number, optional, default 1) β€” 1-indexed page number.
  • pageSize (number, optional, default 20, max 200) β€” number of records per page.
  • type (string, optional, values: announcement, blog, tutorial, advert) β€” filter by content type.
  • search (string, optional) β€” case-insensitive filter on title, message, or tags.
  • view (string, optional, values: admin) β€” when set to admin, bypasses publish/hidden filters and requires super user membership.
  • includeFuture (boolean, optional) β€” override default publish filtering (false for end users, true for admin view).
  • includeExcluded (boolean, optional) β€” include records with excludeFromSearch = true (only honoured for admin view).

Body (POST /announcements)

{
  "title": "April product update",
  "message": "Highlights from this month's release.",
  "type": "announcement",
  "publishAt": "2025-04-30T09:00:00.000Z",
  "publishedAt": "2025-04-30T09:00:00.000Z",
  "article": "<p>Rich text body rendered in the announcement detail view.</p>",
  "tags": "release,platform",
  "excludeFromSearch": false,
  "buttons": [
    { "color": "primary", "text": "Read docs", "link": "https://docs.brewskiapp.com/releases" }
  ]
}
  • title (string, required, max 200 chars) β€” Display title.
  • message (string, required, max 10β€―000 chars) β€” Short summary used in previews.
  • type (string, optional, default announcement, values: announcement, blog, tutorial, advert) β€” Content classification.
  • publishAt (ISO 8601 timestamp, optional, default now) β€” Scheduling timestamp; entries are hidden before this moment.
  • publishedAt (ISO 8601 timestamp or null, optional) β€” Display date shown in article headers; defaults to publishAt.
  • article (string or null, optional) β€” Rich text body saved as HTML.
  • tags (string or null, optional, max 2β€―000 chars) β€” Comma-separated keywords.
  • excludeFromSearch (boolean, optional, default false) β€” If true the record is hidden from public search surfaces.
  • buttons (array, optional, max 5 items) β€” Call-to-action buttons. Each object requires color (string, e.g. primary, secondary, success, warning, info, error), text (string, required), and link (absolute URL, required).

Body (PATCH /announcements/:id)

  • Accepts the same shape as POST but all fields are optional. Supplying an empty buttons array replaces the existing set with none.

File Upload (POST /announcements/:id/image)

  • multipart/form-data with single file field.
  • Accepted formats: PNG, JPEG, WEBP, GIF.
  • Maximum file size: 2β€―MB.
  • The uploaded file is stored under the uploader’s super team storage bucket.

Response

Success 200 OK / 201 Created

{
  "announcement": {
    "id": "7d6a6a7a-4ef2-4cf1-b616-7b4a69d3da9a",
    "title": "April product update",
    "message": "Highlights from this month's release.",
    "type": "announcement",
    "publishAt": "2025-04-30T09:00:00.000Z",
    "publishedAt": "2025-04-30T09:00:00.000Z",
    "article": "<p>Rich text body rendered in the announcement detail view.</p>",
    "tags": "release,platform",
    "excludeFromSearch": false,
    "buttons": [
      { "color": "primary", "text": "Read docs", "link": "https://docs.brewskiapp.com/releases" }
    ],
    "imageUrl": "https://assets.brewskiapp.com/logos/<team-id>/announcement-123/cover.png",
    "imageTeamId": "0f7e9c89-74a0-47b2-920d-efef32cd7e1f",
    "authorId": "45aab965-7ef6-4831-bad2-7f9d98827b63",
    "authorName": "Brewski Ops",
    "authorEmail": "[email protected]",
    "createdAt": "2025-04-25T12:34:56.000Z",
    "updatedAt": "2025-04-25T12:34:56.000Z",
    "requiresAcknowledgement": true,
    "canHide": false,
    "userState": {
      "acknowledgedAt": null,
      "hiddenAt": null
    }
  }
}
  • imageUrl is omitted when no image is stored.
  • imageTeamId identifies the super user team storage bucket containing the asset.
  • When listing (GET /announcements) the response envelope also includes pagination metadata: page, pageSize, pages, total, and unreadCount (number of published announcements without acknowledgement).
  • List responses intentionally omit the long-form article body; use GET /announcements/:id/content to retrieve it on demand.
  • requiresAcknowledgement is true only for announcements that expect the user to confirm the message.
  • canHide is true for blogs, tutorials, and adverts; hiding stores a per-user state so the item no longer appears in the carousel.

List Response (end users)

{
  "page": 1,
  "pageSize": 10,
  "total": 14,
  "pages": 2,
  "unreadCount": 3,
  "announcements": [
    {
      "id": "f6c3f62a-5f2a-4a7b-bf86-97432724a2aa",
      "title": "Delivery confirmations now live",
      "message": "Drivers can capture signatures on mobile – no more paper slips.",
      "type": "announcement",
      "publishAt": "2025-04-20T09:00:00.000Z",
      "publishedAt": "2025-04-19T12:00:00.000Z",
      "tags": "delivery,workflow",
      "excludeFromSearch": false,
      "imageUrl": null,
      "imageTeamId": null,
      "buttons": [
        { "color": "primary", "text": "Learn more", "link": "https://docs.brewskiapp.com/delivery-confirmations" }
      ],
      "authorId": "45aab965-7ef6-4831-bad2-7f9d98827b63",
      "authorName": "Brewski Ops",
      "authorEmail": "[email protected]",
      "createdAt": "2025-04-15T08:21:00.000Z",
      "updatedAt": "2025-04-18T17:43:00.000Z",
      "requiresAcknowledgement": true,
      "canHide": false,
      "userState": {
        "acknowledgedAt": null,
        "hiddenAt": null
      }
    }
  ]
}

GET /announcements/:id/content

  • Returns the same metadata as the list response but always includes the article field for rendering rich content.
  • Enforces publish schedules, hidden flags, and the exclude_from_search toggle. Requests before publishAt receive 403.

POST /announcements/:id/acknowledge

  • Body: empty.
  • Marks an announcement (type announcement) as read for the current user, returning the latest user state.
{
  "userState": {
    "acknowledgedAt": "2025-04-21T10:00:00.000Z",
    "hiddenAt": null
  }
}

POST /announcements/:id/hide

  • Body: empty.
  • Only available for blogs, tutorials, and adverts. Hiding removes the announcement from subsequent list results for that user.
{
  "userState": {
    "acknowledgedAt": null,
    "hiddenAt": "2025-04-21T10:05:00.000Z"
  }
}

Error Codes

Status Body Example When It Happens
400 Bad Request { "message": "Invalid request body" } Validation failed for request payload or upload.
401 Unauthorized { "message": "Unauthorized" } Missing/invalid bearer token or no active session.
403 Forbidden { "message": "Forbidden" } Caller lacks required super user membership (for mutating endpoints) or tries to read content before publishAt.
404 Not Found { "message": "Announcement not found" } ID not visible to the user (deleted, hidden, or excluded).
413 Payload Too Large { "message": "Image file is too large" } Uploaded image exceeds 2β€―MB limit.

Side Effects & Events

  • Writes to the announcements table (insert/update/delete).
  • Per-user acknowledgement state is stored in announcement_user_states.
  • Image uploads are stored alongside team logo assets and replace any previous file.
  • Deleting an announcement also removes its stored image, if present.

Rate Limiting & Idempotency

  • No dedicated rate limiter beyond global platform limits.
  • Image uploads are not idempotent; re-uploading replaces the stored file.

Examples

curl -X POST https://api.brewskiapp.com/announcements \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
        "title": "New delivery notes",
        "message": "Digital delivery confirmations are now live.",
        "type": "tutorial",
        "publishAt": "2025-04-28T08:00:00.000Z",
        "tags": "delivery,workflow",
        "excludeFromSearch": false
      }'

Changelog

Date Author Change
2025-04-27 AI Assistant Added per-user acknowledgement state, advert type, and read/hide endpoints.
2025-04-25 AI Assistant Initial draft for announcements management endpoints.
⚠️ **GitHub.com Fallback** ⚠️