Groups - BevvyTech/BrewskiDocs GitHub Wiki

Groups API

POST /groups/:groupId/image

Upload or replace the hero image shown on the group detail page. The endpoint stores the asset, records a new content version, and immediately approves the change so the UI keeps imageStatus set to approved. When the moderation workflow arrives the same hook will gate these updates before approval.

Authentication & Permissions

  • Requires a valid bearer token.
  • The caller must belong to the target group as an active owner or admin. Non-members and read-only (member) roles receive 403 Forbidden.

Request

  • Content-Type: multipart/form-data
  • Body field image must be a single JPG, PNG, or WebP file:
    • Recommended minimum: 690 × 420 px (23:14). Smaller images are accepted but will be upscaled and may appear soft.
    • Any aspect ratio is allowed; the server crops/resizes to 690 × 420 px automatically.
    • Maximum size: 6 MB
  • Larger images are downscaled server-side to 690 × 420 px; smaller uploads are upscaled with a centered crop.
  • All inputs are stored as JPEG; transparent backgrounds are flattened against white.

GET /groups/notifications

Return badge counts that the Admin navigation can surface for the authenticated user.

Authentication & Permissions

  • Requires a valid bearer token.
  • Results are scoped to the teams the caller belongs to. Passing a teamId that the caller cannot access returns 403 Forbidden.

Query Parameters

  • teamId (optional, UUID): limit the response to a single team. When omitted, counts aggregate across every team the user can access.

Response

  • 200 OK
{
  "pendingInvites": 1,
  "unclaimedOrders": 2
}
  • pendingInvites: number of brewery groups where the caller’s team membership is still in the invited state.
  • unclaimedOrders: number of active group orders awaiting a hub claim where one of the caller’s teams is participating.

Error Codes

  • 401 Unauthorized – no bearer token supplied.
  • 403 ForbiddenteamId does not belong to the caller.

GET /groups

Return the caller’s brewery-group memberships with pagination metadata so Admin can keep the shared pagination component in sync.

Authentication & Permissions

  • Requires a bearer token.
  • Automatically scopes results to the caller’s teams; passing a teamId outside their access returns 403 Forbidden.

Query Parameters

  • teamId (UUID, optional) — restrict the listing to a single team.
  • search (string ≤ 160 chars, optional) — case-insensitive match against name, slug, regionLabel, description, and approved content metadata.
  • status (invited | active, optional) — default lists both invited and active memberships.
  • page (int ≥ 1, default 1) and pageSize (int ≥ 1, default 25, max 200).
  • sort (name | createdAt, optional) — defaults to name ordering (invites first). Combine with direction (asc | desc) to reverse the sort.

Response

  • 200 OK
{
  "page": 1,
  "pageSize": 25,
  "total": 6,
  "pages": 1,
  "results": [
    {
      "id": "87c5d55f-7b97-4b63-bb21-4969a4a83173",
      "slug": "northern-pallet-coop",
      "name": "Northern Pallet Co-op",
      "regionLabel": "North West England",
      "membership": {
        "teamId": "ac49f3ad-41f3-4fd9-86c7-948f98e2cb1d",
        "status": "active",
        "joinedAt": "2025-01-12T10:30:00.000Z"
      },
      "...": "truncated for brevity"
    }
  ],
  "groups": [
    "...same array for legacy clients..."
  ]
}

results and groups intentionally mirror one another so older clients can continue reading groups during the transition.

Error Codes

  • 401 Unauthorized
  • 403 ForbiddenteamId is not accessible to the caller.

GET /groups/system

List every brewery group on the platform for super-user/support operators.

Authentication & Permissions

  • Requires a bearer token tied to a team with role su or support.

Query Parameters

  • search (string ≤ 160 chars, optional) — case-insensitive match against name, slug, regionLabel, description, and approved content metadata.
  • status (active | retired, optional) — defaults to active groups.
  • page (int ≥ 1, default 1) and pageSize (int ≥ 1, default 25, max 200).
  • sort (name | region | createdAt, optional) plus direction (asc | desc) — default ordering is name asc.

