New 2026 exam preparation roadmap now live.
See Plans
README

QUIZZERA – Deployment & Integration Guide (Vercel)

This document explains how to deploy QUIZZERA to Vercel and integrate the custom payment gateway and SendPulse notifications.

Quick links:

  • Deployment guide: DEPLOYMENT.md
  • API reference: API.md

Overview

This repository includes:

  • Next.js app (student + admin)
  • Custom payment gateway API
  • Bank transfer flow
  • SendPulse notifications
  • Swagger/ReDoc API docs

For full details, see the linked documents above.

Authentication Testing

Comprehensive auth integration test validates all authentication flows:

Quick Test

npm run test:auth:integration

This automated test validates:

  • ✓ User signup with email verification
  • ✓ Login blocking for unverified accounts
  • ✓ OTP request and verification flow
  • ✓ Token-based email verification
  • ✓ Forgot password (dual-path: token + OTP)
  • ✓ Password reset with token
  • ✓ Password reset with OTP
  • ✓ Logout with session invalidation
  • ✓ Token invalidation after logout

Manual Verification Steps

Some tests require manual intervention for email codes:

  1. OTP Verification:

    node test-auth-integration.js --otp=123456
    
  2. Reset Password with Token:

    node test-auth-integration.js --reset-token=YOUR_TOKEN
    
  3. Reset Password with OTP:

    node test-auth-integration.js --reset-otp=123456
    
  4. Full Flow with All Codes:

    node test-auth-integration.js --otp=123456 --reset-otp=654321
    

Basic Auth Test Suite

For quick validation of core auth endpoints:

npm run test:auth

Database Seeding

Use MongoDB seed scripts from the project root:

  • Safe seed (non-destructive):
    • npm run seed
  • Reset guard check (expected to fail unless forced):
    • npm run seed:check-reset
  • Full reset + reseed (destructive, CI-friendly):
    • npm run seed:reset

Seed API modes (admin)

  • Users seed endpoint: POST /api/admin/users/seed
    • Reset mode: POST /api/admin/users/seed?reset=true&force=true
  • Exams seed endpoint: POST /api/admin/exams/seed
    • Reset mode: POST /api/admin/exams/seed?reset=true&force=true

Reset requests without force=true are rejected by design for safety.

Deployment

Deployment Guide

Overview

This document provides deployment instructions for the Quizzera application.

Prerequisites

  • Node.js 18+
  • MongoDB Atlas account
  • Vercel account (for hosting)
  • SendPulse account (for email)

Environment Variables

Create a .env.local file with the following variables:

# Database
MONGODB_URI=mongodb+srv://<username>:<password>@cluster.mongodb.net/quiz_platform

# Authentication
JWT_SECRET=your-super-secret-jwt-key
NEXTAUTH_SECRET=your-nextauth-secret

# App URL
NEXT_PUBLIC_APP_URL=http://localhost:3000

# SendPulse Email
SENDPULSE_API_KEY=your-sendpulse-api-key
SENDPULSE_SENDER_EMAIL=hello@quizzera.pk
SENDPULSE_SENDER_NAME=QUIZZERA

# Payment Gateway (Switch)
SWITCH_API_KEY=your-switch-api-key
SWITCH_API_SECRET=your-switch-api-secret
SWITCH_API_URL=https://api.switch.com

Build Commands

# Install dependencies
npm install

# Run development server
npm run dev

# Build for production
npm run build

# Start production server
npm start

Deployment Steps

  1. Push to GitHub: Commit and push your code to a GitHub repository
  2. Connect to Vercel: Import your repository in Vercel
  3. Configure Environment Variables: Add all required environment variables in Vercel dashboard
  4. Deploy: Vercel will automatically build and deploy your application

Database Seeding

To seed the database with initial data:

node scripts/seed-mongodb.js

Troubleshooting

  • Ensure all environment variables are set correctly
  • Check MongoDB Atlas network access settings
  • Verify SendPulse API credentials
  • Check Vercel function logs for errors
