🎯 Quiz API

RESTful API for Quiz Management

✓ API ONLINE

📋 Overview

Welcome to the Quiz API documentation. This API provides a complete solution for managing quizzes, questions, and answers. Build engaging quiz applications with ease!

20
Endpoints
3
Resources
0
Auth Required
100%
Uptime

✨ Key Features

🎯

Complete CRUD

Full Create, Read, Update, Delete operations for all resources

🔒

Data Integrity

Database triggers enforce business rules automatically

🖼️

Image Upload

Upload images for questions (JPEG, PNG, GIF, WebP)

Bulk Operations

Create all 4 answers for a question in one request

🔓 Authentication

Public API: No authentication is required. All endpoints are publicly accessible for development purposes.
Note: If you see 401 errors, please check the server configuration. Authentication should be disabled for all quiz endpoints.

🚀 Quick Start

Base URL

// Production const API_BASE = 'https://api-pq.rouzbehsayadifar.com/api'; // Development const API_BASE = 'http://localhost/api';

Example: Create a Quiz

const response = await fetch('https://api-pq.rouzbehsayadifar.com/api/quizzes', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Sample Quiz', description: 'This is a sample quiz', is_active: 1 }) }); const data = await response.json(); console.log(data);

Example Response

{ "status": "success", "message": "Quiz created successfully", "data": { "quiz": { "QuizId": 1, "Name": "Sample Quiz", "Description": "This is a sample quiz", "IsActive": 1, "CreatedDate": "2025-11-04 12:00:00" } } }

📡 API Endpoints Reference

Complete documentation for all endpoints including request/response formats. For the full developer guide with more examples, see the API Worksheet.

🎯 Quiz Endpoints

GET /api/quizzes

Description: Get all quizzes with optional filtering

Query Parameters:

  • is_active (optional): Filter by active status (0 or 1)

Request Example:

GET /api/quizzes?is_active=1

Response (200 OK):

{ "status": "success", "message": "Quizzes retrieved successfully", "data": { "quizzes": [ { "QuizId": 1, "Name": "Geography Quiz", "Description": "Test your knowledge", "CreatedDate": "2025-11-11 10:00:00", "IsActive": 1 } ] } }

POST /api/quizzes

Description: Create a new quiz

Request Body:

{ "name": "History Quiz", "description": "World history questions", "is_active": 1 } // Required fields: name // Optional fields: description, is_active (default: 1)

Response (200 OK):

{ "status": "success", "message": "Quiz created successfully", "data": { "quiz": { "QuizId": 5, "Name": "History Quiz", "Description": "World history questions", "CreatedDate": "2025-11-11 12:00:00", "IsActive": 1 } } }

PUT /api/quizzes/{id}

Description: Update an existing quiz

Request Body (all fields optional):

{ "name": "Updated Quiz Name", "description": "Updated description", "is_active": 0 }

Response (200 OK):

{ "status": "success", "message": "Quiz updated successfully", "data": { "quiz": { ... } } }

DELETE /api/quizzes/{id}

Description: Delete a quiz (⚠️ cascades to questions and answers)

Response (200 OK):

{ "status": "success", "message": "Quiz deleted successfully" }

❓ Question Endpoints

GET /api/questions

Description: Get all questions with optional filtering

Query Parameters:

  • quiz_id (optional): Filter by quiz ID

Response (200 OK):

{ "status": "success", "message": "Questions retrieved successfully", "data": { "questions": [ { "QuestionId": 1, "QuizId": 1, "QuestionText": "What is the capital of France?", "ImagePath": "/uploads/questions/question_1.jpg", "OrderIndex": 0, "TimerDuration": 30, "answers": [...] } ] } }

POST /api/questions

Description: Create a new question

Request Body:

{ "quiz_id": 1, "question_text": "What is the capital of France?", "image_path": null, "order_index": 0, "timer_duration": 30 } // Required: quiz_id, question_text // Optional: image_path, order_index (default: 0), timer_duration (default: 30, range: 10-300)

Response (200 OK):

{ "status": "success", "message": "Question created successfully", "data": { "question": { "QuestionId": 5, "QuizId": 1, "QuestionText": "What is the capital of France?", "ImagePath": null, "OrderIndex": 0, "TimerDuration": 30, "answers": [] } } }

PUT /api/questions/{id}

Description: Update an existing question

Request Body (all fields optional):

{ "quiz_id": 1, "question_text": "Updated question text", "image_path": "/uploads/questions/new_image.jpg", "order_index": 1, "timer_duration": 45 }

Response (200 OK):

{ "status": "success", "message": "Question updated successfully", "data": { "question": { ... } } }

POST /api/questions/{id}/image

Description: Upload an image for a question (📷 multipart/form-data)

Request:

  • Content-Type: multipart/form-data
  • Field name: image
  • Allowed types: JPEG, PNG, GIF, WebP

JavaScript Example:

const formData = new FormData(); formData.append('image', fileInput.files[0]); fetch('/api/questions/1/image', { method: 'POST', body: formData });

Response (200 OK):

{ "status": "success", "message": "Image uploaded successfully", "data": { "question": { ... }, "image_path": "/uploads/questions/question_1_1699699200_abc123.jpg" } }

Error Responses:

// No image provided { "status": "error", "message": "No image file provided" } // Invalid file type { "status": "error", "message": "Invalid file type. Only JPEG, PNG, GIF, and WebP are allowed" }

💡 Answer Endpoints

POST /api/answers

Description: Create a single answer (⚠️ prefer using bulk creation)

Request Body:

{ "question_id": 1, "answer_text": "Paris", "option_letter": "A", "is_correct": 1 } // Required: question_id, answer_text, option_letter (A/B/C/D) // Optional: is_correct (default: 0)

Response (200 OK):

{ "status": "success", "message": "Answer created successfully", "data": { "answer": { ... } } }

POST /api/answers/bulk

Description: Create all 4 answers for a question at once (✅ recommended)

Request Body:

{ "question_id": 1, "answers": [ { "answer_text": "Paris", "option_letter": "A", "is_correct": 1 }, { "answer_text": "London", "option_letter": "B", "is_correct": 0 }, { "answer_text": "Berlin", "option_letter": "C", "is_correct": 0 }, { "answer_text": "Madrid", "option_letter": "D", "is_correct": 0 } ] } // Requirements: // - Exactly 4 answers // - Unique option_letter (A, B, C, D) // - Exactly one correct answer // - Question must not already have answers

Response (200 OK):

{ "status": "success", "message": "Answers created successfully", "data": { "answers": [ ... ] } }

PUT /api/answers/{id}

Description: Update an existing answer

Request Body (all fields optional):

{ "answer_text": "Updated answer text", "option_letter": "B", "is_correct": 1 }

Response (200 OK):

{ "status": "success", "message": "Answer updated successfully", "data": { "answer": { ... } } }

🔧 Utility Endpoints

GET /api/health

Description: Check API health status

Response (200 OK):

{ "status": "ok", "message": "Quiz API is working correctly", "timestamp": "2025-11-23T12:00:00+00:00" }

🔧 Troubleshooting

Common Issues

1. JSON Parse Error

Issue: SyntaxError: JSON.parse: unexpected character at line 1 column 1

Solution: This is caused by BOM (Byte Order Mark) in PHP files. All PHP files have been saved as UTF-8 without BOM. If you still see this error, clear your browser cache and retry.

2. 500 Internal Server Error

Issue: Server returns 500 error when creating or fetching quizzes

Solution: Check the server error logs at /logs/api_errors.log. The API now includes detailed error logging with stack traces.

3. 401 Unauthorized Error

Issue: Getting unauthorized errors even though API is public

Solution: This has been fixed. All quiz endpoints are now public and don't require authentication.

4. CORS Errors

Issue: Cross-origin request blocked

Solution: CORS has been configured to allow requests from multiple origins. Make sure your origin is in the allowed list.