🚀 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.