API Reference

Questions API

Retrieve questions for a specific quiz, browse questions across all published quizzes, or batch import questions into your quizzes.

The Question Object

A question belongs to a quiz and contains the question text, answer options, and metadata such as difficulty and ordering.

AttributeTypeDescription
idstringUnique identifier for the question
quizIdstringID of the parent quiz
textstringThe question text displayed to the user
typestringOne of: MULTIPLE_CHOICE, TRUE_FALSE, OPEN_ENDED
difficultystringOne of: EASY, MEDIUM, HARD, EXPERT
categorystring | nullCategory of the parent quiz
explanationstring | nullOptional explanation shown after answering
answersobject[]Array of answer objects with id, text, and isCorrect fields
GET/api/v1/questions?quiz_id=...

Get Quiz Questions

Returns all questions for a specific quiz in order. Pass a quiz_id to retrieve the ordered list of questions belonging to that quiz. Each question now includes the parent quiz category.

Query Parameters

ParameterTypeDefaultDescription
quiz_idRequiredstring-The ID of the quiz to fetch questions for
include_answersstringfalseSet to "true" to include the answers array with each question

Example Request

bash
curl -X GET "https://quizapi.io/api/v1/questions?quiz_id=quiz_abc123&include_answers=true" \
  -H "Authorization: Bearer YOUR_API_KEY"

Example Response

json
{
  "success": true,
  "data": [
    {
      "id": "ques_xyz789",
      "quizId": "quiz_abc123",
      "text": "What is the typeof null in JavaScript?",
      "type": "MULTIPLE_CHOICE",
      "difficulty": "MEDIUM",
      "explanation": "typeof null returns 'object' due to a legacy bug.",
      "category": "Programming",
      "answers": [
        { "id": "ans_1", "text": "null", "isCorrect": false },
        { "id": "ans_2", "text": "object", "isCorrect": true },
        { "id": "ans_3", "text": "undefined", "isCorrect": false },
        { "id": "ans_4", "text": "string", "isCorrect": false }
      ]
    }
  ],
  "meta": {
    "total": 10,
    "quizId": "quiz_abc123"
  }
}
GET/api/v1/questions

Browse Questions

Browse questions across all published quizzes. When called without a quiz_id, this endpoint returns paginated questions filtered by category, difficulty, type, and tags. Each question includes its parent quiz context. Answers are always included in browse mode.

Query Parameters

ParameterTypeDefaultDescription
categorystring-Filter by quiz category. Supports comma-separated values for multiple categories (case-insensitive). E.g. Programming,DevOps
difficultystring-Filter by difficulty. Supports comma-separated values (case-insensitive). E.g. EASY,MEDIUM
typestring-Filter by question type. Supports comma-separated values. E.g. MULTIPLE_CHOICE,TRUE_FALSE
tagsstring-Comma-separated list of tags to match (e.g. javascript,react)
limitinteger10Number of questions to return per page (1–50)
offsetinteger0Number of questions to skip for pagination
randomstringfalseSet to "true" to shuffle the returned questions randomly

Tip: Use the /api/v1/metadata endpoint to discover available categories, tags, and difficulty levels before querying. All filter values (category, difficulty, type) are case-insensitive.

Example Request

bash
curl -X GET "https://quizapi.io/api/v1/questions?category=Programming,DevOps&difficulty=EASY,MEDIUM&type=MULTIPLE_CHOICE&tags=javascript,react&limit=10&offset=0" \
  -H "Authorization: Bearer YOUR_API_KEY"

Example Response

