{"openapi":"3.1.0","info":{"title":"Casa Academy Public API","summary":"Machine-readable catalog for Casa Academy exam prep and Florida licensing courses.","description":"Public, unauthenticated catalog for agents. LMS student routes stay cookie-authenticated and are not part of this spec. Rate limit: 120 requests per 60 seconds per client IP. Responses include RateLimit, RateLimit-Policy, X-RateLimit-* headers, and Retry-After on HTTP 429.","version":"1.0.0","contact":{"name":"Casa Academy","email":"shie@cxoxo.io","url":"https://casaacademy.com/developers"},"license":{"name":"Casa Academy public catalog","url":"https://casaacademy.com/developers"}},"servers":[{"url":"https://casaacademy.com","description":"Casa Academy production"}],"tags":[{"name":"Catalog","description":"Public course and exam-prep discovery."},{"name":"MCP","description":"JSON-RPC Model Context Protocol surface."},{"name":"Discovery","description":"OpenAPI, well-known catalogs, and agent skills."}],"paths":{"/api/health":{"get":{"operationId":"getHealth","tags":["Discovery"],"summary":"Service health","description":"Returns Casa Academy public API liveness without authentication.","responses":{"200":{"description":"Service is up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}}}},"/api/catalog/courses":{"get":{"operationId":"listPublicCourses","tags":["Catalog"],"summary":"List public catalog courses","description":"Returns enrollable Casa Academy products agents can deep-link. Nationwide exam prep is included as nationwide-exam-prep.","responses":{"200":{"description":"Public catalog courses.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CourseList"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/catalog/exam-prep":{"get":{"operationId":"getPublicExamPrepInfo","tags":["Catalog"],"summary":"Exam prep product URLs","description":"Florida paid exam prep, Florida free diagnostic, and the nationwide practice-exam hub. Does not invent prices.","responses":{"200":{"description":"Exam-prep URLs and notes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExamPrepInfo"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/catalog/enrollment":{"get":{"operationId":"getPublicEnrollmentUrl","tags":["Catalog"],"summary":"Resolve an enrollment URL by catalog slug","description":"Maps a known catalog slug to its canonical enroll or hub URL. Unknown slugs return HTTP 400.","parameters":[{"name":"slug","in":"query","required":true,"description":"Catalog slug from listPublicCourses.","schema":{"type":"string","enum":["nationwide-exam-prep","florida-63-hour-pre-licensing-course","spanish","exam-prep","postlicensing","continuing-education"]}}],"responses":{"200":{"description":"Resolved enrollment URL.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Enrollment"}}}},"400":{"description":"Unknown or missing slug.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/catalog/graphql":{"get":{"operationId":"getPublicGraphql","tags":["Catalog"],"summary":"Public catalog GraphQL (query string)","description":"Typed public catalog GraphQL with introspection enabled. Payload admin GraphQL at /api/graphql is not this schema.","parameters":[{"name":"query","in":"query","required":true,"description":"GraphQL query document.","schema":{"type":"string"}},{"name":"variables","in":"query","required":false,"description":"JSON-encoded GraphQL variables.","schema":{"type":"string"}}],"responses":{"200":{"description":"GraphQL execution result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GraphqlResult"}}}},"400":{"description":"Missing query.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"operationId":"postPublicGraphql","tags":["Catalog"],"summary":"Public catalog GraphQL","description":"POST a GraphQL document against the public catalog schema. Introspection is enabled. Cost is one request against the 120/60s public rate limit.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GraphqlRequest"}}}},"responses":{"200":{"description":"GraphQL execution result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GraphqlResult"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/mcp":{"get":{"operationId":"getMcpDiscovery","tags":["MCP"],"summary":"MCP discovery pointer","description":"Returns the well-known MCP server card URL for Casa Academy.","responses":{"200":{"description":"MCP discovery payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDiscovery"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"operationId":"postMcpJsonRpc","tags":["MCP"],"summary":"MCP JSON-RPC","description":"JSON-RPC 2.0 MCP endpoint. Tools: list_courses, get_exam_prep_info, get_enrollment_url. Resources include llms.txt, OpenAPI, and sitemap.xml.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcRequest"}}}},"responses":{"200":{"description":"JSON-RPC response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/openapi.json":{"get":{"operationId":"getOpenApiSpec","tags":["Discovery"],"summary":"OpenAPI 3.1 specification","description":"This document. Also published at /api/openapi.json.","responses":{"200":{"description":"OpenAPI document.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/api/openapi.json":{"get":{"operationId":"getOpenApiSpecAlias","tags":["Discovery"],"summary":"OpenAPI 3.1 specification (API alias)","description":"Same document as /openapi.json.","responses":{"200":{"description":"OpenAPI document.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/.well-known/api-catalog":{"get":{"operationId":"getApiCatalog","tags":["Discovery"],"summary":"RFC 9727 API catalog","description":"Linkset pointing at the OpenAPI spec, developers page, and MCP card.","responses":{"200":{"description":"API catalog linkset.","content":{"application/linkset+json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/.well-known/mcp/server-card.json":{"get":{"operationId":"getMcpServerCard","tags":["MCP"],"summary":"MCP server card","description":"Machine card for the Casa Academy MCP server.","responses":{"200":{"description":"MCP server card JSON.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/.well-known/mcp.json":{"get":{"operationId":"getMcpWellKnownJson","tags":["MCP"],"summary":"MCP well-known alias","description":"Alias of the MCP server card at /.well-known/mcp.json for agents that probe that path.","responses":{"200":{"description":"MCP server card JSON (same body as /.well-known/mcp/server-card.json).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/.well-known/agent-skills/index.json":{"get":{"operationId":"listAgentSkills","tags":["Discovery"],"summary":"Agent skills index","description":"Lists published Casa Academy agent skills.","responses":{"200":{"description":"Agent skills index.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/.well-known/agent-skills/{slug}/SKILL.md":{"get":{"operationId":"getAgentSkill","tags":["Discovery"],"summary":"Agent skill markdown","description":"Returns one SKILL.md by slug. Unknown slugs return HTTP 404 markdown.","parameters":[{"name":"slug","in":"path","required":true,"description":"Skill slug from the agent-skills index.","schema":{"type":"string"}}],"responses":{"200":{"description":"Skill markdown.","content":{"text/markdown":{"schema":{"type":"string"}}}},"404":{"description":"Unknown skill slug.","content":{"text/markdown":{"schema":{"type":"string"}}}}}}}},"components":{"schemas":{"Health":{"type":"object","additionalProperties":false,"required":["status","service","timestamp"],"properties":{"status":{"type":"string","enum":["ok"]},"service":{"type":"string","enum":["casa-academy"]},"timestamp":{"type":"string","format":"date-time"}}},"Course":{"type":"object","additionalProperties":false,"required":["slug","title","description","url","language"],"properties":{"slug":{"type":"string","enum":["nationwide-exam-prep","florida-63-hour-pre-licensing-course","spanish","exam-prep","postlicensing","continuing-education"]},"title":{"type":"string"},"description":{"type":"string"},"url":{"type":"string","format":"uri"},"language":{"type":"string","enum":["en","es"]}}},"CourseList":{"type":"object","additionalProperties":false,"required":["courses"],"properties":{"courses":{"type":"array","items":{"$ref":"#/components/schemas/Course"}}}},"ExamPrepInfo":{"type":"object","additionalProperties":false,"required":["product","enrollmentUrl","freeVersionUrl","nationwideHubUrl","currency","note"],"properties":{"product":{"type":"string"},"enrollmentUrl":{"type":"string","format":"uri"},"freeVersionUrl":{"type":"string","format":"uri"},"nationwideHubUrl":{"type":"string","format":"uri"},"currency":{"type":"string","enum":["USD"]},"note":{"type":"string"}}},"Enrollment":{"type":"object","additionalProperties":false,"required":["slug","title","url"],"properties":{"slug":{"type":"string"},"title":{"type":"string"},"url":{"type":"string","format":"uri"}}},"Error":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"string"},"message":{"type":"string"}}},"GraphqlRequest":{"type":"object","additionalProperties":false,"required":["query"],"properties":{"query":{"type":"string"},"variables":{"type":"object","additionalProperties":true},"operationName":{"type":"string"}}},"GraphqlResult":{"type":"object","additionalProperties":true,"properties":{"data":{"type":"object","additionalProperties":true},"errors":{"type":"array","items":{"type":"object","additionalProperties":true}}}},"McpDiscovery":{"type":"object","additionalProperties":false,"required":["mcp"],"properties":{"mcp":{"type":"string","format":"uri"},"name":{"type":"string"},"protocolVersion":{"type":"string"},"card":{"type":"string","format":"uri"},"transport":{"type":"string"},"contact":{"type":"string","format":"email"}}},"JsonRpcRequest":{"type":"object","additionalProperties":true,"required":["jsonrpc","method"],"properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{},"method":{"type":"string"},"params":{"type":"object","additionalProperties":true}}},"JsonRpcResponse":{"type":"object","additionalProperties":true,"required":["jsonrpc"],"properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{},"result":{},"error":{"type":"object","additionalProperties":true}}}},"responses":{"RateLimited":{"description":"Rate limited (120 requests per 60s).","headers":{"RateLimit":{"description":"IETF-style remaining quota.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds until the window resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}