The product feed is the public storefront of Hermes. Any visitor can browse all available products from all stores without authentication. When an unauthenticated user attempts an action that requires login (cart, store), the frontend handles the redirect — the backend simply returns 401.
Endpoint
| Method |
Route |
Auth |
Description |
| GET |
/api/v1/products |
Public |
Returns all products from all stores |
Supported query parameters
| Param |
Type |
Description |
search |
string |
Filters products by name (partial match) |
page |
int |
Page number (default: 0) |
size |
int |
Items per page (default: 20) |
Response example
{
"content": [
{
"id": 1,
"name": "Black T-Shirt",
"description": "100% cotton",
"price": 29.90,
"imageUrl": "https://...",
"storeName": "John's Store",
"storeSlug": "johns-store"
}
],
"totalElements": 42,
"totalPages": 3,
"currentPage": 0
}
Business rules
- The route is fully public — no authentication required
- Results are paginated by default (20 items per page)
- The
search param filters by product name using partial matching
- Each product in the response includes the store name and slug
- An empty result returns
200 OK with content: [], never 404
Acceptance criteria
The product feed is the public storefront of Hermes. Any visitor can browse all available products from all stores without authentication. When an unauthenticated user attempts an action that requires login (cart, store), the frontend handles the redirect — the backend simply returns
401.Endpoint
Supported query parameters
searchpagesizeResponse example
{ "content": [ { "id": 1, "name": "Black T-Shirt", "description": "100% cotton", "price": 29.90, "imageUrl": "https://...", "storeName": "John's Store", "storeSlug": "johns-store" } ], "totalElements": 42, "totalPages": 3, "currentPage": 0 }Business rules
searchparam filters by product name using partial matching200 OKwithcontent: [], never404Acceptance criteria
GET /api/v1/productsis accessible without a JWT tokenpageandsizeparams?search=shirtreturns all products whose name contains "shirt" (case-insensitive)storeNameandstoreSlug200 OKwithcontent: []