Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.quiz-quail.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Quiz Quail API uses RFC 9457 Problem Details for all error responses. Every error response has Content-Type: application/problem+json and a consistent JSON structure.

Error Format

{
  "type": "https://quizquail.com/problems/not-found",
  "title": "Not Found",
  "status": 404,
  "detail": "Quiz 'quiz_abc123' not found"
}
FieldTypeDescription
typestringA URI identifying the error type. Stable — safe to match on.
titlestringShort human-readable summary of the error type.
statusnumberHTTP status code.
detailstringHuman-readable explanation specific to this occurrence.
instancestring(Optional) URI identifying this specific error occurrence.
errorsarray(Optional) Field-level validation errors. See below.

Error Types

400 — Validation Error

Returned when the request body or query parameters fail validation.
{
  "type": "https://quizquail.com/problems/validation-error",
  "title": "Validation Error",
  "status": 400,
  "detail": "Request validation failed",
  "errors": [
    { "field": "title", "message": "Required", "code": "invalid_type" },
    { "field": "rounds", "message": "Array must contain at least 1 element(s)", "code": "too_small" }
  ]
}
The errors array contains per-field details:
FieldTypeDescription
fieldstringDot-separated path to the invalid field.
messagestringHuman-readable description of the problem.
codestring(Optional) Machine-readable error code.

401 — Unauthorized

Returned when the request is missing or has an invalid API key.
{
  "type": "https://quizquail.com/problems/unauthorized",
  "title": "Unauthorized",
  "status": 401,
  "detail": "Authentication required"
}

403 — Forbidden

Returned when the API key does not have the required scope for the operation.
{
  "type": "https://quizquail.com/problems/forbidden",
  "title": "Forbidden",
  "status": 403,
  "detail": "You do not have permission to perform this action"
}

404 — Not Found

Returned when the requested resource does not exist or is not accessible to your account.
{
  "type": "https://quizquail.com/problems/not-found",
  "title": "Not Found",
  "status": 404,
  "detail": "Quiz 'quiz_abc123' not found"
}

409 — Conflict

Returned when the request conflicts with the current state of a resource (e.g., trying to render a quiz that is already rendering).
{
  "type": "https://quizquail.com/problems/conflict",
  "title": "Conflict",
  "status": 409,
  "detail": "A render is already in progress for this quiz"
}

429 — Too Many Requests

Returned when you exceed the rate limit for the endpoint. Includes a Retry-After header.
{
  "type": "https://quizquail.com/problems/rate-limit-exceeded",
  "title": "Too Many Requests",
  "status": 429,
  "detail": "Rate limit exceeded. Try again in 12 seconds."
}

500 — Internal Server Error

Returned when an unexpected error occurs. The detail field will not contain sensitive information.
{
  "type": "https://quizquail.com/problems/internal-error",
  "title": "Internal Server Error",
  "status": 500,
  "detail": "An unexpected error occurred"
}

Handling Errors

Match on type, Not title

The type URI is stable and safe to use in error-handling logic. The title and detail fields are human-readable and may change.
async function createQuiz(apiKey, quizData) {
  const response = await fetch("https://app.quiz-quail.com/api/v1/quizzes", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${apiKey}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(quizData),
  });

  if (!response.ok) {
    const error = await response.json();

    switch (error.type) {
      case "https://quizquail.com/problems/validation-error":
        console.error("Validation failed:", error.errors);
        break;
      case "https://quizquail.com/problems/rate-limit-exceeded":
        const retryAfter = response.headers.get("Retry-After");
        console.error(`Rate limited. Retry in ${retryAfter}s`);
        break;
      case "https://quizquail.com/problems/unauthorized":
        console.error("Check your API key");
        break;
      default:
        console.error(`API error: ${error.detail}`);
    }

    throw new Error(error.detail);
  }

  return response.json();
}

Display Validation Errors

For 400 responses with field-level errors, map them to your form fields:
if (error.type === "https://quizquail.com/problems/validation-error") {
  for (const fieldError of error.errors) {
    console.error(`${fieldError.field}: ${fieldError.message}`);
    // e.g. "title: Required"
    // e.g. "rounds: Array must contain at least 1 element(s)"
  }
}