API Reference

QUIZZERA API Reference

Overview

Base URL (production): https://quizzera.pk Base URL (development): http://localhost:9002

All admin endpoints require a valid JWT bearer token and admin authorization.


Authentication

  • JWT access token: Authorization: Bearer <token>
  • Payment gateway: x-api-key: <PAYMENT_GATEWAY_API_KEY>

Authorization Header Format

Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6...

Demo Mode

For development, you can use demo tokens starting with demo_token_ for admin endpoints.


Authentication APIs

POST /api/auth/login

Headers: Authorization: Bearer <token> (optional for rate limiting)

Request:

{
  "email": "user@example.com",
  "password": "password123"
}

Response:

{
  "success": true,
  "data": {
    "uid": "user123",
    "email": "user@example.com",
    "emailVerified": true,
    "customToken": "..."
  }
}

Error Responses:

  • 401: Invalid credentials
  • 400: Validation error

POST /api/auth/signup

Headers: Authorization: Bearer <token> (optional for rate limiting)

Request:

{
  "email": "user@example.com",
  "password": "password123",
  "name": "Full Name",
  "role": "student" // or "mentor"
}

Response:

{
  "success": true,
  "data": {
    "uid": "user123",
    "email": "user@example.com",
    "name": "Full Name",
    "role": "student"
  }
}

POST /api/auth/forgot-password

Headers: Authorization: Bearer <token> (optional for rate limiting)

Request:

{
  "email": "user@example.com"
}

Response:

{
  "success": true,
  "message": "If an account exists with this email, a password reset link has been sent"
}

POST /api/auth/token

Headers: Authorization: Bearer <access_token>

Get a custom session token for API authentication.

Request: Empty body

Response:

{
  "token": "custom_session_token"
}

Admin Users Management

GET /api/admin/users

Headers: Authorization: Bearer <admin token>

Query Parameters:

  • role - Filter by role: student, mentor, all
  • status - Filter by status: Active, Inactive, all
  • search - Search by name or email
  • limit - Pagination limit (default: 50)
  • offset - Pagination offset (default: 0)

Response:

{
  "success": true,
  "data": {
    "users": [
      {
        "id": "user123",
        "name": "Ahmed Khan",
        "email": "ahmed@example.com",
        "phone": "+92 300 1234567",
        "role": "student",
        "status": "Active",
        "city": "Karachi",
        "country": "createdAt": "Pakistan",
        "2024-01-15T10:00:00Z"
      }
    ],
    "total": 156,
    "offset": 0,
    "limit": 50
  }
}

POST /api/admin/users

Headers: Authorization: Bearer <admin token>

Request:

{
  "name": "New User",
  "email": "newuser@example.com",
  "phone": "+92 300 1234567",
  "role": "student",
  "status": "Active",
  "city": "Karachi",
  "country": "Pakistan"
}

Response:

{
  "success": true,
  "data": {
    "id": "newuser123",
    "name": "New User",
    "email": "newuser@example.com",
    "role": "student",
    "status": "Active"
  }
}

PUT /api/admin/users

Headers: Authorization: Bearer <admin token>

Request:

{
  "id": "user123",
  "name": "Updated Name",
  "phone": "+92 300 7654321",
  "status": "Inactive"
}

DELETE /api/admin/users

Headers: Authorization: Bearer <admin token>

Query Parameter: id (required)

Response:

{
  "success": true,
  "message": "User deleted successfully"
}

Admin Mentors Management

GET /api/admin/mentors

Headers: Authorization: Bearer <admin token>

Query Parameters:

  • status - Filter by status: Active, Inactive, all
  • specialization - Filter by specialization
  • search - Search by name, email, or specialization
  • limit - Pagination limit (default: 50)
  • offset - Pagination offset (default: 0)

Response:

