Orders API
Complete reference for shopping cart, wishlist, and order management.
Overview
The Orders module handles the complete e-commerce flow:
Shopping Cart: Guest and authenticated user support
Wishlist: Save items for later
Order Creation: Convert cart to order
Order Tracking: Monitor order status
Order History: View past purchases
Endpoints Summary
Endpoint |
Method |
Auth |
Description |
|---|---|---|---|
|
GET |
Optional |
View cart contents |
|
POST |
Optional |
Add item to cart |
|
PATCH |
Optional |
Update cart item quantity |
|
DELETE |
Optional |
Remove item from cart |
|
POST |
Optional |
Empty cart |
|
GET |
Yes |
View wishlist |
|
POST |
Yes |
Add to wishlist |
|
DELETE |
Yes |
Remove from wishlist |
|
POST |
Yes |
Create order from cart |
|
GET |
Yes |
List user’s orders |
|
GET |
Yes |
Order details |
|
POST |
Yes |
Cancel order |
Shopping Cart
GET /api/orders/cart/
View current cart contents with calculated totals.
Authentication: Optional (session-based for guests)
Example Request:
# Authenticated user
curl https://modestwear.onrender.com/api/orders/cart/ \
-H "Authorization: Bearer eyJ0eXAiOiJKV1Qi..."
# Guest user (uses session cookie)
curl https://modestwear.onrender.com/api/orders/cart/ \
-H "Cookie: sessionid=abc123..."
Success Response (200 OK):
{
"items": [
{
"id": 45,
"variant": {
"id": 12,
"sku": "DRESS-001-M-BLK",
"size": "M",
"color": "Black",
"stock_available": 15,
"product": {
"id": 5,
"name": "Elegant Maxi Dress",
"slug": "elegant-maxi-dress",
"base_price": "1299.99",
"images": [
{
"thumbnail": "https://res.cloudinary.com/.../dress_thumb.jpg",
"is_feature": true
}
]
}
},
"quantity": 2,
"subtotal": "2599.98",
"created_at": "2024-01-20T15:30:00Z"
},
{
"id": 46,
"variant": {
"id": 23,
"sku": "ABAYA-005-L-NVY",
"size": "L",
"color": "Navy",
"stock_available": 8,
"product": {
"id": 12,
"name": "Classic Abaya",
"slug": "classic-abaya",
"base_price": "899.99"
}
},
"quantity": 1,
"subtotal": "899.99"
}
],
"summary": {
"total_items": 3,
"total_price": "3499.97",
"currency": "ZAR"
}
}
Business Logic:
For authenticated users: Fetches cart by user_id
For guest users: Fetches cart by session_key
Calculates subtotals (quantity × price)
Calculates total price
Includes product details and images
Shows current stock availability
Empty Cart Response:
{
"items": [],
"summary": {
"total_items": 0,
"total_price": "0.00",
"currency": "ZAR"
}
}
POST /api/orders/cart/add/
Add product variant to cart.
Authentication: Optional
Request Body:
Field |
Type |
Required |
Description |
|---|---|---|---|
variant_id |
integer |
Yes |
Product variant ID |
quantity |
integer |
No |
Quantity (default: 1) |
Example Request:
curl -X POST https://modestwear.onrender.com/api/orders/cart/add/ \
-H "Authorization: Bearer eyJ0eXAiOiJKV1Qi..." \
-H "Content-Type: application/json" \
-d '{
"variant_id": 12,
"quantity": 2
}'
Success Response (201 Created):
{
"success": true,
"message": "Item added to cart",
"data": {
"cart_item_id": 45,
"variant_id": 12,
"quantity": 2,
"subtotal": "2599.98"
}
}
Business Logic:
Validates variant exists and is active
Checks stock availability
If item already in cart: Updates quantity (adds to existing)
If new item: Creates new cart item
Associates with user_id (authenticated) or session_key (guest)
Returns cart item details
Stock Validation:
Requested quantity must be ≤ stock_available
If insufficient stock, returns error with available quantity
Error Responses:
Insufficient Stock (400):
{
"success": false,
"error": "Insufficient stock. Only 5 items available.",
"available_stock": 5
}
Invalid Variant (404):
{
"success": false,
"error": "Product variant not found or inactive"
}
Invalid Quantity (400):
{
"success": false,
"error": "Quantity must be at least 1"
}
PATCH /api/orders/cart/update/{id}/
Update cart item quantity.
Authentication: Optional
URL Parameters:
id(integer) - Cart item ID
Request Body:
Field |
Type |
Required |
Description |
|---|---|---|---|
quantity |
integer |
Yes |
New quantity (min: 1) |
Example Request:
curl -X PATCH https://modestwear.onrender.com/api/orders/cart/update/45/ \
-H "Authorization: Bearer eyJ0eXAiOiJKV1Qi..." \
-H "Content-Type: application/json" \
-d '{
"quantity": 3
}'
Success Response (200 OK):
{
"success": true,
"message": "Cart item updated",
"data": {
"cart_item_id": 45,
"quantity": 3,
"subtotal": "3899.97"
}
}
Business Logic:
Validates cart item belongs to user/session
Checks new quantity against stock
Updates quantity
Recalculates subtotal
Returns updated item
DELETE /api/orders/cart/remove/{id}/
Remove item from cart.
Authentication: Optional
URL Parameters:
id(integer) - Cart item ID
Example Request:
curl -X DELETE https://modestwear.onrender.com/api/orders/cart/remove/45/ \
-H "Authorization: Bearer eyJ0eXAiOiJKV1Qi..."
Success Response (200 OK):
{
"success": true,
"message": "Item removed from cart"
}
Business Logic:
Validates cart item belongs to user/session
Deletes cart item
Returns success message
POST /api/orders/cart/clear/
Empty entire cart.
Authentication: Optional
Example Request:
curl -X POST https://modestwear.onrender.com/api/orders/cart/clear/ \
-H "Authorization: Bearer eyJ0eXAiOiJKV1Qi..."
Success Response (200 OK):
{
"success": true,
"message": "Cart cleared",
"items_removed": 3
}
Business Logic:
Fetches all cart items for user/session
Deletes all items
Returns count of removed items
Wishlist
GET /api/orders/wishlist/
View user’s saved items.
Authentication: Required
Example Request:
curl https://modestwear.onrender.com/api/orders/wishlist/ \
-H "Authorization: Bearer eyJ0eXAiOiJKV1Qi..."
Success Response (200 OK):
{
"items": [
{
"id": 12,
"variant": {
"id": 34,
"sku": "TUNIC-008-M-BEG",
"size": "M",
"color": "Beige",
"stock_available": 12,
"is_active": true,
"product": {
"id": 18,
"name": "Modest Tunic",
"slug": "modest-tunic",
"base_price": "699.99",
"is_featured": false,
"images": [
{
"image": "https://res.cloudinary.com/.../tunic.jpg",
"thumbnail": "https://res.cloudinary.com/.../tunic_thumb.jpg"
}
]
}
},
"added_at": "2024-01-18T10:20:00Z"
}
],
"total_items": 1
}
Business Logic:
Fetches all wishlist items for authenticated user
Includes full product and variant details
Shows current stock status
Orders by most recently added
POST /api/orders/wishlist/add/
Add product variant to wishlist.
Authentication: Required
Request Body:
Field |
Type |
Required |
Description |
|---|---|---|---|
variant_id |
integer |
Yes |
Product variant ID |
Example Request:
curl -X POST https://modestwear.onrender.com/api/orders/wishlist/add/ \
-H "Authorization: Bearer eyJ0eXAiOiJKV1Qi..." \
-H "Content-Type: application/json" \
-d '{
"variant_id": 34
}'
Success Response (201 Created):
{
"success": true,
"message": "Item added to wishlist",
"data": {
"wishlist_item_id": 12,
"variant_id": 34
}
}
Business Logic:
Validates variant exists
Checks for duplicate (user_id + variant_id unique)
Creates wishlist item
Returns wishlist item ID
Error Responses:
Already in Wishlist (400):
{
"success": false,
"error": "Item already in wishlist"
}
Invalid Variant (404):
{
"success": false,
"error": "Product variant not found"
}
DELETE /api/orders/wishlist/remove/{id}/
Remove item from wishlist.
Authentication: Required
URL Parameters:
id(integer) - Wishlist item ID
Example Request:
curl -X DELETE https://modestwear.onrender.com/api/orders/wishlist/remove/12/ \
-H "Authorization: Bearer eyJ0eXAiOiJKV1Qi..."
Success Response (200 OK):
{
"success": true,
"message": "Item removed from wishlist"
}
Order Management
POST /api/orders/create/
Create order from cart contents.
Authentication: Required
Request Body:
Field |
Type |
Required |
Description |
|---|---|---|---|
address |
string |
Yes |
Delivery address |
payment_method |
string |
Yes |
|
notes |
string |
No |
Order notes |
Example Request:
curl -X POST https://modestwear.onrender.com/api/orders/create/ \
-H "Authorization: Bearer eyJ0eXAiOiJKV1Qi..." \
-H "Content-Type: application/json" \
-d '{
"address": "123 Main Street, Cape Town, Western Cape, 8001, South Africa",
"payment_method": "stripe",
"notes": "Please call before delivery"
}'
Success Response (201 Created):
{
"success": true,
"message": "Order created successfully",
"data": {
"order_id": 89,
"order_number": "MW-2024-00089",
"status": "pending",
"total_price": "3499.97",
"items_count": 3,
"created_at": "2024-01-20T16:45:00Z",
"payment_url": "https://checkout.stripe.com/pay/cs_test_..."
}
}
Business Logic:
Validates user has items in cart
Validates all items still in stock
Creates order record with status=‘pending’
Creates order items (copies cart items)
Captures price at purchase (price_at_purchase field)
Calculates total price
Clears user’s cart
Generates payment URL (Stripe/Paystack)
Sends order confirmation email
Returns order details and payment link
Price History:
Each order item stores
price_at_purchaseEnsures accurate financial records even if product price changes later
Order total is sum of order items, not recalculated from current prices
Stock Management:
Stock is reserved but not decremented until payment confirmed
If payment fails, stock reservation is released
Prevents overselling
Error Responses:
Empty Cart (400):
{
"success": false,
"error": "Cart is empty"
}
Insufficient Stock (400):
{
"success": false,
"error": "Insufficient stock for: Elegant Maxi Dress (M, Black). Only 1 available.",
"out_of_stock_items": [
{
"product": "Elegant Maxi Dress",
"variant": "M, Black",
"requested": 2,
"available": 1
}
]
}
Invalid Address (400):
{
"success": false,
"error": "Delivery address is required"
}
GET /api/orders/
List user’s orders with pagination.
Authentication: Required
Query Parameters:
Parameter |
Type |
Description |
|---|---|---|
status |
string |
Filter by status: |
page |
integer |
Page number (default: 1) |
page_size |
integer |
Items per page (default: 20) |
ordering |
string |
Sort by: |
Example Request:
curl "https://modestwear.onrender.com/api/orders/?status=paid&ordering=-created_at" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1Qi..."
Success Response (200 OK):
{
"count": 15,
"next": "https://modestwear.onrender.com/api/orders/?page=2",
"previous": null,
"results": [
{
"id": 89,
"order_number": "MW-2024-00089",
"status": "paid",
"total_price": "3499.97",
"address": "123 Main Street, Cape Town...",
"created_at": "2024-01-20T16:45:00Z",
"updated_at": "2024-01-20T16:50:00Z",
"items_count": 3,
"items_preview": [
{
"product_name": "Elegant Maxi Dress",
"quantity": 2,
"thumbnail": "https://res.cloudinary.com/.../dress_thumb.jpg"
}
]
},
{
"id": 76,
"order_number": "MW-2024-00076",
"status": "delivered",
"total_price": "1899.98",
"created_at": "2024-01-15T10:20:00Z",
"items_count": 2
}
]
}
Business Logic:
Fetches orders for authenticated user only
Filters by status if provided
Orders by creation date (newest first by default)
Paginates results
Includes item preview for quick reference
GET /api/orders/{id}/
Get detailed order information.
Authentication: Required
URL Parameters:
id(integer) - Order ID
Example Request:
curl https://modestwear.onrender.com/api/orders/89/ \
-H "Authorization: Bearer eyJ0eXAiOiJKV1Qi..."
Success Response (200 OK):
{
"id": 89,
"order_number": "MW-2024-00089",
"status": "paid",
"total_price": "3499.97",
"address": "123 Main Street, Cape Town, Western Cape, 8001, South Africa",
"notes": "Please call before delivery",
"created_at": "2024-01-20T16:45:00Z",
"updated_at": "2024-01-20T16:50:00Z",
"items": [
{
"id": 234,
"variant": {
"id": 12,
"sku": "DRESS-001-M-BLK",
"size": "M",
"color": "Black",
"product": {
"id": 5,
"name": "Elegant Maxi Dress",
"slug": "elegant-maxi-dress",
"images": [
{
"thumbnail": "https://res.cloudinary.com/.../dress_thumb.jpg"
}
]
}
},
"quantity": 2,
"price_at_purchase": "1299.99",
"subtotal": "2599.98"
},
{
"id": 235,
"variant": {
"id": 23,
"sku": "ABAYA-005-L-NVY",
"size": "L",
"color": "Navy",
"product": {
"id": 12,
"name": "Classic Abaya",
"slug": "classic-abaya"
}
},
"quantity": 1,
"price_at_purchase": "899.99",
"subtotal": "899.99"
}
],
"status_history": [
{
"status": "pending",
"timestamp": "2024-01-20T16:45:00Z"
},
{
"status": "paid",
"timestamp": "2024-01-20T16:50:00Z"
}
]
}
Business Logic:
Validates order belongs to authenticated user
Fetches complete order details
Includes all order items with product info
Shows price at purchase (historical pricing)
Includes status history for tracking
Authorization:
Users can only view their own orders
Admin users can view all orders
POST /api/orders/{id}/cancel/
Cancel a pending order.
Authentication: Required
URL Parameters:
id(integer) - Order ID
Request Body:
Field |
Type |
Required |
Description |
|---|---|---|---|
reason |
string |
No |
Cancellation reason |
Example Request:
curl -X POST https://modestwear.onrender.com/api/orders/89/cancel/ \
-H "Authorization: Bearer eyJ0eXAiOiJKV1Qi..." \
-H "Content-Type: application/json" \
-d '{
"reason": "Changed my mind"
}'
Success Response (200 OK):
{
"success": true,
"message": "Order cancelled successfully",
"data": {
"order_id": 89,
"status": "cancelled",
"refund_status": "pending"
}
}
Business Logic:
Validates order belongs to user
Checks order status is ‘pending’ or ‘paid’
Updates status to ‘cancelled’
Releases stock reservation
Initiates refund if payment was made
Sends cancellation confirmation email
Logs cancellation reason
Cancellation Rules:
Pending orders: Can be cancelled anytime
Paid orders: Can be cancelled within 24 hours
Shipped orders: Cannot be cancelled (must return)
Delivered orders: Cannot be cancelled (must return)
Error Responses:
Cannot Cancel (400):
{
"success": false,
"error": "Order cannot be cancelled. Status: shipped"
}
Not Found (404):
{
"success": false,
"error": "Order not found"
}
Order Status Lifecycle
pending → paid → shipped → delivered
↓
cancelled
Status Descriptions:
Status |
Description |
User Actions |
Admin Actions |
|---|---|---|---|
pending |
Order created, awaiting payment |
Cancel, Pay |
Cancel, Mark as paid |
paid |
Payment confirmed |
Cancel (24h), View |
Mark as shipped |
shipped |
Order dispatched |
Track, Contact support |
Update tracking, Mark as delivered |
delivered |
Order received |
Review, Return (7 days) |
- |
cancelled |
Order cancelled |
View refund status |
Process refund |
Guest Cart Migration
When a guest user logs in or registers, their cart is automatically migrated:
Migration Process:
User logs in/registers
System fetches guest cart by session_key
Merges with user’s existing cart
Updates cart items:
session_key=null,user_id=<user_id>Removes duplicate items (keeps higher quantity)
Clears session cart
Example:
Guest Cart: User Cart: Merged Cart:
- Item A (qty 2) - Item B (qty 1) - Item A (qty 2)
- Item C (qty 1) - Item C (qty 3) - Item B (qty 1)
- Item C (qty 3) ← kept higher qty
Stock Management
Stock Reservation
Stock reserved when order created (status=‘pending’)
Reservation expires after 30 minutes if unpaid
Stock decremented when payment confirmed (status=‘paid’)
Stock Release
Released when order cancelled
Released when reservation expires
Released when payment fails
Low Stock Alerts
Admin notified when stock < 5 units
Celery task checks hourly
Email sent to admin
Payment Integration
Stripe
# Payment flow
1. Order created → status='pending'
2. Stripe checkout session created
3. User redirected to Stripe
4. Webhook receives payment confirmation
5. Order status updated to 'paid'
6. Stock decremented
7. Confirmation email sent
Paystack
# Payment flow (similar to Stripe)
1. Order created → status='pending'
2. Paystack transaction initialized
3. User redirected to Paystack
4. Webhook receives payment confirmation
5. Order status updated to 'paid'
Best Practices
Check stock before checkout - Validate availability
Handle cart migration - Merge guest cart on login
Show order status - Keep users informed
Enable cancellation - Allow users to cancel pending orders
Store price history - Use price_at_purchase for accuracy
Implement retry logic - Handle payment webhook failures
Send notifications - Email on order status changes
Next Steps
Explore Outfits API
Learn about Error Handling