🔐 Authentication

Authentication Method: Bearer token via Laravel Sanctum.
After login/register, include the token in all protected requests:
Authorization: Bearer {your_token}
Tokens are valid until manually revoked (no expiration by default). To revoke, use logout.
POST /register
Create a new user account.
📝 Request Body
{
    "name": "John Doe",
    "email": "john@example.com",
    "password": "secret123",
    "password_confirmation": "secret123"
}
✅ Example Response (201)
{
    "user": {
        "id": 1,
        "name": "John Doe",
        "email": "john@example.com",
        "role": 1,
        "type": null,
        "wallet_balance": 0,
        "membership_validity_from": null,
        "membership_validity_to": null,
        "created_at": "2025-03-28T10:00:00.000000Z",
        "updated_at": "2025-03-28T10:00:00.000000Z"
    },
    "token": "1|abc123def456..."
}
POST /login
Authenticate and get a token.
📝 Request Body
{
    "email": "john@example.com",
    "password": "secret123"
}
✅ Example Response (200)
{
    "user": { ... },
    "token": "2|xyz789..."
}
POST /forgot-password
Send password reset link to email.
📝 Request Body
{"email": "john@example.com"}
✅ Example Response (200)
{"message": "We have emailed your password reset link!"}
POST /reset-password
Reset password using token from email.
📝 Request Body
{
    "token": "reset_token_here",
    "email": "john@example.com",
    "password": "newpassword",
    "password_confirmation": "newpassword"
}
✅ Example Response (200)
{"message": "Your password has been reset!"}
POST /logout
Revoke the current access token.
📝 Headers
Authorization: Bearer {token}
✅ Example Response (200)
{"message": "Logged out successfully"}
GET /user
Get the authenticated user's profile.
✅ Example Response (200)
{
    "id": 1,
    "name": "John Doe",
    "email": "john@example.com",
    "role": 1,
    "wallet_balance": 45.00,
    "membership_validity_to": "2025-12-31"
}

🌍 Public Endpoints

No authentication required.

GET /courses
Get all active courses with categories and packages.
🔍 Query Parameters
  • search (string) – Search by title or short description.
  • category (int) – Filter by category ID.
✅ Example Response (200)
{
    "courses": [
        {
            "id": 5,
            "title": "Yoga for Beginners",
            "slug": "yoga-for-beginners",
            "plan": "one-time",
            "price": 49.99,
            "discounted_price": 39.99,
            "banner": "https://...",
            ...
        }
    ],
    "categories": [{"id":1,"name":"Beginner"}],
    "packages": [...]
}
GET /courses/{identifier}
Get detailed course information or slug.
✅ Example Response (200)
{
    "course": {...},
    "offers": [...],
    "reviews": [...]
}
GET /packages/{slug}
Get package details including associated courses.
GET /membership
List all memberships and membership-only courses.
POST /coupon/check-course/{course}
Validate a coupon code for a specific course.
📝 Request Body
{"code": "SAVE10"}
✅ Example Response (200)
{
    "valid": true,
    "code": "SAVE10",
    "type": "percentage",
    "value": 10,
    "message": "10% discount applied!"
}
GET /course/{id}/reviews
List all reviews for a course.
GET /membership
List all memberships.

👤 User Endpoints

All endpoints require authentication (Bearer token).

GET /dashboard
Get dashboard statistics, recent certificates, and courses with progress.
✅ Example Response
{
    "active_courses": 3,
    "completed_courses": 5,
    "total_certificates": 2,
    "recent_certificates": [...],
    "recent_learning": [...],
    "courses": [ ... ]  // with progress, total_sessions, completed_sessions
}
GET /my-courses
List all courses the user has access to (direct purchase, package, membership) with progress.
GET /my-classes
List courses where user is instructor or co-instructor.
GET /certificates
List all certificates earned by the user.
GET /learning-history
List all paid course orders (learning history).
GET /my-membership
Get current membership details.
POST /membership/cancel
Cancel active membership and get pro-rated refund added to wallet.
✅ Example Response
{"message": "Membership cancelled. 45.50 added to wallet."}
GET /transactions
List user's transactions (wallet, refunds, etc.).
POST /course/{id}/review
Submit a review for a course.
📝 Request Body
{
    "rating": 5,
    "review": "Amazing course!",
    "name": "John Doe",
    "email": "john@example.com"
}

📘 Course Content

GET /courses/{course}/preview
Get course details including outline for enrolled users.
GET /courses/{course}/discussion/messages
Fetch discussion messages (pagination via last_id).
🔍 Query Parameters last_id – Get messages older than this ID (for loading more).
POST /courses/{course}/discussion/messages
Post a new message or file in course discussion.
📝 Form Data
  • message (string, optional)
  • file (file, max 10MB, optional)