{
  "success": true,
  "data": {
    "mentors": [
      {
        "id": "mentor123",
        "displayName": "Dr. Fatima Ali",
        "email": "fatima@example.com",
        "phone": "+92 301 2345678",
        "specialization": "Mathematics",
        "experienceYears": 5,
        "hourlyRate": 1500,
        "status": "Active",
        "rating": 4.8,
        "totalStudents": 25,
        "totalSessions": 150,
        "city": "Lahore",
        "country": "Pakistan"
      }
    ],
    "total": 42,
    "offset": 0,
    "limit": 50
  }
}

POST /api/admin/mentors

Headers: Authorization: Bearer <admin token>

Request:

{
  "email": "newmentor@example.com",
  "displayName": "Dr. New Mentor",
  "phone": "+92 302 3456789",
  "specialization": "Physics",
  "experienceYears": 7,
  "teachingApproach": "Student-centered learning",
  "bio": "Experienced physics teacher...",
  "hourlyRate": 2000,
  "city": "Islamabad",
  "country": "Pakistan"
}

Response:

{
  "success": true,
  "data": {
    "id": "mentor456",
    "email": "newmentor@example.com",
    "displayName": "Dr. New Mentor",
    "specialization": "Physics",
    "hourlyRate": 2000,
    "status": "Active"
  }
}

PUT /api/admin/mentors

Headers: Authorization: Bearer <admin token>

Request:

{
  "id": "mentor123",
  "displayName": "Prof. Fatima Ali",
  "hourlyRate": 1800,
  "specialization": "Mathematics & Physics",
  "status": "Active"
}

DELETE /api/admin/mentors

Headers: Authorization: Bearer <admin token>

Query Parameter: id (required)

Response:

{
  "success": true,
  "message": "Mentor deleted successfully"
}

Admin Students Management

GET /api/admin/students

Headers: Authorization: Bearer <admin token>

Query Parameters:

  • status - Filter by status: Active, Inactive, all
  • grade - Filter by grade/class
  • search - Search by name or email
  • limit - Pagination limit (default: 50)
  • offset - Pagination offset (default: 0)

Response:

{
  "success": true,
  "data": {
    "students": [
      {
        "id": "student123",
        "displayName": "Ahmed Khan",
        "email": "ahmed@example.com",
        "phone": "+92 300 1234567",
        "grade": "10th Grade",
        "learningGoals": "Want to improve math scores",
        "status": "Active",
        "city": "Karachi",
        "country": "Pakistan",
        "subscriptionPlan": "pro",
        "totalPractices": 25,
        "averageScore": 78.5
      }
    ],
    "total": 114,
    "offset": 0,
    "limit": 50
  }
}

POST /api/admin/students

Headers: Authorization: Bearer <admin token>

Request:

{
  "email": "newstudent@example.com",
  "displayName": "New Student",
  "phone": "+92 303 4567890",
  "grade": "11th Grade",
  "learningGoals": "Prepare for entrance exams",
  "city": "Peshawar",
  "country": "Pakistan"
}

PUT /api/admin/students

Headers: Authorization: Bearer <admin token>

Request:

{
  "id": "student123",
  "displayName": "Ahmed Omar Khan",
  "grade": "12th Grade",
  "status": "Active"
}

DELETE /api/admin/students

Headers: Authorization: Bearer <admin token>

Query Parameter: id (required)


Admin Assignments Management

GET /api/admin/assignments

Headers: Authorization: Bearer <admin token>

Query Parameters:

  • status - Filter by status: active, completed, cancelled, all

Response:

{
  "success": true,
  "data": {
    "assignments": [
      {
        "id": "assign123",
        "mentorId": "mentor123",
        "mentorName": "Dr. Fatima Ali",
        "studentId": "student456",
        "studentName": "Ahmed Khan",
        "status": "active",
        "startDate": "2024-01-15",
        "endDate": null,
        "notes": "Focus on Mathematics",
        "sessionsCompleted": 5
      }
    ],
    "stats": {
      "active": 38,
      "completed": 25,
      "cancelled": 5
    }
  }
}

