Skip to main content

Orders Module

The ACID‑compliant checkout engine – payment verification, invoice generation, and logistic dispatch.

Razorpay Shiprocket PDF


πŸ“– Table of Contents​


Base Route : /api/v1/orders​

Customer endpoints require a valid access token. Admin endpoints require ADMIN role. Webhooks are public but cryptographically verified.


Endpoints Overview​

MethodEndpointAccessDescription
Customer
POST/checkoutPrivate (Bearer)Create an order, deduct stock, initiate Razorpay payment
POST/verify-paymentPrivate (Bearer)Verify Razorpay payment signature after successful checkout
GET/my-orderPrivate (Bearer)Fetch authenticated user's order history (paginated)
GET/:id/invoicePrivate (Bearer)Stream PDF invoice for a specific order (IDOR protected)
Admin
GET/adminAdminFetch all orders across the platform (fulfillment dashboard)
POST/admin/:id/dispatchAdminGenerate AWB via Shiprocket, mark order as shipped
PATCH/admin/:id/statusAdminManually update order status (state machine)
Webhooks
POST/webhookPublic (HMAC)Razorpay payment confirmation webhook
POST/shiprocket-webhookPublic (API Key)Shiprocket delivery status updates

Rate limits: standardLimiter on all endpoints; checkoutLimiter (5/hour) on /checkout.


Endpoint Details​

Customer Endpoints​

POST /checkout​

Convert the user's cart into an order. This is an ACID transaction that:

  • Validates stock for all items (rolls back if any item is out of stock).
  • Calculates final total (after coupon discount).
  • Creates an order document (status PENDING).
  • Dedicates stock (reduces currentStock).
  • Returns a Razorpay order ID for frontend payment.

Headers: Authorization: Bearer <access_token>
Rate limit: checkoutLimiter (5 per hour per IP)

Request body:

{
"addressId": "64a7b...",
"paymentMethod": "RAZORPAY",
"couponCode": "DIWALI500" // optional
}

Response (200 OK):

{
"success": true,
"statusCode": 200,
"message": "Order created. Proceed to payment.",
"data": {
"orderId": "64a7c...",
"orderNumber": "ORD-12345",
"razorpayOrderId": "order_xyz123",
"amount": 850,
"currency": "INR"
},
"timestamp": "2026-05-22T10:30:00.000Z"
}

The cart is not cleared until payment verification. If payment fails, stock remains reserved but can be released after timeout.

POST /verify-payment​

After the frontend completes Razorpay payment, call this endpoint to verify the signature and confirm the order.

Headers:
Authorization: Bearer <access_token>

Request body:

{
"orderId": "64a7c...", // Reshma order ID
"razorpayPaymentId": "pay_xyz",
"razorpaySignature": "signature_string"
}

Response (200 OK):

{
"success": true,
"statusCode": 200,
"message": "Payment verified. Order confirmed.",
"data": {
"orderStatus": "PROCESSING",
"orderNumber": "ORD-12345"
},
"timestamp": "2026-05-22T10:35:00.000Z"
}

After verification, the user's cart is cleared, and stock is permanently committed. An order confirmation email is queued.

POST /verify-payment​

After the frontend completes Razorpay payment, call this endpoint to verify the signature and confirm the order.

Headers:
Authorization: Bearer <access_token>


GET /my-order​

Fetch the authenticated user's order history with pagination.

Headers:
Authorization: Bearer <access_token>

Query parameters:

ParamTypeDefaultDescription
pageinteger1Page number
limitinteger10Items per page (max 50)
statusstring–Filter by order status (e.g., DELIVERED, PROCESSING)

Response (200 OK):

{
"success": true,
"statusCode": 200,
"message": "Orders retrieved successfully",
"data": {
"orders": [
{
"_id": "...",
"orderNumber": "ORD-12345",
"orderStatus": "DELIVERED",
"pricing": { "subtotal": 900, "discount": 50, "totalAmount": 850 },
"createdAt": "2026-05-20T12:00:00.000Z"
}
],
"meta": { "total": 15, "limit": 10, "page": 1 }
},
"timestamp": "2026-05-22T10:40:00.000Z"
}

GET /:id/invoice​

Stream a PDF invoice for a specific order. The endpoint checks that the order belongs to the authenticated user (IDOR protection).

Headers:
Authorization: Bearer <access_token>

URL Parameter:

  • id – Reshma order ID (not orderNumber).