✅ Example Response
{
    "message": {
        "id": 42,
        "user_id": 1,
        "course_id": 5,
        "message": "Great class!",
        "file_path": null,
        "created_at": "...",
        "user": { "id":1, "name":"John Doe" }
    }
}
POST /courses/{course}/zoom-create
Create a Zoom meeting (for instructors).
GET /zoom/recording
Get Zoom recording links for a meeting.
🔍 Query Parameters meeting_id (required), class_time (optional, for specific session).
✅ Example Response
{
    "success": true,
    "share_url": "https://zoom.us/rec/share/...",
    "password": "123456",
    "recordings": [{"play_url":"...","download_url":"..."}]
}
POST /certificate/{order}
Upload PDF certificate for a completed course.
📝 Form Data certificate (PDF file, max 10MB)
✅ Example Response
{
    "message": "Certificate uploaded successfully",
    "certificate_url": "https://.../certificate_123456.pdf"
}

💰 Checkout & Payments

POST /checkout/course
Create an order for a course.
📝 Request Body
{
    "name": "John Doe",
    "email": "john@example.com",
    "course_id": 5,
    "payment_method": "stripe",   // or "paypal"
    "platform": "android",        // optional; use "ios" for App Store builds
    "coupon_code": "SAVE10"       // optional
}
✅ Example Response (paid course)
{
    "order": { "id": 101, "amount": 39.99, "payment_status": "pending" },
    "payment_links": {
        "stripe": "https://checkout.stripe.com/...",
        "paypal": "https://www.paypal.com/checkoutnow?token=..."
    }
}
✅ Example Response (iOS in-app purchase)
{
    "order": { "id": 101, "amount": 39.99, "payment_status": "pending" },
    "in_app_purchase": {
        "provider": "app_store",
        "product_id": "65b53e03e4b04982091eb2ad",
        "status": "client_purchase_required"
    }
}
🍎 Complete App Store Purchase
POST /checkout/course/{order}/app-store/complete
{
    "product_id": "65b53e03e4b04982091eb2ad",
    "receipt_data": "{StoreKit serverVerificationData}",
    "transaction_id": "{StoreKit transaction id}"
}
✅ Example Response (free/membership course)
{
    "order": { "id": 102, "payment_status": "completed" },
    "redirect": "/order/success/102"
}
GET /payment/stripe/{order}
Initiate Stripe Checkout session, returns payment URL. Do not use this route from iOS App Store builds; use App Store in-app purchase instead.
✅ Example Response
{"redirect_url": "https://checkout.stripe.com/..."}
GET /payment/paypal/redirect/{order}
Initiate PayPal payment, returns approval URL.
GET /order/success/{order}
Get order details after successful payment (Stripe/PayPal call this automatically).

🎫 Support Tickets

GET /tickets
List user's tickets.
POST /tickets
Create new ticket.
📝 Request Body
{
    "subject": "Login issue",
    "category": "Account Issue",
    "message": "I can't reset my password."
}
GET /tickets/{ticket}
View ticket with replies.
POST /tickets/{ticket}/reply
Add reply to ticket.
📝 Request Body
{"message": "Here's more info..."}

📝 Quizzes

GET /quizzes/available
List quizzes the user hasn't taken yet.
GET /quiz/{quizId}/start
Get quiz questions and create attempt.
✅ Example Response
{
    "quiz": {...},
    "attempt": {...},
    "questions": [...],
    "progress": {...}
}
POST /quiz/attempt/{attemptId}/save-progress
Save partial progress (optional).
POST /quiz/attempt/{attemptId}/submit
Submit final answers and get results.
📝 Request Body
{
    "answers": {
        "1": 3,           // for multiple choice
        "2": ["a","c"],   // for multiple response
        "3": "my answer"  // for short answer
    },
    "time_spent": 120
}
GET /quiz/result/{attemptId}
Get quiz result details.
GET /quiz/leaderboard?quizId={optional}
View leaderboard for all quizzes or a specific one.

🔧 Admin Endpoints

Only users with role=0 (admin) can access these.

GET /admin/tickets
List all tickets with filters (status, category, assigned).
POST /admin/tickets/{ticket}/assign
Assign ticket to current admin/instructor.
POST /admin/tickets/{ticket}/reassign
Reassign ticket to another user.
📝 Request Body
{"assigned_to": 5}
PATCH /admin/tickets/{ticket}/status
Update ticket status (open, in_progress, resolved, closed).
📝 Request Body
{"status": "resolved"}
GET /admin/logs
View application logs (file list).
POST /admin/clear-cache
Clear Laravel cache (config, route, view).

⚠️ Error Handling

All errors return JSON with appropriate HTTP status codes.

StatusMeaningExample Response
401Unauthorized – missing or invalid token
{"message": "Unauthenticated."}
403Forbidden – insufficient permissions
{"message": "This action is unauthorized."}
422Validation error
{"message": "The given data was invalid.", "errors": {"email": ["The email field is required."]}}
500Server error
{"message": "Server Error"}
Note: Paginated responses follow the structure: { "data": [...], "links": { "first": "...", "last": "...", "prev": null, "next": "..." }, "meta": { "current_page": 1, "from": 1, "last_page": 5, "per_page": 15, "to": 15, "total": 75 } }