POST /api/admin/assignments

Headers: Authorization: Bearer <admin token>

Request:

{
  "mentorId": "mentor123",
  "studentId": "student456",
  "notes": "Focus on calculus and algebra"
}

Response:

{
  "success": true,
  "data": {
    "id": "assign789",
    "mentorId": "mentor123",
    "studentId": "student456",
    "status": "active",
    "startDate": "2024-02-11",
    "sessionsCompleted": 0
  }
}

PUT /api/admin/assignments

Headers: Authorization: Bearer <admin token>

Request:

{
  "id": "assign123",
  "status": "completed",
  "endDate": "2024-02-11"
}

DELETE /api/admin/assignments

Headers: Authorization: Bearer <admin token>

Query Parameter: id (required)


Admin Exams Management

GET /api/admin/exams

Headers: Authorization: Bearer <admin token>

Response:

{
  "success": true,
  "data": {
    "exams": [
      {
        "id": "exam123",
        "title": "Mathematics Mock Test",
        "description": "Practice test for matriculation math",
        "timeLimit": 60,
        "questionCount": 50,
        "isPaid": false,
        "createdAt": "2024-01-10T10:00:00Z"
      }
    ],
    "total": 15
  }
}

POST /api/admin/exams

Headers: Authorization: Bearer <admin token>

Request:

{
  "title": "New Mock Test",
  "description": "Description of the exam",
  "timeLimit": 45,
  "mcqs": [
    {
      "id": "mcq1",
      "questionText": "What is 2+2?",
      "options": ["3", "4", "5", "6"],
      "correctAnswer": 1,
      "explanation": "Simple addition"
    }
  ],
  "isPaid": false,
  "negativeMarking": true,
  "negativeMarkValue": 0.25,
  "disclaimer": "This is a practice exam"
}

GET /api/admin/exams/:id

Headers: Authorization: Bearer <admin token>

Get exam details with all MCQs.


PUT /api/admin/exams/:id

Headers: Authorization: Bearer <admin token>

Update exam details.


DELETE /api/admin/exams/:id

Headers: Authorization: Bearer <admin token>

Delete an exam.


Admin MCQs Management

GET /api/admin/mcqs

Headers: Authorization: Bearer <admin token>

Query Parameters:

  • category - Filter by category
  • topic - Filter by topic
  • difficulty - Filter by difficulty: easy, medium, hard

Response:

{
  "success": true,
  "data": {
    "mcqs": [
      {
        "id": "mcq123",
        "questionText": "What is the capital of Pakistan?",
        "options": ["Karachi", "Lahore", "Islamabad", "Rawalpindi"],
        "correctAnswer": 2,
        "category": "Geography",
        "topic": "Pakistan",
        "difficulty": "easy"
      }
    ],
    "total": 1500
  }
}

POST /api/admin/mcqs

Headers: Authorization: Bearer <admin token>

Request:

{
  "questionText": "What is the capital of Pakistan?",
  "options": ["Karachi", "Lahore", "Islamabad", "Rawalpindi"],
  "correctAnswer": 2,
  "explanation": "Islamabad is the federal capital of Pakistan",
  "category": "Geography",
  "topic": "Pakistan",
  "difficulty": "easy"
}

PUT /api/admin/mcqs/:id

Headers: Authorization: Bearer <admin token>

Update MCQ details.


DELETE /api/admin/mcqs/:id

Headers: Authorization: Bearer <admin token>

Delete an MCQ.


POST /api/admin/mcqs/import

Headers: Authorization: Bearer <admin token> Content-Type: multipart/form-data

Import MCQs from CSV file.


GET /api/admin/mcqs/export

Headers: Authorization: Bearer <admin token>

Export all MCQs as CSV.


Mentor APIs