Response: PDF file stream (Content-Type: application/pdf).

Error: 403 Forbidden if order does not belong to user.

Admin Endpoints​

GET /admin​

Fetch all orders across the platform for the fulfillment dashboard. Supports filtering by status, date range, and pagination.

Headers:
Authorization: Bearer <admin_access_token>

Query parameters:

ParamTypeDefaultDescription
totalinteger1total products
pageinteger1Page number
limitinteger20Items per page (max 100)
totalPagestring–Total page number
statusstring–Filter by order status
startDateISO date–Filter orders created after this date
endDateISO date–Filter orders created before this date

Response (200 OK): Paginated list of orders with customer details.

GET /admin/:id​

Fetch a single order's full detail for the admin fulfillment view

Headers:
Authorization: Bearer <admin_access_token>

Query parameters:

ParamTypeDescription
_idstringOrder Id

POST /admin/:id/dispatch​

Generate a Shiprocket AWB (airway bill) and mark the order as SHIPPED. Requires physical package dimensions.

Headers:
Authorization: Bearer <admin_access_token>

URL Parameter:

  • id – Reshma order ID.

Request body:

{
"length": 15,
"breadth": 10,
"height": 5,
"weight": 0.5
}

Response (200 OK):

{
"success": true,
"statusCode": 200,
"message": "Order dispatched successfully",
"data": {
"orderStatus": "SHIPPED",
"trackingNumber": "AWB123456",
"courierName": "Delhivery"
},
"timestamp": "2026-05-22T11:00:00.000Z"
}

Idempotency: Dispatching an already shipped order returns 409 Conflict.

PATCH /admin/:id/status​

Manually update the order status (state machine). Useful for marking orders as DELIVERED if tracking webhook fails.

Headers:
Authorization: Bearer <admin_access_token>

URL Parameter:

  • id – Reshma order ID.

Request body:

{
"status": "DELIVERED"
}

Allowed transitions: PENDING β†’ PROCESSING β†’ SHIPPED β†’ DELIVERED. Also CANCELLED (before shipment).

Response (200 OK): Returns updated order.


Webhooks​

POST /webhook​

Razorpay webhook for asynchronous payment confirmation. Uses HMAC signature verification.

Headers:
x-razorpay-signature: <signature>

Request body: Raw JSON from Razorpay.

Response (200 OK):

{
"status": "success"
}

POST /shiprocket-webhook​

Shiprocket delivery status update webhook. Updates order status to DELIVERED or RETURNED.

Headers:
x-api-key: <SHIPROCKET_WEBHOOK_SECRET>

Request body: Shiprocket payload (AWB, current_status, etc.)

Response (200 OK):

{
"status": "success",
"received": true
}

Note: Invalid API key returns 401 Unauthorized.


Validation Rules (Zod)​

EndpointFieldRules
/checkoutaddressIdvalid ObjectId, required
paymentMethodenum ["RAZORPAY"], required
couponCodestring, optional
/verify-paymentorderIdvalid ObjectId, required
razorpayPaymentIdstring, required
razorpaySignaturestring, required
/admin/:id/dispatchlengthnumber > 0, required
breadthnumber > 0, required
heightnumber > 0, required
weightnumber > 0, required
/admin/:id/statusstatusenum ["PROCESSING", "SHIPPED", "DELIVERED", "CANCELLED"], required

All schemas use .strict().


Error Responses​

StatusCodeExample messageWhen
400BAD_REQUEST"Negative dimensions not allowed"Zod validation fails
401UNAUTHORIZED"Authentication required"Missing token
403FORBIDDEN"You do not have permission to view this invoice"IDOR on invoice
404NOT_FOUND"Order not found"Invalid order ID
409CONFLICT"This order has already been dispatched"Duplicate dispatch attempt
409CONFLICT"Insufficient stock for product X"Checkout stock validation fails
429TOO_MANY_REQUESTS"Checkout limit exceeded">5 checkouts per hour

Order Status State Machine​

Runbook​

For manual testing with Thunder Client / Postman, see ../../testing/order-runbook.md. The runbook covers:

  • Checkout flow (create order, get Razorpay order ID)
  • Payment verification (mock or real)
  • Invoice download (IDOR test)
  • Admin dispatch (dimensions validation)
  • Webhook simulation


Secure checkout, seamless logistics – the Reshma‑Core order engine.