Swagger UI Data Viewer GitHub

Market API

Complete e-commerce REST API for QA practice — grocery shopping simulation with products, basket, and orders.

🌐 This page is public

No login required to read this documentation. Register at /profile.html to get your personal API key and start testing.

Quick Start

1
Register an account
POST /api/register → returns your api_key
2
Browse your products
GET /api/groceries → Authorization: qac_live_...
3
Add items to basket
POST /api/basket → { "product_id": "...", "quantity": 2 }
4
Place an order
POST /api/orders → basket cleared, stock decremented

Description

The Market application is a grocery e-commerce API that simulates a real online supermarket. It is one of several practice applications in the qacloud platform, designed specifically for QA engineers to learn and practice API testing.

Each user gets their own isolated data environment: a personal product catalog pre-seeded with grocery items, an empty basket, and an empty order history. Your data is never mixed with other users' data. This makes it safe to run destructive tests (delete, reset) without affecting other testers.

What makes it interesting for QA?

Product Categories (default seed data)

CategoryExample productsTypical temperature zone
DairyMilk, Yogurt, Cheese, ButterChilled
BakeryBread, Croissants, RollsDry / Room Temperature
MeatChicken, Beef, PorkChilled / Frozen
ProduceApples, Tomatoes, CarrotsChilled / Room Temperature
BeveragesOrange Juice, Sparkling WaterChilled / Dry
FrozenIce Cream, Frozen PizzaFrozen
DeliHam, Salami, HummusChilled
PantryPasta, Rice, Canned BeansDry

UI Overview

The Market application ships with a built-in browser UI accessible at /market/<username> after login. It is divided into three tabs — Products, Basket, and Orders — with a live stats dashboard at the top of every screen.

Stats Dashboard

A persistent header bar displays four live counters, updated whenever you switch tabs or click Refresh:

CounterWhat it showsWhen it updates
ProductsTotal number of products in your catalogAfter creating or deleting a product
Basket ItemsTotal quantity of all items currently in basketAfter adding, removing, or placing an order
OrdersTotal number of orders placedAfter placing or deleting an order
Total ValueSum of (price × stock) across the entire product catalogAfter any product price or stock change

The Total Value stat (e.g. $9391.80) reflects the monetary worth of your full inventory — not the basket total or order total. It changes when product prices or stock levels change.

Products Tab

The default view after login. Shows your full grocery catalog as a scrollable card grid with filtering and sorting controls.

Basket Tab

Shows all items currently in your shopping basket with full quantity management and a live order summary.

Orders Tab

Lists all placed orders, newest first. Each order card is expandable to show line items and a status editor.

Top Navigation Bar

Persistent across all three tabs:

Products Flow

All product endpoints require the Authorization: qac_live_... header. Products are scoped to the authenticated user only.

1
Seed / Reset Products
On registration, 25-30 grocery products are pre-seeded. At any time you can call POST /api/reset to restore the catalog to the default state (deletes all custom products first).
POST /api/reset → 200 { message: "Data reset successfully" }
2
List / Filter
Get all products with optional filtering by category, temperature_zone, weighted flag, and sort order. Multiple categories can be comma-separated.
GET /api/groceries
GET /api/groceries/filter?category=Dairy,Meat&sort=desc
3
Create a Product
Required fields: product_name, price, category. Optional: stock, temperature_zone, weighted, details.
POST /api/groceries → 201 { ...product }
4
Update / Delete
Partial updates supported on PUT (send only fields you want to change). Delete removes the product and cascades to any basket items containing it.
PUT /api/groceries/:id
DELETE /api/groceries/:id

Basket Flow

1
Add Item
Checks stock availability. If the product is already in the basket, quantities are merged (not duplicate rows). The combined quantity must not exceed available stock.
POST /api/basket { "product_id": "uuid", "quantity": 2 } → 201
2
View Basket
Returns all items with product details, current price, and quantities.
GET /api/basket → { "items": [...] }
3
Update Quantity
Update by product_id — sets absolute quantity (not additive like POST).
PUT /api/basket { "product_id": "uuid", "quantity": 5 } → 200
4
Remove / Clear
Remove one product or clear the entire basket.
DELETE /api/basket/:product_id
DELETE /api/basket/clear