GET /api/mentor/profile

Headers: Authorization: Bearer <token>

Query Parameter: uid (required)

Response:

{
  "success": true,
  "data": {
    "profile": {
      "uid": "mentor123",
      "displayName": "Dr. Fatima Ali",
      "email": "fatima@example.com",
      "bio": "Experienced mathematics teacher...",
      "hourlyRate": 1500,
      "specializations": ["Mathematics", "Calculus", "Algebra"],
      "rating": 4.8,
      "totalReviews": 45,
      "totalStudents": 25,
      "totalSessions": 150,
      "availability": "Mon-Fri, 9AM-5PM"
    }
  }
}

PUT /api/mentor/profile

Headers: Authorization: Bearer <token>

Request:

{
  "uid": "mentor123",
  "displayName": "Prof. Fatima Ali",
  "bio": "Updated bio...",
  "hourlyRate": 1800,
  "specializations": ["Mathematics", "Statistics"]
}

GET /api/mentor/stats

Headers: Authorization: Bearer <token>

Query Parameter: uid (required)

Response:

{
  "success": true,
  "data": {
    "stats": {
      "totalSessions": 150,
      "totalStudents": 25,
      "upcomingSessions": 5,
      "averageRating": 4.8,
      "totalEarnings": 150000,
      "monthlyEarnings": 15000,
      "completionRate": 95,
      "responseTime": 2
    }
  }
}

GET /api/mentor/bookings

Headers: Authorization: Bearer <token>

Query Parameters:

  • uid - Mentor UID
  • status - Filter: upcoming, completed, all

Response:

{
  "success": true,
  "data": {
    "bookings": [
      {
        "id": "booking123",
        "studentName": "Ahmed Khan",
        "serviceName": "Mathematics Session",
        "scheduledDate": "2024-02-12",
        "scheduledTime": "10:00 AM",
        "duration": 60,
        "status": "confirmed",
        "price": 1500
      }
    ]
  }
}

POST /api/mentor/bookings

Headers: Authorization: Bearer <token>

Request:

{
  "mentorId": "mentor123",
  "studentId": "student456",
  "serviceName": "Mathematics Session",
  "scheduledDate": "2024-02-15",
  "scheduledTime": "2:00 PM",
  "duration": 60,
  "price": 1500
}

GET /api/mentor/quizzes

Headers: Authorization: Bearer <token>

Query Parameters:

  • mentorId - Filter by mentor UID
  • status - Filter: published, draft, all
  • subject - Filter by subject
  • limit - Pagination limit
  • offset - Pagination offset

Response:

{
  "success": true,
  "data": {
    "quizzes": [
      {
        "id": "quiz123",
        "title": "Calculus Quiz 1",
        "subject": "Mathematics",
        "grade": "12th",
        "difficulty": "medium",
        "questionCount": 20,
        "isPublished": true,
        "totalAttempts": 45,
        "averageScore": 72.5,
        "createdAt": "2024-01-15T10:00:00Z"
      }
    ],
    "total": 10
  }
}

POST /api/mentor/quizzes

Headers: Authorization: Bearer <token>

Request:

{
  "title": "Algebra Quiz",
  "description": "Practice quiz on linear equations",
  "subject": "Mathematics",
  "grade": "10th",
  "difficulty": "easy",
  "questions": [
    {
      "questionText": "Solve for x: 2x + 5 = 15",
      "options": ["3", "5", "7", "10"],
      "correctAnswer": 1,
      "explanation": "Subtract 5 and divide by 2",
      "points": 1
    }
  ],
  "timeLimit": 30,
  "isPublished": false
}

PUT /api/mentor/quizzes

Headers: Authorization: Bearer <token>

Update quiz details.


DELETE /api/mentor/quizzes

Headers: Authorization: Bearer <token>

Query Parameter: id (required)


GET /api/mentor/students

Headers: Authorization: Bearer <token>

