Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ALEJ4NDRO2025/urban-store/llms.txt

Use this file to discover all available pages before exploring further.

The /api/products/ endpoint serves as the primary entry point to the product catalog. GET requests are fully public and return all active products stored in MongoDB, with optional query-string filters to narrow results. POST requests create a new product document and are restricted to administrators whose JWT payload carries is_admin: true.

GET /api/products/

Retrieve a list of all active products. No authentication is required. Filters can be combined freely; omitting all filters returns the full catalog. Authentication: None (public)

Query Parameters

category
string
Filter products by category name. The comparison is exact (case-sensitive). Example: streetwear
min_price
number
Return only products whose price is greater than or equal to this value. Example: 29.99
max_price
number
Return only products whose price is less than or equal to this value. Example: 99.99
size
string
Filter products that include this size in their sizes array. Matches a single size string exactly. Example: M

Response Fields

Each object in the returned array contains:
id
string
MongoDB ObjectId of the product, serialized as a string.
name
string
Display name of the product.
slug
string
URL-safe unique identifier used in detail, update, and delete endpoints.
price
string
Product price as a decimal string with two decimal places (e.g. "49.99").
category
string
Category the product belongs to.
stock
integer
Total aggregate stock count across all variants.
sizes
array of strings
List of available sizes, e.g. ["S", "M", "L", "XL"].
colors
array of strings
List of available colors, e.g. ["negro", "blanco"].
images
array of strings
Cloudinary URLs for the product’s images.
stock_by_variant
object
Per-variant stock counts keyed by "size|color". Example: {"M|negro": 5, "L|blanco": 3}.

Examples

Fetch all active products:
curl https://urban-store-api.example.com/api/products/
Filter by category and price range:
curl "https://urban-store-api.example.com/api/products/?category=streetwear&min_price=30&max_price=80"
Filter by size:
curl "https://urban-store-api.example.com/api/products/?size=M"
Example response:
[
  {
    "id": "665f1a2b3c4d5e6f7a8b9c0d",
    "name": "Urban Classic Tee",
    "slug": "urban-classic-tee",
    "price": "49.99",
    "category": "streetwear",
    "stock": 24,
    "sizes": ["S", "M", "L", "XL"],
    "colors": ["negro", "blanco"],
    "images": [
      "https://res.cloudinary.com/urban-store/image/upload/v1/products/classic-tee-1.jpg",
      "https://res.cloudinary.com/urban-store/image/upload/v1/products/classic-tee-2.jpg"
    ],
    "stock_by_variant": {
      "S|negro": 4,
      "S|blanco": 3,
      "M|negro": 5,
      "M|blanco": 4,
      "L|negro": 3,
      "L|blanco": 3,
      "XL|negro": 1,
      "XL|blanco": 1
    }
  }
]

POST /api/products/

Create a new product document in MongoDB. Only administrators are authorized. Authentication: Bearer token required. The JWT payload must contain is_admin: true.
Authorization: Bearer <token>

Request Body

name
string
required
Display name of the product. Maximum 200 characters.
slug
string
required
URL-safe unique identifier for the product. Must be unique across the entire catalog. Example: "urban-classic-tee"
description
string
Optional long-form product description.
price
decimal
required
Product price. Stored with two decimal places of precision. Example: 49.99
category
string
required
Category name the product belongs to. Example: "streetwear"
stock
integer
Total aggregate stock count. Defaults to 0.
sizes
array of strings
Available sizes. Example: ["S", "M", "L", "XL"]
colors
array of strings
Available colors. Example: ["negro", "blanco"]
stock_by_variant
object
Per-variant stock keyed by "size|color". Example: {"M|negro": 5, "L|blanco": 3}
images
array of strings
Cloudinary URLs for the product’s images.
is_active
boolean
Whether the product appears in the public catalog. Defaults to true.

Response

201 Created — product was successfully saved:
{
  "message": "Producto creado exitosamente",
  "slug": "urban-classic-tee",
  "name": "Urban Classic Tee"
}
400 Bad Request — validation failed (e.g. duplicate slug, missing required field):
{
  "slug": ["Ya existe un producto con este slug"]
}
403 Forbidden — the Bearer token is missing, invalid, or the user is not an admin.

Example

curl -X POST https://urban-store-api.example.com/api/products/ \
  -H "Authorization: Bearer <admin_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Urban Classic Tee",
    "slug": "urban-classic-tee",
    "description": "A clean staple for every wardrobe.",
    "price": 49.99,
    "category": "streetwear",
    "stock": 24,
    "sizes": ["S", "M", "L", "XL"],
    "colors": ["negro", "blanco"],
    "stock_by_variant": {
      "S|negro": 4,
      "S|blanco": 3,
      "M|negro": 5,
      "M|blanco": 4,
      "L|negro": 3,
      "L|blanco": 3,
      "XL|negro": 1,
      "XL|blanco": 1
    },
    "images": [
      "https://res.cloudinary.com/urban-store/image/upload/v1/products/classic-tee-1.jpg"
    ],
    "is_active": true
  }'
Choose slugs carefully. The slug is used as the URL key for all subsequent GET, PUT, and DELETE operations. Changing a slug after creation will break any existing links or bookmarks pointing to the old URL.

Build docs developers (and LLMs) love