{
  "openapi": "3.1.0",
  "info": {
    "title": "Vocab Voyage Public Vocabulary API",
    "version": "1.0.0",
    "description": "Zero-auth REST API for vocabulary definitions, courses, quizzes, word lists, and study plan previews. Designed for AI agents and developers."
  },
  "externalDocs": {
    "description": "Developer docs",
    "url": "https://vocab.voyage/developers"
  },
  "servers": [
    {
      "url": "https://gponcrussdahcdyrlhcr.supabase.co/functions/v1/vocab-api",
      "description": "Public vocabulary API function"
    }
  ],
  "security": [],
  "tags": [
    {
      "name": "Vocabulary",
      "description": "Definitions, word of the day, and study plans."
    },
    {
      "name": "Courses",
      "description": "Course catalog and course word lists."
    },
    {
      "name": "Quiz",
      "description": "Generated vocabulary quizzes."
    }
  ],
  "x-agent-use-cases": [
    "define vocabulary words",
    "generate SAT vocabulary quizzes",
    "list ISEE and SSAT courses",
    "preview GRE vocabulary study plans"
  ],
  "components": {
    "schemas": {
      "StructuredError": {
        "type": "object",
        "required": [
          "error_code",
          "message"
        ],
        "properties": {
          "error_code": {
            "type": "string",
            "examples": [
              "invalid_request",
              "not_found",
              "rate_limited",
              "server_error"
            ]
          },
          "message": {
            "type": "string"
          },
          "hint": {
            "type": "string"
          },
          "retry_after": {
            "type": "integer"
          }
        }
      },
      "Health": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "name": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "docs": {
            "type": "string"
          }
        }
      },
      "Word": {
        "type": "object",
        "properties": {
          "word": {
            "type": "string",
            "examples": [
              "aberrant"
            ]
          },
          "definition": {
            "type": "string"
          },
          "part_of_speech": {
            "type": [
              "string",
              "null"
            ]
          },
          "example": {
            "type": [
              "string",
              "null"
            ]
          },
          "synonym": {
            "type": [
              "string",
              "null"
            ]
          },
          "antonym": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Course": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "slug": {
            "type": "string",
            "examples": [
              "sat-vocab"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "grade_range": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Quiz": {
        "type": "object",
        "properties": {
          "test_family": {
            "type": "string"
          },
          "count": {
            "type": "integer"
          },
          "questions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "word": {
                  "type": "string"
                },
                "choices": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "answer": {
                  "type": "string"
                },
                "answer_index": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "StudyPlan": {
        "type": "object",
        "properties": {
          "test_family": {
            "type": "string"
          },
          "days": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "day": {
                  "type": "integer"
                },
                "focus": {
                  "type": "string"
                },
                "words": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "parameters": {
      "testFamily": {
        "name": "test_family",
        "in": "query",
        "schema": {
          "type": "string",
          "enum": [
            "isee",
            "ssat",
            "sat",
            "psat",
            "gre",
            "gmat",
            "lsat",
            "general"
          ]
        },
        "description": "Test family scope."
      }
    },
    "responses": {
      "Error": {
        "description": "Structured error",
        "headers": {
          "X-RateLimit-Limit": {
            "schema": {
              "type": "integer"
            },
            "description": "Request limit for this window."
          },
          "X-RateLimit-Remaining": {
            "schema": {
              "type": "integer"
            },
            "description": "Remaining requests in this window."
          },
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds to wait before retrying after 429."
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/StructuredError"
            },
            "examples": {
              "rateLimited": {
                "value": {
                  "error_code": "rate_limited",
                  "message": "Anonymous rate limit reached.",
                  "hint": "Wait and retry after the indicated number of seconds.",
                  "retry_after": 60
                }
              }
            }
          }
        }
      }
    }
  },
  "paths": {
    "/health": {
      "get": {
        "operationId": "getHealth",
        "tags": [
          "Vocabulary"
        ],
        "summary": "Check API health",
        "description": "Returns API status metadata and docs URL.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful JSON response",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Request limit for this window."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Remaining requests in this window."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying after 429."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/word-of-the-day": {
      "get": {
        "operationId": "getWordOfTheDay",
        "tags": [
          "Vocabulary"
        ],
        "summary": "Get today\u2019s vocabulary word",
        "description": "Returns a deterministic daily word, optionally scoped to a test family.",
        "parameters": [
          {
            "$ref": "#/components/parameters/testFamily"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful JSON response",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Request limit for this window."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Remaining requests in this window."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying after 429."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Word"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/definition": {
      "get": {
        "operationId": "getDefinition",
        "tags": [
          "Vocabulary"
        ],
        "summary": "Look up a vocabulary definition",
        "description": "Returns definition, part of speech, example, synonym, and antonym for a word.",
        "parameters": [
          {
            "name": "word",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "description": "Word to define.",
            "example": "aberrant"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful JSON response",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Request limit for this window."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Remaining requests in this window."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying after 429."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Word"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/courses": {
      "get": {
        "operationId": "listCourses",
        "tags": [
          "Courses"
        ],
        "summary": "List active courses",
        "description": "Lists Vocab Voyage courses with slugs for API calls.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful JSON response",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Request limit for this window."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Remaining requests in this window."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying after 429."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "courses": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Course"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/course-word-list": {
      "get": {
        "operationId": "getCourseWordList",
        "tags": [
          "Courses"
        ],
        "summary": "Get course word list",
        "description": "Returns a sample of words for a course slug.",
        "parameters": [
          {
            "name": "course_slug",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "sat-vocab"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful JSON response",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Request limit for this window."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Remaining requests in this window."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying after 429."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "course": {
                      "$ref": "#/components/schemas/Course"
                    },
                    "words": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Word"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/quiz": {
      "get": {
        "operationId": "generateQuiz",
        "tags": [
          "Quiz"
        ],
        "summary": "Generate vocabulary quiz",
        "description": "Returns multiple-choice quiz questions for a test family.",
        "parameters": [
          {
            "$ref": "#/components/parameters/testFamily"
          },
          {
            "name": "count",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10,
              "default": 5
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful JSON response",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Request limit for this window."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Remaining requests in this window."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying after 429."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quiz"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/study-plan-preview": {
      "get": {
        "operationId": "getStudyPlanPreview",
        "tags": [
          "Vocabulary"
        ],
        "summary": "Preview 7-day study plan",
        "description": "Returns a 7-day study plan preview for a test family.",
        "parameters": [
          {
            "$ref": "#/components/parameters/testFamily"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful JSON response",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Request limit for this window."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Remaining requests in this window."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying after 429."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudyPlan"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    }
  }
}