Get list of students assigned to mentor.

Response:

{
  "success": true,
  "data": {
    "students": [
      {
        "id": "student123",
        "name": "Ahmed Khan",
        "email": "ahmed@example.com",
        "totalSessions": 10,
        "totalSpent": 15000,
        "lastSession": "2024-02-10",
        "status": "active"
      }
    ],
    "total": 25
  }
}

GET /api/mentor/notifications

Headers: Authorization: Bearer <token>

Get mentor notifications.


Student APIs

GET /api/student/stats

Headers: Authorization: Bearer <token>

Response:

{
  "success": true,
  "data": {
    "stats": {
      "totalPractices": 50,
      "totalMockTests": 10,
      "averageScore": 78.5,
      "upcomingSessions": 2,
      "totalSessionsAttended": 15
    }
  }
}

GET /api/student/history

Headers: Authorization: Bearer <token>

Query Parameters:

  • page - Page number (default: 1)
  • limit - Items per page (default: 10, max: 50)
  • status - Filter: all, completed, in-progress

Response:

{
  "success": true,
  "data": {
    "sessions": [
      {
        "id": "session123",
        "examTitle": "Mathematics Mock Test",
        "score": 42,
        "totalQuestions": 50,
        "percentage": 84,
        "completedAt": "2024-02-10T15:00:00Z",
        "timeTaken": 3600
      }
    ],
    "stats": {
      "totalPractices": 50,
      "totalMockTests": 10,
      "averageScore": 78.5,
      "highestScore": 95
    },
    "pagination": {
      "page": 1,
      "limit": 10,
      "total": 60,
      "totalPages": 6
    }
  }
}

Practice Session APIs

POST /api/practice/session/start

Headers: Authorization: Bearer <token>

Start a new practice session with random MCQs.

Request:

{
  "category": "mathematics",
  "topic": "algebra",
  "difficulty": "medium",
  "questionCount": 10,
  "timeLimit": 15
}

Response:

{
  "success": true,
  "data": {
    "session": {
      "sessionId": "session_abc123",
      "questions": [
        {
          "id": "mcq123",
          "questionText": "Solve for x: 2x + 5 = 15",
          "options": ["3", "5", "7", "10"],
          "subject": "Mathematics",
          "topic": "Algebra",
          "difficulty": "medium"
        }
      ],
      "timeLimit": 15,
      "startedAt": "2024-02-11T10:00:00Z"
    }
  }
}

GET /api/practice/session/start

Headers: Authorization: Bearer <token>

Query Parameters:

  • sessionId - Get specific session

Get user's active practice session.

Response:

{
  "success": true,
  "data": {
    "activeSession": {
      "id": "session_abc123",
      "category": "mathematics",
      "status": "in_progress",
      "startedAt": "2024-02-11T10:00:00Z",
      "timeLimit": 15
    }
  }
}

POST /api/practice/session/submit

Headers: Authorization: Bearer <token>

Submit practice answers and get instant results.

Request:

{
  "sessionId": "session_abc123",
  "answers": [
    {
      "questionId": "mcq123",
      "selectedAnswer": 1,
      "timeSpent": 45
    }
  ],
  "timeSpent": 600
}

Response:

{
  "success": true,
  "data": {
    "sessionId": "session_abc123",
    "results": {
      "totalQuestions": 10,
      "correctAnswers": 8,
      "wrongAnswers": 2,
      "unanswered": 0,
      "score": 8,
      "percentage": 80,
      "grade": "B",
      "timeSpent": 600,
      "answers": [
        {
          "questionId": "mcq123",
          "questionText": "Solve for x: 2x + 5 = 15",
          "options": ["3", "5", "7", "10"],
          "selectedAnswer": 1,
          "correctAnswer": 1,
          "isCorrect": true,
          "explanation": "Subtract 5 and divide by 2",
          "timeSpent": 45
        }
      ]
    }
  }
}

