← Documentation
Variant API Contract (Strict)
This document is the source of truth for product variants across backend, storefront, and admin.
If any request/response shape below changes, update this page and all affected DTOs/types in the same PR.
Non-negotiable invariants
- Product purchase logic is variant-first (
variantIdis required for quote/checkout). variantIdmust belong toproductId(validated server-side).- Price is resolved on server from DB:
unitCents = variant.priceOverrideCents ?? product.priceCents
- Inventory is deducted/restored per variant only.
product.stockQuantityis derived aggregate from variants (not source of truth).- Admin stock adjustment on multi-variant product requires
variantId.
Product contracts
Create/Update product (POST /admin/products, PUT /admin/products/:id)
Required payload fields (simplified):
{
"name": "Baggy Shirt",
"slug": "baggy-shirt",
"priceCents": 499900,
"currency": "PKR",
"variants": [
{
"id": "optional-on-update",
"color": "Black",
"size": "M",
"sku": "BAGGY-BLK-M",
"stockQuantity": 12,
"priceOverrideCents": 479900,
"isActive": true
}
]
}
Product response (GET /store/products*, GET /admin/products*)
Must include:
variants[]with{ id, color, size, sku, stockQuantity, priceOverrideCents, isActive }colors[](derived unique list)sizes[](derived unique list)stockQuantityandinStockderived from variants
Checkout contracts (store)
Quote (POST /store/orders/quote)
items[] shape:
{
"productId": "uuid",
"variantId": "uuid",
"color": "Black",
"size": "M",
"quantity": 1
}
Checkout (POST /store/orders/checkout)
Same items[] shape as quote.
Quote and order item responses
Each line item must include:
productIdvariantIdcolor(snapshot)size(snapshot)quantityunitCents
Inventory contracts
Admin stock adjust (PATCH /admin/products/:id/stock)
Payload:
{
"variantId": "uuid-when-product-has-multiple-variants",
"quantityDelta": -2,
"reference": "Damage write-off"
}
Inventory history (GET /admin/inventory/products/:productId/movements)
Supported query params:
pagelimitvariantId(optional filter)
Each movement row includes:
variantIdvariantColorvariantSizequantityDeltastockBeforestockAfter- audit fields (
type,reference, performer info, timestamps)
Regression checklist (must pass before merge)
- Create product with 2+ variants from admin form.
- Storefront product page can select color/size and adds correct
variantIdto cart. - Quote + checkout payload sends
variantId. - Order in admin displays
color / size. - Stock deduction reduces only selected variant.
- Admin movement history filter by
variantIdworks.