Order Flow

⚠️ Order placement is irreversible for stock

Once placed, stock is decremented immediately. There is no automatic stock restoration on order cancel or delete — this is intentional for testing stock-related scenarios.

1
Fill Basket
Add at least one item to the basket. The basket must not be empty when placing an order.
2
Place Order
Server snapshots product name, category, price, and temperature_zone into order_items. Total is computed server-side. Basket is cleared automatically. Stock is decremented per item.
POST /api/orders { "notes": "optional" } → 201 { order_number, order_items, ... }
3
Track Order
View all orders or a specific order with its items.
GET /api/orders
GET /api/orders/:id
4
Update Status
Update order status or notes. Valid statuses: pending · processing · shipped · delivered · cancelled.
PUT /api/orders/:id { "status": "delivered" } → 200

Product Endpoints

All require Authorization: qac_live_... header.

GET /api/groceries List all products

Query Params

  • sort=asc (default) or sort=desc — sort by name

Success Response — 200

{ "products": [ { "id": "...", "product_name": "Organic Milk", "category": "Dairy", "price": 2.49, "stock": 100, ... } ] }
GET /api/groceries/filter Filter products

Query Params

  • category=Dairy or category=Dairy,Meat
  • temperature_zone=Chilled — one of: Dry, Frozen, Chilled, Room Temperature
  • weighted=true or weighted=false
  • sort=asc (default) or sort=desc
POST /api/groceries Create a product

Request Body

{
  "product_name": "Cheddar Cheese",   // required
  "price": 4.99,                       // required, positive number
  "category": "Dairy",                 // required
  "temperature_zone": "Chilled",       // optional
  "weighted": false,                   // optional, default false
  "stock": 50,                         // optional, default 0
  "details": {                         // optional JSONB
    "brand": "Vintage Gold",
    "weight": "400g"
  }
}

Success — 201

{ "id": "...", "product_name": "Cheddar Cheese", ... }

Errors

  • 400 — Missing required fields or invalid temperature_zone
PUT /api/groceries/:id Update product (partial update supported)

// Only include fields you want to change
{ "price": 5.49, "stock": 30 }
  • 404 — Product not found or belongs to different user
DELETE /api/groceries/:id Delete product (cascades from basket)

Deleting a product automatically removes it from all basket entries (CASCADE). Existing order items are not affected (they store a snapshot).

  • 404 — Product not found
POST /api/reset Reset catalog to default demo products

Deletes all existing products and re-seeds the default grocery catalog. Basket and orders are not affected. Useful in test setup/teardown scripts.

// No body required
POST /api/reset
Authorization: qac_live_...

→ 200  { "message": "Data reset successfully", "count": 28 }

Basket Endpoints

POST /api/basket Add item to basket

{ "product_id": "uuid", "quantity": 2 }

If the product is already in the basket, quantities are merged (existing + new). Combined quantity must not exceed stock.

  • 400 — quantity < 1
  • 400 — Not enough stock (includes current basket qty)
  • 404 — Product not found
PUT /api/basket Update item quantity by product_id

{ "product_id": "uuid", "quantity": 5 }

Sets the quantity to the specified value (not additive). Must be ≥ 1.

DELETE /api/basket/clear Clear entire basket

Removes all items. Returns 200 even if basket was already empty.

DELETE /api/basket/:product_id Remove one product from basket

Removes the product row from the basket. Quantity removed entirely (not decremented).

Order Endpoints

POST /api/orders Place order from current basket

{ "notes": "Leave at door" }   // body is optional
  • Basket must not be empty
  • Items with deleted products are auto-cleaned before order creation
  • Basket is cleared after successful order
  • Stock is decremented per item
PUT /api/orders/:id Update order status or notes

{ "status": "shipped" }
// Valid statuses: pending · processing · shipped · delivered · cancelled

Test Cases

PRODUCTS