GET /api/practice/session/submit

Headers: Authorization: Bearer <token>

Query Parameter: sessionId (required)

Get completed session results.


Public Exam APIs

GET /api/exams

Public endpoint - no authentication required

Response:

{
  "success": true,
  "data": {
    "exams": [
      {
        "id": "exam123",
        "title": "Mathematics Mock Test",
        "description": "Practice test for matriculation math",
        "timeLimit": 60,
        "questionCount": 50,
        "category": "Pakistan"
      }
    ]
  }
}

GET /api/exams/:id

Public endpoint

Get exam details with all MCQs.

Response:

{
  "success": true,
  "data": {
    "exam": {
      "id": "exam123",
      "title": "Mathematics Mock Test",
      "description": "Practice test",
      "timeLimit": 60,
      "questionCount": 50,
      "mcqs": [
        {
          "id": "mcq1",
          "questionText": "What is 2+2?",
          "options": ["3", "4", "5", "6"]
        }
      ]
    }
  }
}

Payment APIs

POST /api/payments/initiate

Headers: x-api-key: <PAYMENT_GATEWAY_API_KEY>

Request:

{
  "userId": "uid123",
  "planId": "pro",
  "amount": 2000,
  "currency": "PKR",
  "redirectUrl": "https://quizzera.pk/success"
}

Response:

{
  "success": true,
  "data": {
    "paymentUrl": "https://paymentgateway.com/pay?txn=xxx",
    "transactionId": "txn_xxx"
  }
}

POST /api/payments/callback

Headers: x-api-key: <PAYMENT_GATEWAY_API_KEY>

Request:

{
  "transactionId": "txn_123",
  "status": "success",
  "userId": "uid123",
  "planId": "pro",
  "amount": 2000,
  "currency": "PKR"
}

POST /api/payments/bank-transfer/initiate

Headers: Authorization: Bearer <token> Content-Type: multipart/form-data

Form Fields:

  • transactionId (required)
  • amount (required)
  • attachment (optional - bank receipt)

POST /api/payments/switch/initiate

Headers: Authorization: Bearer <token>

Switch subscription plan.


POST /api/payments/switch/callback

Headers: Authorization: Bearer <token>

Handle plan switch callback.


Admin Payment/Invoices

GET /api/admin/payment-requests

Headers: Authorization: Bearer <admin token>

Get pending bank transfer requests.


POST /api/admin/payment-requests/:id/approve

Headers: Authorization: Bearer <admin token>

Approve a payment request.


GET /api/admin/invoice-requests

Headers: Authorization: Bearer <admin token>

Get pending invoice requests.


POST /api/admin/invoice-requests/:id/approve

Headers: Authorization: Bearer <admin token>

Approve and generate invoice.


GET /api/admin/invoices

Headers: Authorization: Bearer <admin token>

List all invoices.


POST /api/admin/invoices

Headers: Authorization: Bearer <admin token>

Create manual invoice.

Request:

{
  "userId": "uid123",
  "planName": "Pro Plan",
  "amount": 2000,
  "currency": "PKR",
  "dueDate": "2024-03-01",
  "notes": "Manual invoice for annual subscription"
}

GET /api/admin/invoices/:id/pdf

Headers: Authorization: Bearer <admin token> Query: userId=<uid>

Download invoice PDF.


GET /api/student/invoices/:id/pdf

Headers: Authorization: Bearer <token>

Student downloads their invoice PDF.


GET /api/student/certificates/:id/pdf

Headers: Authorization: Bearer <token>

Download certificate PDF.


Blog APIs

GET /api/blog

Public endpoint

List blog posts.

Response:

{
  "success": true,
  "data": [
    {
      "id": "post123",
      "title": "How to Prepare for NTS",
      "slug": "how-to-prepare-for-nts",
      "excerpt": "Complete guide...",
      "content": "Full content...",
      "author": "Education Team",
      "publishedAt": "2024-02-10T10:00:00Z",
      "category": "Exam Prep",
      "tags": ["NTS", "Test Prep"],
      "coverImage": "https://..."
    }
  ]
}

