{"openapi":"3.1.0","info":{"title":"Floryan Simar API","version":"1.0.0","summary":"Read-only JSON API over the public content of theyoxy.be.","description":"A small, unauthenticated API for agents and tools that need structured facts about Floryan Simar: identity, skills, links and published blog posts. Every operation returns `application/json`. The site is served as static files, so a path with no prerendered document, an unsupported method or a post slug with no published post is answered by the host itself, as HTML; see `getPost`.","contact":{"name":"Floryan Simar","email":"floryan.simar@endevops.be","url":"https://www.theyoxy.be/contact"},"license":{"name":"All rights reserved","url":"https://www.theyoxy.be/privacy"}},"servers":[{"url":"https://www.theyoxy.be","description":"Production"}],"security":[],"tags":[{"name":"Index","description":"Discover the API surface."},{"name":"Profile","description":"Who Floryan is and how to reach him."},{"name":"Posts","description":"Published blog posts."},{"name":"Health","description":"Liveness checks."}],"paths":{"/api":{"get":{"operationId":"getApiIndex","summary":"List the API endpoints","description":"Returns the API name, version, OpenAPI document URL and every available operation. Start here when you do not know which endpoint to call.","tags":["Index"],"responses":{"200":{"description":"API index.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiIndex"}}}},"404":{"description":"Structured error. The body always has an `error` object with a stable code, a human message and a resolution hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Structured error. The body always has an `error` object with a stable code, a human message and a resolution hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Structured error. The body always has an `error` object with a stable code, a human message and a resolution hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/profile":{"get":{"operationId":"getProfile","summary":"Get the professional profile","description":"Returns identity, job title, location, availability, spoken languages, core skills and canonical links. Use this to answer who Floryan Simar is, where he is based, what he works with and where his résumé and portfolio live.","tags":["Profile"],"responses":{"200":{"description":"The profile.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Profile"}}}},"404":{"description":"Structured error. The body always has an `error` object with a stable code, a human message and a resolution hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Structured error. The body always has an `error` object with a stable code, a human message and a resolution hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Structured error. The body always has an `error` object with a stable code, a human message and a resolution hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/posts":{"get":{"operationId":"listPosts","summary":"List published blog posts","description":"Returns every published post, newest first, with its slug, title, description, ISO date, tags and canonical URL. Draft posts are excluded. Use the slug with `getPost` to read the full text.","tags":["Posts"],"responses":{"200":{"description":"The post list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostList"}}}},"404":{"description":"Structured error. The body always has an `error` object with a stable code, a human message and a resolution hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Structured error. The body always has an `error` object with a stable code, a human message and a resolution hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Structured error. The body always has an `error` object with a stable code, a human message and a resolution hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/posts/{slug}":{"get":{"operationId":"getPost","summary":"Get one blog post","description":"Returns a single published post with its metadata, canonical URL and Markdown source. One document is prerendered per published slug, so a slug with no published post is answered by the host's plain 404 page, not by this API. `listPosts` returns the valid slugs.","tags":["Posts"],"parameters":[{"name":"slug","in":"path","required":true,"description":"The post slug from `listPosts`, for example `welcome`.","schema":{"type":"string","minLength":1,"examples":["welcome"]}}],"responses":{"200":{"description":"The post.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Post"}}}},"400":{"description":"Structured error. The body always has an `error` object with a stable code, a human message and a resolution hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error. The body always has an `error` object with a stable code, a human message and a resolution hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Structured error. The body always has an `error` object with a stable code, a human message and a resolution hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Structured error. The body always has an `error` object with a stable code, a human message and a resolution hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/health":{"get":{"operationId":"getHealth","summary":"Check that the API is alive","description":"Returns `status: ok` with the service name. The document is a static file, so it carries no timestamp. Not cached; use it as a liveness probe.","tags":["Health"],"responses":{"200":{"description":"The service is up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}},"404":{"description":"Structured error. The body always has an `error` object with a stable code, a human message and a resolution hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Structured error. The body always has an `error` object with a stable code, a human message and a resolution hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Structured error. The body always has an `error` object with a stable code, a human message and a resolution hint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"ApiIndex":{"type":"object","additionalProperties":false,"required":["name","description","version","openapi","endpoints"],"properties":{"name":{"type":"string","description":"Human-readable API name."},"description":{"type":"string","description":"What the API offers and its access model."},"version":{"type":"string","description":"API version segment used in the paths."},"openapi":{"type":"string","format":"uri","description":"URL of this OpenAPI document."},"endpoints":{"type":"array","description":"Every available operation.","items":{"type":"object","additionalProperties":false,"required":["method","path","description"],"properties":{"method":{"type":"string","enum":["GET"]},"path":{"type":"string","description":"Path template, with `{slug}` for path parameters."},"description":{"type":"string"}}}}}},"Profile":{"type":"object","additionalProperties":false,"required":["name","alternateName","jobTitle","description","location","availability","languages","skills","links"],"properties":{"name":{"type":"string","description":"Full name."},"alternateName":{"type":"string","description":"Online handle."},"jobTitle":{"type":"string","description":"Current professional title."},"description":{"type":"string","description":"One-paragraph summary."},"location":{"type":"object","additionalProperties":false,"required":["city","country","countryCode"],"properties":{"city":{"type":"string"},"country":{"type":"string"},"countryCode":{"type":"string","description":"ISO 3166-1 alpha-2 code.","minLength":2,"maxLength":2}}},"availability":{"type":"string","description":"Free-text availability status."},"languages":{"type":"array","description":"Spoken languages as ISO 639-1 codes.","items":{"type":"string"}},"skills":{"type":"array","description":"Core technologies.","items":{"type":"string"}},"links":{"type":"object","additionalProperties":false,"required":["website","github","email","photography","resume","portfolio","blog","docs","homeFr","resumeFr"],"properties":{"website":{"type":"string","format":"uri"},"github":{"type":"string","format":"uri"},"email":{"type":"string","description":"`mailto:` link."},"photography":{"type":"string","format":"uri"},"resume":{"type":"string","format":"uri"},"portfolio":{"type":"string","format":"uri"},"blog":{"type":"string","format":"uri"},"docs":{"type":"string","format":"uri"},"homeFr":{"type":"string","format":"uri","description":"French home page."},"resumeFr":{"type":"string","format":"uri","description":"French résumé."}}}}},"PostSummary":{"type":"object","additionalProperties":false,"required":["slug","title","description","date","tags","url"],"properties":{"slug":{"type":"string","description":"Stable identifier used by `getPost`."},"title":{"type":"string"},"description":{"type":"string","description":"Short summary written by the author."},"date":{"type":"string","format":"date","description":"Publication date in ISO 8601 form."},"tags":{"type":"array","items":{"type":"string"}},"url":{"type":"string","format":"uri","description":"Canonical HTML page."}}},"Post":{"type":"object","additionalProperties":false,"required":["slug","title","description","date","tags","url","markdown"],"properties":{"slug":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"date":{"type":"string","format":"date"},"tags":{"type":"array","items":{"type":"string"}},"url":{"type":"string","format":"uri"},"markdown":{"type":"string","description":"Full post body as Markdown source."}}},"PostList":{"type":"object","additionalProperties":false,"required":["count","posts"],"properties":{"count":{"type":"integer","minimum":0,"description":"Number of published posts."},"posts":{"type":"array","items":{"$ref":"#/components/schemas/PostSummary"}}}},"Health":{"type":"object","additionalProperties":false,"required":["status","service"],"properties":{"status":{"type":"string","enum":["ok"]},"service":{"type":"string","description":"Service identifier."}}},"Error":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message","hint"],"properties":{"code":{"type":"string","description":"Stable machine-readable code.","examples":["not_found","post_not_found","invalid_slug","method_not_allowed"]},"message":{"type":"string","description":"What went wrong, in one sentence."},"hint":{"type":"string","description":"What to try next."}}}}}}}}