Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Pragyat-Nikunj/Learning-Management-System-backend/llms.txt

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

The LMS Backend uses Stripe Checkout to process course purchases. The flow works in three steps: your client calls the create-checkout-session endpoint to get a Stripe session URL, the student completes payment on Stripe’s hosted page, and Stripe calls the webhook endpoint to confirm the charge. The CoursePurchase document starts in pending status and is updated to completed or failed based on the Stripe charge.succeeded or charge.failed event.
All payment endpoints are prefixed with /api/v1/payments. Set STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET in your environment before using these endpoints. See Environment Setup for the full variable list.

POST /api/v1/payments/create-checkout-session

Create a Stripe Checkout session for a course purchase. The server looks up the course price, creates the Stripe session in payment mode, and records a CoursePurchase document with status: "pending". The Stripe session URL is returned in the response for your client to redirect the student to. Auth required: Yes

Request body

courseId
string
required
MongoDB ObjectId of the course the student wants to purchase.

Response — 201

success
boolean
true on success.
message
string
"Stripe checkout initiated successfully."
data
object
curl --request POST \
  --url http://localhost:4000/api/v1/payments/create-checkout-session \
  --cookie cookies.txt \
  --header 'Content-Type: application/json' \
  --data '{"courseId": "64f1a2b3c4d5e6f7a8b9c0d1"}'

Errors

StatusCondition
401Missing or invalid auth cookie
404Course not found
500Stripe session creation failed

POST /api/v1/payments/webhook

Receive and process Stripe webhook events. This endpoint must receive the raw request body (not JSON-parsed) so that Stripe’s signature verification can succeed. The route uses express.raw({ type: 'application/json' }) middleware for this reason. Auth required: No — secured by Stripe signature verification using STRIPE_WEBHOOK_SECRET.
Do not send this endpoint a regular JSON body — the raw bytes are required for the stripe-signature header verification. Any proxy or middleware that parses the body before it reaches this route will cause signature verification to fail with a 400 error.

Headers

stripe-signature
string
required
The Stripe-Signature header set by Stripe on every webhook delivery. Used to verify the event payload has not been tampered with.

Handled event types

Fired when a payment charge is successfully captured. The handler finds the matching CoursePurchase record by paymentId (the charge ID) and updates its status to "completed".
Fired when a payment charge fails. The handler finds the matching CoursePurchase record by paymentId and updates its status to "failed".
All other event types are acknowledged but not processed.

Response — 200

{
  "received": true
}
A 200 response is always returned once the event is acknowledged, even for unhandled event types. This tells Stripe not to retry delivery.
# Forward events to your local server using the Stripe CLI:
stripe listen --forward-to http://localhost:4000/api/v1/payments/webhook

# Trigger a test charge.succeeded event:
stripe trigger charge.succeeded

Errors

StatusCondition
400Stripe signature verification failed (wrong secret, tampered body, or body was pre-parsed)

GET /api/v1/payments/courses/:courseId/purchase-status

Check whether the authenticated user has purchased a specific course and what the current status of that purchase is. Auth required: Yes

Path parameters

courseId
string
required
MongoDB ObjectId of the course to check.

Response — 200

status
string
"success"
data
object
curl --request GET \
  --url http://localhost:4000/api/v1/payments/courses/64f1a2b3c4d5e6f7a8b9c0d1/purchase-status \
  --cookie cookies.txt
Example 200 response — completed purchase
{
  "status": "success",
  "data": {
    "course": {
      "_id": "64f1a2b3c4d5e6f7a8b9c0d1",
      "title": "Introduction to Node.js",
      "description": "A complete beginner course covering Express, MongoDB, and authentication.",
      "price": 49
    },
    "purchaseStatus": "completed"
  }
}

Errors

StatusCondition
401Missing or invalid auth cookie
404Course not found

GET /api/v1/payments/purchased-courses

Retrieve all courses the authenticated user has purchased with a "completed" status. Results are sorted by most recently purchased and include the course title, description, and price. Auth required: Yes

Response — 200

status
string
"success"
data
object
curl --request GET \
  --url http://localhost:4000/api/v1/payments/purchased-courses \
  --cookie cookies.txt
Example 200 response
{
  "status": "success",
  "data": {
    "purchase": [
      {
        "_id": "66b1c2d3e4f5a6b7c8d9e0f1",
        "course": {
          "_id": "64f1a2b3c4d5e6f7a8b9c0d1",
          "title": "Introduction to Node.js",
          "description": "A complete beginner course covering Express, MongoDB, and authentication.",
          "price": 49
        },
        "amount": 49,
        "currency": "USD",
        "paymentMethod": "stripe",
        "paymentId": "cs_test_a1b2c3d4e5f6g7h8i9j0",
        "createdAt": "2024-11-15T14:30:00.000Z"
      }
    ]
  }
}

Errors

StatusCondition
401Missing or invalid auth cookie

During local development, use the Stripe CLI to forward webhook events to your local server and trigger test events. Run stripe listen --forward-to http://localhost:4000/api/v1/payments/webhook before testing the checkout flow end-to-end.

Build docs developers (and LLMs) love