TC-PROD-001 Get all products returns 200 with non-empty array after registration Positive
Expected200 · { "products": [...] }, array length ≥ 1
TC-PROD-002 Create product with all optional fields Positive
Inputproduct_name, price, category, temperature_zone, weighted, stock, details
Expected201 · all fields reflected in response
TC-PROD-003 Create product with invalid temperature_zone Negative
Inputtemperature_zone="Warm"
Expected400 · must be one of accepted values
TC-PROD-004 Filter by multiple categories (comma-separated) Positive
InputGET /api/groceries/filter?category=Dairy,Meat
Expected200 · only Dairy and Meat products returned
TC-PROD-005 Invalid API key returns 401 Security
InputAuthorization: invalid-key
Expected401 · unauthorized
TC-PROD-006 Get product by ID belonging to different user returns 404 Security
InputValid product UUID from User A, but authorized as User B
Expected404 · item not found (data isolation)
TC-PROD-007 Update price only (partial update) Edge
InputPUT /api/groceries/:id { "price": 9.99 }
Expected200 · only price changed, all other fields preserved

BASKET

TC-BASK-001 Add product to basket Positive
Expected201 · basket item created, quantity = requested
TC-BASK-002 Add same product twice merges quantities Edge
InputAdd product (qty 2), then add same product (qty 3)
Expected200 · basket shows quantity = 5 (one row, not two)
TC-BASK-003 Add more than available stock Negative
InputProduct with stock=5, add quantity=6
Expected400 · "Not enough stock. Available: 5"
TC-BASK-004 Add to basket considers existing basket quantity Edge
InputStock=5, basket already has 3 → try to add 3 more
Expected400 · "Not enough stock. Available: 5, Already in basket: 3"
TC-BASK-005 Add item with quantity 0 Negative
Expected400 · "quantity must be at least 1"
TC-BASK-006 Delete product cascades from basket Edge
StepsAdd product to basket → delete product → fetch basket
Expected200 · basket shows 0 items (cascade delete)

ORDERS

TC-ORD-001 Place order with items in basket Positive
Expected201 · order_number matches /^O\d{5}$/, basket is empty after
TC-ORD-002 Place order with empty basket Negative
Expected400 · "Basket is empty"
TC-ORD-003 Order total_amount matches sum of (price × quantity) for all items Positive
StepsKnow product prices, add to basket → place order → verify total
ExpectedComputed total matches expected value (2 decimal places)
TC-ORD-004 price_at_purchase does not change after product price update Edge
StepsPlace order → update product price → fetch order
Expectedprice_at_purchase unchanged (snapshot)
TC-ORD-005 Stock is decremented after order placement Positive
StepsNote stock → buy N units → check stock
ExpectedNew stock = original − N
TC-ORD-006 Update order status from pending to invalid value Negative
Input{ "status": "returned" }
Expected400 · validation error or DB constraint error
TC-ORD-007 Order number format validation Edge
Expectedorder_number matches regex /^O\d{5}$/

UI Test Cases

These test cases target the browser UI at /market/<username>. Use a real browser — Chrome, Firefox, or Safari.

Stats Dashboard

TC-UI-001 Basket Items counter increments after adding a product Positive
StepsNote Basket Items stat → add a product with qty 3 → check stat
ExpectedBasket Items counter increases by 3
TC-UI-002 Stats update after placing order: basket resets, orders increments Positive
StepsNote Orders=0, Basket Items=N → click PLACE ORDER
ExpectedOrders counter becomes 1; Basket Items becomes 0
TC-UI-003 Total Value reflects catalog inventory worth, not basket or order totals Edge
StepsRecord Total Value (e.g. $9391.80) → clear entire basket
ExpectedTotal Value unchanged — it is computed from product catalog, not basket

Products Tab — UI

TC-UI-004 Sidebar category filter shows only products in that category Positive
StepsClick "Dairy" in the left sidebar
ExpectedOnly product cards with a "Dairy" category badge are shown; no other categories visible
TC-UI-005 Sort Z→A reverses product grid order Positive
StepsNote first product in A→Z view → switch Sort By to Z→A
ExpectedThe first card is now the last name alphabetically; full list is reversed
TC-UI-006 Every product card displays all required fields Positive
ExpectedEach card shows: emoji icon, product name, color-coded category badge, price, temperature zone, stock level
TC-UI-007 Reset (top nav) restores deleted products Positive
StepsDelete a product via the UI → click Reset in top navigation bar
ExpectedProduct reappears; Products stat returns to default seeded count

