Supercommerce API Docs
Store API

Banner Module — Storefront

HTTP surface for storefront banner reads. The customer-facing app fetches active, platform-targeted promotional banners attached to a catalog entity (category / brand / tag /…

HTTP surface for storefront banner reads. The customer-facing app fetches active, platform-targeted promotional banners attached to a catalog entity (category / brand / tag / ingredient) and renders them in carousels and entity-page heroes.

Source: api-modules/banner/src/controllers/public-banner.controller.ts.

Admin CRUD for banners lives in docs/separated/admin/banner.md. This file documents the public read endpoint only.


Conventions

Authentication

EndpointAuth
GET /store/banners/:entityType/slug/:slugnone (public)

Banners are public marketing content — no session is required and no PII is returned.

Response envelope

Successful responses are wrapped by ResponseInterceptor:

{
  "data": <payload>,
  "message": "Success",
  "statusCode": 200,
  "metadata": { /* optional */ }
}

The response is not paginated — banners attached to a single entity are bounded by the admin who configured them.

Error envelope

statusCodeerrorCode examples
400BAD_REQUEST (unknown entityType)
500INTERNAL_SERVER_ERROR, DATABASE_ERROR

A missing slug does not 404 — the response is an empty array. The endpoint deliberately can't distinguish "no banners attached" from "no such entity" so consumers render the same empty state in both cases.


Domain types

BannerResponse

type BannerEntityType = "category" | "brand" | "tag" | "ingredient";
type Platform         = "APP" | "WEB" | "BOTH";

type BannerResponse = {
  id: string;
  entityType: BannerEntityType;
  entityId: string;
  image: string;                       // S3 keyresolve to URL client-side via the storage CDN
  url: string;                         // click destinationhttps:// absolute or /relative
  platform: Platform;
  isActive: boolean;                   // always true for storefront reads
  sortOrder: number;                   // ascending; ties broken by createdAt desc
  metadata: Record<string, unknown> | null;
  createdAt: string;                   // ISO
  updatedAt: string;                   // ISO
  deletedAt: string | null;            // always null for storefront reads
};

url is constrained server-side to https://... absolutes or /-prefixed relative paths — http://, javascript:, mailto: and other schemes are rejected at admin create-time, so the storefront can use the value verbatim without re-sanitising.


Endpoints

GET /store/banners/:entityType/slug/:slug — Active banners for an entity

Returns active (isActive=true, deletedAt IS NULL) banners attached to the resolved entity, sorted by sortOrder ASC, createdAt DESC.

Path params

NameNotes
entityTypeOne of category / brand / tag / ingredient. Anything else → 400 BAD_REQUEST with a list of valid values
slugSlug of the catalog entity

Query

NameTypeNotes
platformPlatform?When APP or WEB, hides banners that target the other platform. Absent or BOTH returns every active banner regardless of platform targeting

Response 200 — array of BannerResponse.

{
  "data": [
    {
      "id": "01J9...",
      "entityType": "brand",
      "entityId": "01J9...",
      "image": "banners/2026-05/festive.jpg",
      "url": "/sale",
      "platform": "BOTH",
      "isActive": true,
      "sortOrder": 0,
      "metadata": null,
      "createdAt": "2026-05-01T08:00:00.000Z",
      "updatedAt": "2026-05-01T08:00:00.000Z",
      "deletedAt": null
    }
  ],
  "message": "Success",
  "statusCode": 200
}

Errors

StatusCodeWhen
400BAD_REQUESTentityType is not one of the four allowed values

  • catalog — owns the category / brand / tag / ingredient slugs that this endpoint resolves against. See catalog.md.
  • storage — resolves image storage keys to public CDN URLs on the client.

On this page