Response

  • 200 OK
{
  "page": 2,
  "pageSize": 25,
  "total": 87,
  "pages": 4,
  "results": [
    {
      "id": "1f32fbfa-38e9-47cc-9424-2d0acb037132",
      "name": "South Coast Drops",
      "status": "active",
      "regionLabel": "South East England",
      "membership": {
        "teamId": "hub-team-id",
        "status": "active"
      },
      "pendingContentVersion": null,
      "approvedContentVersion": { "...": "truncated" }
    }
  ],
  "groups": [
    "...same array for legacy clients..."
  ]
}

Error Codes

  • 401 Unauthorized
  • 403 Forbidden – caller lacks super-user/support access.
curl -X POST "https://api.brewskiapp.com/groups/{groupId}/image" \
  -H "Authorization: Bearer $TOKEN" \
  -F "image=@/path/to/group-hero.jpg"

Response

  • 200 OK
{
  "group": {
    "id": "87c5d55f-7b97-4b63-bb21-4969a4a83173",
    "name": "Northern Pallet Co-op",
    "description": "Shared logistics across the North West.",
    "regionLabel": "North West England",
    "imageUrl": "https://cdn.brewskiapp.com/groups/87c5d55f/group-hero-1730226153.jpg",
    "imageStatus": "approved",
    "shopVisible": true,
    "status": "active",
    "pendingContentVersion": null,
    "approvedContentVersion": {
      "id": "a31e6d15-e330-4987-a52e-6ecffdf7cfe0",
      "imageUrl": "https://cdn.brewskiapp.com/groups/87c5d55f/group-hero-1730226153.jpg",
      "status": "approved",
      "submittedAt": "2025-07-27T10:15:21.000Z",
      "reviewedAt": "2025-07-27T10:15:21.000Z"
    },
    "...": "truncated for brevity"
  }
}

The payload mirrors GET /groups/:groupId, reflecting the freshly uploaded asset and updated content version references.

Error Codes

  • 400 Bad Request – missing file or unreadable image metadata.
  • 401 Unauthorized – no bearer token supplied.
  • 403 Forbidden – caller lacks owner/admin membership in the group.
  • 404 Not Found – group does not exist or has been retired.
  • 413 Payload Too Large – file exceeds the 6 MB limit.
  • 415 Unsupported Media Type – file is not JPG/PNG/WebP.

PATCH /groups/:groupId

Update the core metadata for a brewery group—the name, public slug, region label, and long-form description. Every edit records a new approved content version so dashboards and public listings stay in sync.

Authentication & Permissions

  • Requires a valid bearer token.
  • Callers must belong to the target group as an active owner or admin; read-only (member) roles receive 403 Forbidden.

Request Body

  • name (string, required, ≤160 chars)
  • slug (string, optional, ≤160 chars) — when omitted, the previous slug is preserved. Inputs are normalised to lowercase alphanumerics with hyphen separators.
  • color (string, optional, hex #RRGGBB) — when provided, overrides the stored pastel colour used across Admin and public listings.
  • regionLabel (string, optional, ≤160 chars) — friendly geography label for storefront listings.
  • description (string, optional, ≤5000 chars) — long-form overview shown in Admin and Shop.

Behaviour

  • When a new slug is supplied it must resolve to at least one alphanumeric character after normalisation. Duplicate slugs return 409 Conflict.
  • Colour updates must provide a 7-character hex value prefixed with #; invalid formats return 400 Bad Request.
  • Successful updates clear any pending content version, set the new content as approved, and bump updatedAt.

Response

  • 200 OK{ "group": <GroupDetail> }, mirroring GET /groups/:groupId (including the color swatch used by Admin and public storefronts).

Error Codes

  • 400 Bad Request – slug normalises to an empty value or violates length constraints.
  • 401 Unauthorized – no bearer token supplied.
  • 403 Forbidden – caller lacks owner/admin membership in the group.
  • 404 Not Found – group does not exist or has been retired.
  • 409 Conflict – another group already uses the submitted slug.
⚠️ **GitHub.com Fallback** ⚠️