GET /api/blog/:slug

Public endpoint

Get single blog post.


GET /api/blog/:slug/comments

Public endpoint

List blog post comments.


POST /api/blog/:slug/comments

Headers: Authorization: Bearer <token>

Request:

{
  "content": "Great article! Very helpful.",
  "parentId": null
}

FAQ APIs

GET /api/faq

Public endpoint

Response:

{
  "success": true,
  "data": [
    {
      "id": "faq1",
      "question": "How do I reset my password?",
      "answer": "Go to login page and click 'Forgot Password'.",
      "category": "Account",
      "order": 1
    }
  ],
  "categories": ["General", "Billing", "Technical"]
}

Categories APIs

GET /api/categories

Public endpoint

Response:

{
  "success": true,
  "data": [
    {
      "id": "cat1",
      "name": "Pakistan Exams",
      "slug": "pakistan",
      "description": "Exams conducted in Pakistan",
      "order": 1
    }
  ]
}

Admin Dashboard

GET /api/admin/dashboard

Headers: Authorization: Bearer <admin token>

Response:

{
  "success": true,
  "data": {
    "stats": {
      "totalUsers": 500,
      "totalMentors": 42,
      "totalStudents": 458,
      "totalExams": 50,
      "totalMcqs": 10000,
      "activeSubscriptions": 150,
      "pendingPayments": 20,
      "totalRevenue": 500000
    },
    "examsByCategory": {
      "Pakistan": 20,
      "UAE": 15,
      "KSA": 10
    }
  }
}

GET /api/admin/health

Headers: Authorization: Bearer <admin token>

Response:

{
  "success": true,
  "data": {
    "status": "healthy",
    "services": {
      "firestore": "connected",
      "auth": "connected"
    },
    "timestamp": "2024-02-11T10:00:00.000Z",
    "uptime": 123456.78
  }
}

GET /api/admin/settings

Headers: Authorization: Bearer <admin token>

Get platform settings.


PUT /api/admin/settings

Headers: Authorization: Bearer <admin token>

Update platform settings.


Notifications

POST /api/notifications/signup

Headers: Authorization: Bearer <admin token>

Send welcome notification.

Request:

{
  "email": "user@example.com",
  "name": "New User"
}

POST /api/notifications/result

Headers: Authorization: Bearer <admin token>

Send exam result notification.


POST /api/notifications/invoice

Headers: Authorization: Bearer <admin token>

Send invoice notification.


Rate Limits

| Endpoint Type | Rate Limit | |--------------|------------| | Authentication | 5 requests/minute | | Signup | 5 requests/hour per IP | | Password Reset | 3 requests/hour per IP | | General API | 100 requests/minute | | Admin APIs | 30 requests/minute |


Error Response Format

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message"
  }
}

Common Error Codes

| Code | Description | |------|-------------| | UNAUTHORIZED | Authentication required | | INVALID_TOKEN | Invalid or expired token | | FORBIDDEN | Insufficient permissions | | NOT_FOUND | Resource not found | | INVALID_INPUT | Invalid request data | | RATE_LIMIT_EXCEEDED | Too many requests | | UPGRADE_REQUIRED | Pro Plan required | | CONFLICT | Resource already exists |

HTTP Status Codes

| Status | Description | |--------|-------------| | 200 | Success | | 201 | Created | | 400 | Bad Request | | 401 | Unauthorized | | 403 | Forbidden | | 404 | Not Found | | 409 | Conflict | | 429 | Too Many Requests | | 500 | Internal Server Error |


API Documentation

  • Swagger UI: /api-docs/swagger
  • ReDoc: /api-docs/redoc
  • OpenAPI JSON: /openapi.json

Support

For API-related questions, contact: api-support@quizzera.pk