json
{
  "success": true,
  "data": [
    {
      "id": "ques_xyz789",
      "text": "What is the typeof null in JavaScript?",
      "type": "MULTIPLE_CHOICE",
      "difficulty": "MEDIUM",
      "explanation": "typeof null returns 'object' due to a legacy bug.",
      "category": "Programming",
      "tags": ["javascript", "fundamentals"],
      "quizId": "quiz_abc123",
      "quizTitle": "JavaScript Essentials",
      "answers": [
        { "id": "ans_1", "text": "null", "isCorrect": false },
        { "id": "ans_2", "text": "object", "isCorrect": true },
        { "id": "ans_3", "text": "undefined", "isCorrect": false },
        { "id": "ans_4", "text": "string", "isCorrect": false }
      ]
    }
  ],
  "meta": {
    "total": 23,
    "pageTotal": 1,
    "page": 1,
    "lastPage": 3,
    "limit": 10,
    "offset": 0,
    "links": {
      "first": "/api/v1/questions?...&offset=0&limit=10",
      "last": "/api/v1/questions?...&offset=20&limit=10",
      "next": "/api/v1/questions?...&offset=10&limit=10",
      "prev": null
    }
  }
}

Pagination Meta Object

FieldTypeDescription
totalintegerTotal number of questions matching your filters (across all pages)
pageTotalintegerNumber of questions returned in this page
pageintegerCurrent page number (1-based)
lastPageintegerTotal number of pages available
limitintegerThe limit value used for this request
offsetintegerThe offset value used for this request
linksobjectPagination links: first, last, next (null on last page), prev (null on first page)
POST/api/v1/quizzes/{id}/questions/batch

Batch Import Questions

Import up to 50 questions into an existing quiz in a single request. Questions are validated and inserted atomically — if any question fails validation, the entire batch is rejected. New questions are appended after existing ones with automatic ordering.

Starter / Pro plan required20 requests/min rate limit

Request Body

FieldTypeDescription
questionsRequiredarrayArray of question objects (1–50 items)
questions[].textRequiredstringThe question text
questions[].typeRequiredstringOne of MULTIPLE_CHOICE, TRUE_FALSE, or OPEN_ENDED
questions[].difficultyRequiredstringOne of EASY, MEDIUM, HARD, or EXPERT
questions[].explanationstringOptional explanation shown after answering
questions[].answersRequiredarrayArray of answer objects (min 2). Each has text (string) and isCorrect (boolean). At least one must be correct (except OPEN_ENDED). TRUE_FALSE must have exactly 2 answers.

Example Request

bash
curl -X POST "https://quizapi.io/api/v1/quizzes/quiz_abc123/questions/batch" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "questions": [
      {
        "text": "What is a closure in JavaScript?",
        "type": "MULTIPLE_CHOICE",
        "difficulty": "MEDIUM",
        "explanation": "A closure is a function that retains access to its outer scope.",
        "answers": [
          { "text": "A function with access to outer scope variables", "isCorrect": true },
          { "text": "A way to close a browser window", "isCorrect": false },
          { "text": "A CSS layout technique", "isCorrect": false },
          { "text": "A type of HTML element", "isCorrect": false }
        ]
      }
    ]
  }'

Example Response

json
{
  "success": true,
  "data": {
    "quizId": "quiz_abc123",
    "questionsCreated": 1,
    "questions": [
      {
        "id": "ques_new789",
        "text": "What is a closure in JavaScript?",
        "type": "MULTIPLE_CHOICE",
        "difficulty": "MEDIUM",
        "order": 11,
        "explanation": "A closure is a function that retains access to its outer scope.",
        "answers": [
          { "id": "ans_a1", "text": "A function with access to outer scope variables", "isCorrect": true },
          { "id": "ans_a2", "text": "A way to close a browser window", "isCorrect": false },
          { "id": "ans_a3", "text": "A CSS layout technique", "isCorrect": false },
          { "id": "ans_a4", "text": "A type of HTML element", "isCorrect": false }
        ]
      }
    ]
  }
}

Error Responses

Status CodeDescription
400Invalid JSON in request body
401Missing or invalid API key
403Free plan (upgrade required) or not the quiz owner
404Quiz not found
422Validation failed (returns detailed error array in details)
429Rate limit exceeded (20 requests/min)

Response Format

All API responses follow a consistent format. Successful responses wrap the result in a data key. Browse endpoints include a meta object with pagination info and navigation links.

Status CodeDescription
200Successful request
201Resource created (batch import)
400Bad request (invalid difficulty, type, or other validation error)
401Unauthorized (missing or invalid API key)
429Rate limit exceeded