Basket Tab — UI

TC-UI-008 Quantity stepper updates subtotal in real time Positive
StepsAdd "100% Florida Orange Juice" (qty 3, $6.50 each) → click + in basket
ExpectedSubtotal changes from $19.50 to $26.00; Order Summary total updates to match
TC-UI-009 Empty basket shows correct empty state message Positive
StepsPlace an order or click CLEAR ALL → switch to Basket tab
ExpectedCart icon shown with message: "Your basket is empty. Start marketing!"
TC-UI-010 REMOVE button removes only that specific product Positive
StepsAdd 2 different products → click REMOVE on one item
ExpectedOnly the clicked product is removed; the other item remains with quantity unchanged
TC-UI-011 PLACE ORDER button unavailable when basket is empty Edge
StepsNavigate to Basket tab with no items
ExpectedPLACE ORDER button is absent or disabled; attempting to order does nothing
TC-UI-012 Order Summary total matches sum of all item subtotals Positive
StepsAdd multiple products with different quantities → check Order Summary
ExpectedTotal = sum of all (unit price × quantity); consistent with individual subtotals shown on each row

Orders Tab — UI

TC-UI-013 Order number matches format O##### (O + 5 digits) Positive
StepsPlace any order → open Orders tab
ExpectedOrder number is exactly 6 characters: letter O followed by exactly 5 digits (e.g. O40699)
TC-UI-014 Status badge color is correct per status value Positive
StepsPlace order (PENDING) → change status to DELIVERED → then to CANCELLED
ExpectedPENDING = yellow badge; DELIVERED = green badge; CANCELLED = red badge
TC-UI-015 Order items line shows correct name, quantity, and subtotal Positive
StepsOrder "100% Florida Orange Juice" × 3 at $6.50 each
ExpectedItems section shows: 100% Florida Orange Juice × 3 — $19.50
TC-UI-016 Order timestamp is close to actual time of placement Positive
StepsNote system time → click PLACE ORDER → read timestamp in Orders tab
ExpectedDisplayed timestamp (date + time) matches actual time within a few seconds
TC-UI-017 DELETE ORDER removes order and decrements counter Negative
StepsPlace order (Orders=1) → click DELETE ORDER
ExpectedOrder disappears from list; Orders stat counter decrements to 0
TC-UI-018 Basket clears automatically after PLACE ORDER Positive
StepsAdd items to basket → click PLACE ORDER → switch to Basket tab
ExpectedEmpty state message shown; Basket Items stat = 0; Order appears in Orders tab

QA Tasks

Hands-on tasks for QA engineers — both manual and automation. Use these to explore the API, find edge cases, and build automation skills.

🔑 Before you start

Register at /profile.html, grab your api_key, and keep it ready. Run POST /api/reset to get a clean, known starting state before each task.

Task 1: The Full Shopping Journey
Manual

Complete the end-to-end shopping flow manually using a REST client (Postman, Insomnia, or curl). Document each step and verify responses.

  • Register a new account and capture the api_key
  • List all products and find 3 different categories
  • Add 2 different products to the basket
  • Verify the basket GET shows exactly those 2 items
  • Place the order and record the order_number
  • Verify the basket is empty after the order
  • Verify the product stock decreased by ordered quantity
  • Update the order status to delivered
Task 2: Break the Stock System
Manual

Explore all the ways stock validation can be violated. Try to find edge cases the system handles (or doesn't handle).

  • Find a product with stock = 0 and try to add it to the basket
  • Set a product's stock to 5, add 3 to basket, then try to add 3 more
  • Add the maximum stock amount to basket — verify it allows it
  • Add stock + 1 — verify the error message is helpful
  • Place an order, then try to add the same product quantity that should now be depleted
  • Create a product with stock=0 and verify it appears but cannot be added to basket
Task 3: Data Isolation Audit
Manual

Verify that the API correctly isolates data between users. Attempt cross-user data access and confirm it is properly blocked.

  • Register two accounts — capture both API keys
  • Create products with User A's key, verify User B cannot see them
  • Use User B's key to GET User A's product ID directly — expect 404
  • Try to update/delete User A's product using User B's key — expect 404
  • Add items to User A's basket — verify User B's basket is empty
  • Place an order as User A — verify it doesn't appear in User B's orders
Task 4: Filter & Sort Validation
Manual + Auto

Thoroughly test the product filter endpoint with all parameter combinations, ensuring accurate filtering and sorting behavior.

  • Filter by each temperature_zone value and verify only correct products returned
  • Filter by invalid temperature_zone — expect 400
  • Filter by weighted=true — all returned products must have weighted=true
  • Combine category + temperature_zone filters
  • Filter by multiple categories: category=Dairy,Meat
  • Test sort=asc — verify alphabetical order (A→Z)
  • Test sort=desc — verify reverse alphabetical order (Z→A)
  • Filter by a category that doesn't exist — expect empty array, not error
Task 5: Automate the Happy Path
Automation

Write an automated test script that covers the full positive flow: register → get products → add to basket → place order → verify order.

  • Auto-generate unique test credentials (e.g., timestamp-based username)
  • Register and extract api_key from response
  • GET products and select the first one with stock > 0
  • Add 1 unit to basket and verify 201 response
  • GET basket and assert item count = 1
  • POST /api/orders and assert order_number matches /^O\d{5}$/
  • Assert total_amount equals product price × quantity
  • Assert basket is empty after order
Task 6: CRUD Product Automation Suite
Automation

Build a complete test suite covering Create, Read, Update, Delete for the products API with both positive and negative cases.

  • Setup: register and reset data before suite runs
  • Test POST with only required fields → expect 201
  • Test POST with all fields including details JSONB → expect 201
  • Test POST missing product_name → expect 400
  • Test POST with invalid temperature_zone → expect 400
  • Test PUT partial update: only change price → other fields unchanged
  • Test DELETE → product disappears from GET all
  • Test DELETE nonexistent ID → expect 404
  • Test GET with invalid API key → expect 401
  • Teardown: POST /api/reset to restore catalog
Task 7: Stress Test the Basket
Automation

Write automation that targets basket edge-cases, particularly around quantity merging, stock limits, and concurrent additions.

  • Add product A (qty=2), add same product again (qty=3) → basket qty=5
  • Add product with qty=0 → expect 400
  • Add product with qty=-1 → expect 400
  • Add product with qty exceeding stock → expect 400 with helpful message
  • Add product with exact stock amount → expect 201
  • Add product with stock+1 after item is in basket → expect 400
  • Clear basket → GET basket → verify empty array
  • Remove specific product → verify only that product is removed
Task 8: Price Snapshot Integrity
Manual + Auto

Verify the price snapshot behavior — a placed order's items must retain the price at the time of purchase, even if the product is later modified or deleted.

  • Create a product with price=10.00
  • Add it to basket and place order — record order item's price_at_purchase
  • Update product price to 99.99
  • Fetch the order — verify price_at_purchase is still 10.00
  • Delete the product entirely
  • Fetch the order — verify order items still show product data
  • Automate this as a regression test
Task 9: Auth Security Testing
Manual

Probe the authentication system for common vulnerabilities and verify security controls are in place.

  • Attempt to register with SQL injection in username: admin'; DROP TABLE users;--
  • Attempt XSS in username field: <script>alert(1)</script>
  • Try brute-force: 10 incorrect login attempts — verify system behaviour
  • Attempt to access GET /api/profile without any auth → expect 401
  • Modify the JWT token payload (decode, change userId, re-encode) → expect 401
  • Use an expired JWT if possible → expect 401
  • Try registering with an empty string password ""
Task 10: Build a Postman Collection
Manual + Auto

Build a complete, shareable Postman collection for the Market API with environment variables, pre-request scripts, and test scripts.

  • Create environment variables: base_url, api_key, product_id, order_id
  • Add register request with test script to extract and save api_key
  • Add a pre-request script that calls POST /api/reset before product tests
  • Add test assertions for status codes on every request
  • Add test assertions for response body shape (required fields present)
  • Chain requests: create product → save ID → use in basket → place order → save order ID
  • Add a negative test folder with expected error scenarios
  • Export collection and document how to import and run it