{
  "openapi": "3.1.1",
  "info": {
    "title": "heydenys.com Content API",
    "summary": "The portfolio of Denys Ishchenko, as structured data.",
    "description": "Read-only access to every page of heydenys.com — the personal\nportfolio of Denys Ishchenko, Senior User Experience Designer at PM-International,\nbased in Luxembourg.\n\nThis is a small static site, not a product. The API exists so that an\nagent can read the site's facts without parsing its HTML, and so that\nthe answers it gives cannot drift from the pages a human sees: every\nresponse here is generated from the same source as the rendered page.\n\n**No authentication.** Nothing here is private and no key is issued.\n\n**Versioning.** Every endpoint answers at two addresses. `/api/v1/...`\nis pinned to the v1 response shapes; `/api/...` returns identical\nbytes but always tracks the current major. Pin the versioned base if a\nstable shape matters. Nothing is deprecated today; when something is,\nit will say so with `Deprecation` and `Sunset` headers at least 180\ndays apart.\n\n**Rate limit.** 600 requests per 60 seconds per client address, at the\norigin, published in `RateLimit-Policy` on every response. Successful\nresponses are cached at the edge for an hour and mostly never reach the\norigin, so the live `RateLimit` counter appears only on responses that\nare not shared-cached — every error, and the 429 itself, which also\ncarries `Retry-After`.\n\n**Three ways in, in increasing cost.** `GET /llms-full.txt` is the whole\nsite in one response (about 18 KB) and is the cheapest way to answer\nalmost any question. `GET /api/v1/profile` is the structured facts about\nthe person. `GET /api/v1/pages` then `GET /api/v1/pages/{slug}` walks the\nsite page by page when a specific document is wanted.\n\n**Errors are JSON**, always, with a stable `error.code` and an\n`error.hint` naming the call that would have worked.",
    "version": "1.0.0",
    "contact": {
      "name": "Denys Ishchenko",
      "email": "me@heydenys.com",
      "url": "https://www.heydenys.com/contact"
    }
  },
  "servers": [
    {
      "url": "https://www.heydenys.com",
      "description": "Production"
    }
  ],
  "security": [],
  "externalDocs": {
    "description": "Human-readable documentation for this API",
    "url": "https://www.heydenys.com/docs"
  },
  "x-api-versioning": {
    "strategy": "url-path",
    "current": "v1",
    "versionedBase": "https://www.heydenys.com/api/v1",
    "unversionedBase": "https://www.heydenys.com/api",
    "versionHeader": "API-Version",
    "description": "Major versions live in the path. https://www.heydenys.com/api/v1 is pinned; https://www.heydenys.com/api serves the same bytes and tracks the current major. Every response also states its shape version in the `API-Version` header.",
    "deprecation": {
      "noticeDays": 180,
      "headers": [
        "Deprecation",
        "Sunset",
        "Link; rel=\"deprecation\""
      ],
      "description": "Nothing is deprecated. When something is, the responses that are going away start carrying `Deprecation` (RFC 9745) with the date the decision took effect and `Sunset` (RFC 8594) with the date they stop answering, at least 180 days apart, plus `Link: rel=\"deprecation\"` pointing at the page that explains it. A breaking change to a response shape is not a deprecation: it is a new major at /api/v2, and /api/v1 keeps answering until its own Sunset date. Pin /api/v1 if that matters; /api/... without a version always tracks the current major."
    }
  },
  "x-rate-limit": {
    "policy": "\"content\";q=600;w=60",
    "limit": 600,
    "window": "60s",
    "scope": "client address, at the origin",
    "headers": [
      "RateLimit-Policy",
      "RateLimit-Limit",
      "RateLimit",
      "Retry-After"
    ],
    "description": "600 requests per 60 seconds per client address, enforced at the origin and published in `RateLimit-Policy` on every response. Responses are cached at the edge for an hour, so a client that polls harder than that mostly sees the same bytes without being counted. The live `RateLimit` counter is sent only on responses that are not shared-cached — every JSON error, and the 429, which also carries `Retry-After`."
  },
  "x-cli": {
    "name": "heydenys",
    "description": "The heydenys.com command-line client: one dependency-free file, served by the API it calls, so reading this site from a script costs one download and no install step. It calls the pinned base, https://www.heydenys.com/api/v1.",
    "url": "https://www.heydenys.com/cli/heydenys.mjs",
    "install": "curl -fsSL https://www.heydenys.com/cli/heydenys.mjs -o heydenys.mjs",
    "run": "node heydenys.mjs profile",
    "commands": [
      "profile",
      "pages",
      "page <slug>",
      "read",
      "spec",
      "api"
    ],
    "requires": "Node 18+",
    "registries": [],
    "registriesNote": "Not published to npm, PyPI or Homebrew. The file above is the only distribution.",
    "documentation": "https://www.heydenys.com/docs"
  },
  "tags": [
    {
      "name": "discovery",
      "description": "Find out what exists before calling anything else."
    },
    {
      "name": "pages",
      "description": "The site's pages, as data."
    },
    {
      "name": "profile",
      "description": "The canonical facts about the person behind the site."
    },
    {
      "name": "files",
      "description": "The machine-readable files served at fixed paths outside /api."
    },
    {
      "name": "pinned",
      "description": "The same endpoints under /api/v1, pinned to the v1 response shapes. Identical bytes; safe to hard-code."
    }
  ],
  "paths": {
    "/api": {
      "get": {
        "operationId": "getApiIndex",
        "summary": "List the API's endpoints",
        "description": "Returns the endpoint list, the API version, the versioning and rate-limit policies, and links to this OpenAPI description and to the human documentation. Call it first when the shape of the API is unknown.",
        "tags": [
          "discovery"
        ],
        "responses": {
          "200": {
            "description": "The API index.",
            "headers": {
              "API-Version": {
                "description": "The response-shape version that produced this body.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "1.0.0"
                  ]
                }
              },
              "RateLimit-Policy": {
                "description": "The quota, as a Structured Fields list: policy name, `q` requests per `w` seconds.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "\"content\";q=600;w=60"
                  ]
                }
              },
              "RateLimit-Limit": {
                "description": "The same quota as a bare integer, for older clients.",
                "schema": {
                  "type": "integer",
                  "examples": [
                    600
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "title": "ApiIndex",
                  "description": "The API root: what exists, how it is versioned, and where it is described.",
                  "required": [
                    "name",
                    "version",
                    "versioning",
                    "rateLimit",
                    "documentation",
                    "openapi",
                    "endpoints"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string",
                      "description": "Response-shape version. Bumped only on a breaking change.",
                      "examples": [
                        "1.0.0"
                      ]
                    },
                    "versioning": {
                      "type": "object",
                      "title": "VersioningPolicy",
                      "description": "Which major a client is talking to, and how a removal would be announced before it happened.",
                      "required": [
                        "version",
                        "current",
                        "versionedBase",
                        "unversionedBase",
                        "policy",
                        "deprecation"
                      ],
                      "properties": {
                        "version": {
                          "type": "string",
                          "description": "Response-shape version. Bumped only on a breaking change.",
                          "examples": [
                            "1.0.0"
                          ]
                        },
                        "current": {
                          "type": "string",
                          "description": "The current major, as it appears in the path.",
                          "examples": [
                            "v1"
                          ]
                        },
                        "versionedBase": {
                          "type": "string",
                          "format": "uri",
                          "description": "Pinned base. Its response shapes will not change."
                        },
                        "unversionedBase": {
                          "type": "string",
                          "format": "uri",
                          "description": "Convenience base. Always tracks the current major."
                        },
                        "policy": {
                          "type": "string",
                          "description": "The difference between the two, in a sentence."
                        },
                        "deprecation": {
                          "type": "string",
                          "description": "How a removal is signalled: `Deprecation` and `Sunset` headers, at least 180 days apart."
                        },
                        "documentation": {
                          "type": "string",
                          "format": "uri"
                        }
                      }
                    },
                    "rateLimit": {
                      "type": "object",
                      "title": "RateLimitPolicy",
                      "description": "The quota, and which responses carry a live counter for it.",
                      "required": [
                        "limit",
                        "window",
                        "scope",
                        "headers"
                      ],
                      "properties": {
                        "limit": {
                          "type": "integer",
                          "description": "Requests per window, per client address, at the origin.",
                          "examples": [
                            600
                          ]
                        },
                        "window": {
                          "type": "string",
                          "description": "Window length.",
                          "examples": [
                            "60s"
                          ]
                        },
                        "scope": {
                          "type": "string",
                          "description": "What the counter is keyed on."
                        },
                        "headers": {
                          "type": "object",
                          "description": "Which header carries what, and on which responses.",
                          "additionalProperties": {
                            "type": "string"
                          }
                        },
                        "note": {
                          "type": "string",
                          "description": "Why a cached 200 carries no counter."
                        }
                      }
                    },
                    "documentation": {
                      "type": "string",
                      "format": "uri"
                    },
                    "openapi": {
                      "type": "string",
                      "format": "uri"
                    },
                    "endpoints": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "title": "Endpoint",
                        "description": "One callable endpoint, as listed by the API index.",
                        "required": [
                          "method",
                          "path",
                          "operationId",
                          "description",
                          "versionedPath"
                        ],
                        "properties": {
                          "method": {
                            "type": "string",
                            "enum": [
                              "GET"
                            ]
                          },
                          "path": {
                            "type": "string",
                            "description": "The unversioned address, which tracks the current major.",
                            "examples": [
                              "/api/pages"
                            ]
                          },
                          "versionedPath": {
                            "type": "string",
                            "description": "The same endpoint pinned to the current major. Identical bytes; safe to hard-code.",
                            "examples": [
                              "/api/v1/pages"
                            ]
                          },
                          "operationId": {
                            "type": "string",
                            "description": "Matches the operationId in the OpenAPI description."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mediaType": {
                            "type": "string",
                            "examples": [
                              "application/json"
                            ]
                          }
                        }
                      }
                    },
                    "files": {
                      "type": "object",
                      "description": "The machine-readable files served outside /api.",
                      "additionalProperties": {
                        "type": "string",
                        "format": "uri"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Nothing is served at that path.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "This API is read-only. The `Allow` header names what the endpoint accepts.",
            "headers": {
              "Allow": {
                "description": "The methods this endpoint accepts.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "GET, HEAD, OPTIONS"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header refuses application/json, which is all this endpoint produces.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds reached the origin from one client address. Wait for `Retry-After` seconds, or read /llms-full.txt once instead of polling.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "examples": [
                    42
                  ]
                }
              },
              "RateLimit": {
                "description": "The live window state: `r` requests left, `t` seconds until it resets.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "\"content\";r=0;t=42"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1": {
      "get": {
        "operationId": "getApiIndexV1",
        "summary": "List the API's endpoints (pinned to v1)",
        "description": "Returns the endpoint list, the API version, the versioning and rate-limit policies, and links to this OpenAPI description and to the human documentation. Call it first when the shape of the API is unknown.\n\nPinned to v1: this path answers with the v1 response shapes for as long as it exists, and a breaking change lands at /api/v2 instead. The unversioned path returns identical bytes but tracks whatever the current major is.",
        "tags": [
          "discovery",
          "pinned"
        ],
        "responses": {
          "200": {
            "description": "The API index.",
            "headers": {
              "API-Version": {
                "description": "The response-shape version that produced this body.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "1.0.0"
                  ]
                }
              },
              "RateLimit-Policy": {
                "description": "The quota, as a Structured Fields list: policy name, `q` requests per `w` seconds.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "\"content\";q=600;w=60"
                  ]
                }
              },
              "RateLimit-Limit": {
                "description": "The same quota as a bare integer, for older clients.",
                "schema": {
                  "type": "integer",
                  "examples": [
                    600
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "title": "ApiIndex",
                  "description": "The API root: what exists, how it is versioned, and where it is described.",
                  "required": [
                    "name",
                    "version",
                    "versioning",
                    "rateLimit",
                    "documentation",
                    "openapi",
                    "endpoints"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string",
                      "description": "Response-shape version. Bumped only on a breaking change.",
                      "examples": [
                        "1.0.0"
                      ]
                    },
                    "versioning": {
                      "type": "object",
                      "title": "VersioningPolicy",
                      "description": "Which major a client is talking to, and how a removal would be announced before it happened.",
                      "required": [
                        "version",
                        "current",
                        "versionedBase",
                        "unversionedBase",
                        "policy",
                        "deprecation"
                      ],
                      "properties": {
                        "version": {
                          "type": "string",
                          "description": "Response-shape version. Bumped only on a breaking change.",
                          "examples": [
                            "1.0.0"
                          ]
                        },
                        "current": {
                          "type": "string",
                          "description": "The current major, as it appears in the path.",
                          "examples": [
                            "v1"
                          ]
                        },
                        "versionedBase": {
                          "type": "string",
                          "format": "uri",
                          "description": "Pinned base. Its response shapes will not change."
                        },
                        "unversionedBase": {
                          "type": "string",
                          "format": "uri",
                          "description": "Convenience base. Always tracks the current major."
                        },
                        "policy": {
                          "type": "string",
                          "description": "The difference between the two, in a sentence."
                        },
                        "deprecation": {
                          "type": "string",
                          "description": "How a removal is signalled: `Deprecation` and `Sunset` headers, at least 180 days apart."
                        },
                        "documentation": {
                          "type": "string",
                          "format": "uri"
                        }
                      }
                    },
                    "rateLimit": {
                      "type": "object",
                      "title": "RateLimitPolicy",
                      "description": "The quota, and which responses carry a live counter for it.",
                      "required": [
                        "limit",
                        "window",
                        "scope",
                        "headers"
                      ],
                      "properties": {
                        "limit": {
                          "type": "integer",
                          "description": "Requests per window, per client address, at the origin.",
                          "examples": [
                            600
                          ]
                        },
                        "window": {
                          "type": "string",
                          "description": "Window length.",
                          "examples": [
                            "60s"
                          ]
                        },
                        "scope": {
                          "type": "string",
                          "description": "What the counter is keyed on."
                        },
                        "headers": {
                          "type": "object",
                          "description": "Which header carries what, and on which responses.",
                          "additionalProperties": {
                            "type": "string"
                          }
                        },
                        "note": {
                          "type": "string",
                          "description": "Why a cached 200 carries no counter."
                        }
                      }
                    },
                    "documentation": {
                      "type": "string",
                      "format": "uri"
                    },
                    "openapi": {
                      "type": "string",
                      "format": "uri"
                    },
                    "endpoints": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "title": "Endpoint",
                        "description": "One callable endpoint, as listed by the API index.",
                        "required": [
                          "method",
                          "path",
                          "operationId",
                          "description",
                          "versionedPath"
                        ],
                        "properties": {
                          "method": {
                            "type": "string",
                            "enum": [
                              "GET"
                            ]
                          },
                          "path": {
                            "type": "string",
                            "description": "The unversioned address, which tracks the current major.",
                            "examples": [
                              "/api/pages"
                            ]
                          },
                          "versionedPath": {
                            "type": "string",
                            "description": "The same endpoint pinned to the current major. Identical bytes; safe to hard-code.",
                            "examples": [
                              "/api/v1/pages"
                            ]
                          },
                          "operationId": {
                            "type": "string",
                            "description": "Matches the operationId in the OpenAPI description."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mediaType": {
                            "type": "string",
                            "examples": [
                              "application/json"
                            ]
                          }
                        }
                      }
                    },
                    "files": {
                      "type": "object",
                      "description": "The machine-readable files served outside /api.",
                      "additionalProperties": {
                        "type": "string",
                        "format": "uri"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Nothing is served at that path.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "This API is read-only. The `Allow` header names what the endpoint accepts.",
            "headers": {
              "Allow": {
                "description": "The methods this endpoint accepts.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "GET, HEAD, OPTIONS"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header refuses application/json, which is all this endpoint produces.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds reached the origin from one client address. Wait for `Retry-After` seconds, or read /llms-full.txt once instead of polling.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "examples": [
                    42
                  ]
                }
              },
              "RateLimit": {
                "description": "The live window state: `r` requests left, `t` seconds until it resets.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "\"content\";r=0;t=42"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/pages": {
      "get": {
        "operationId": "listPages",
        "summary": "List every page on the site",
        "description": "Every page in navigation order, each with its title, one-sentence summary, canonical URL, Markdown URL and last-modified date. The body of a page is not included; fetch it with getPage.",
        "tags": [
          "pages"
        ],
        "responses": {
          "200": {
            "description": "Every page on the site.",
            "headers": {
              "API-Version": {
                "description": "The response-shape version that produced this body.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "1.0.0"
                  ]
                }
              },
              "RateLimit-Policy": {
                "description": "The quota, as a Structured Fields list: policy name, `q` requests per `w` seconds.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "\"content\";q=600;w=60"
                  ]
                }
              },
              "RateLimit-Limit": {
                "description": "The same quota as a bare integer, for older clients.",
                "schema": {
                  "type": "integer",
                  "examples": [
                    600
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "title": "PageList",
                  "description": "Every page on the site, in navigation order.",
                  "required": [
                    "count",
                    "pages"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer",
                      "examples": [
                        10
                      ]
                    },
                    "pages": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "title": "PageSummary",
                        "description": "One page of the site, without its body.",
                        "required": [
                          "path",
                          "slug",
                          "title",
                          "summary",
                          "url",
                          "markdownUrl",
                          "apiUrl",
                          "lastModified",
                          "priority"
                        ],
                        "properties": {
                          "path": {
                            "type": "string",
                            "description": "Site-relative path, always starting with a slash.",
                            "examples": [
                              "/about"
                            ]
                          },
                          "slug": {
                            "type": "string",
                            "description": "The identifier used by /api/pages/{slug}. The homepage is `index`.",
                            "enum": [
                              "index",
                              "about",
                              "playground",
                              "fitline",
                              "monroe",
                              "help-center",
                              "telegram-contest",
                              "contact",
                              "docs",
                              "privacy"
                            ]
                          },
                          "title": {
                            "type": "string",
                            "description": "The page's own H1.",
                            "examples": [
                              "About Denys Ishchenko"
                            ]
                          },
                          "summary": {
                            "type": "string",
                            "description": "One line saying what is actually on the page — the same text /llms.txt uses, written to be read in a list rather than on its own.",
                            "examples": [
                              "biography and full career history, with dates and figures"
                            ]
                          },
                          "url": {
                            "type": "string",
                            "format": "uri",
                            "description": "Canonical HTML URL."
                          },
                          "markdownUrl": {
                            "type": "string",
                            "format": "uri",
                            "description": "The same page as Markdown. The canonical URL also serves it to `Accept: text/markdown`."
                          },
                          "apiUrl": {
                            "type": "string",
                            "format": "uri",
                            "description": "This page as JSON, including its full Markdown body."
                          },
                          "lastModified": {
                            "type": "string",
                            "format": "date",
                            "description": "The date the page's content last changed, not the last deploy.",
                            "examples": [
                              "2026-08-18"
                            ]
                          },
                          "priority": {
                            "type": "number",
                            "minimum": 0,
                            "maximum": 1,
                            "description": "Relative importance within the site, as in the sitemap."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Nothing is served at that path.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "This API is read-only. The `Allow` header names what the endpoint accepts.",
            "headers": {
              "Allow": {
                "description": "The methods this endpoint accepts.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "GET, HEAD, OPTIONS"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header refuses application/json, which is all this endpoint produces.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds reached the origin from one client address. Wait for `Retry-After` seconds, or read /llms-full.txt once instead of polling.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "examples": [
                    42
                  ]
                }
              },
              "RateLimit": {
                "description": "The live window state: `r` requests left, `t` seconds until it resets.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "\"content\";r=0;t=42"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/pages": {
      "get": {
        "operationId": "listPagesV1",
        "summary": "List every page on the site (pinned to v1)",
        "description": "Every page in navigation order, each with its title, one-sentence summary, canonical URL, Markdown URL and last-modified date. The body of a page is not included; fetch it with getPage.\n\nPinned to v1: this path answers with the v1 response shapes for as long as it exists, and a breaking change lands at /api/v2 instead. The unversioned path returns identical bytes but tracks whatever the current major is.",
        "tags": [
          "pages",
          "pinned"
        ],
        "responses": {
          "200": {
            "description": "Every page on the site.",
            "headers": {
              "API-Version": {
                "description": "The response-shape version that produced this body.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "1.0.0"
                  ]
                }
              },
              "RateLimit-Policy": {
                "description": "The quota, as a Structured Fields list: policy name, `q` requests per `w` seconds.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "\"content\";q=600;w=60"
                  ]
                }
              },
              "RateLimit-Limit": {
                "description": "The same quota as a bare integer, for older clients.",
                "schema": {
                  "type": "integer",
                  "examples": [
                    600
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "title": "PageList",
                  "description": "Every page on the site, in navigation order.",
                  "required": [
                    "count",
                    "pages"
                  ],
                  "properties": {
                    "count": {
                      "type": "integer",
                      "examples": [
                        10
                      ]
                    },
                    "pages": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "title": "PageSummary",
                        "description": "One page of the site, without its body.",
                        "required": [
                          "path",
                          "slug",
                          "title",
                          "summary",
                          "url",
                          "markdownUrl",
                          "apiUrl",
                          "lastModified",
                          "priority"
                        ],
                        "properties": {
                          "path": {
                            "type": "string",
                            "description": "Site-relative path, always starting with a slash.",
                            "examples": [
                              "/about"
                            ]
                          },
                          "slug": {
                            "type": "string",
                            "description": "The identifier used by /api/pages/{slug}. The homepage is `index`.",
                            "enum": [
                              "index",
                              "about",
                              "playground",
                              "fitline",
                              "monroe",
                              "help-center",
                              "telegram-contest",
                              "contact",
                              "docs",
                              "privacy"
                            ]
                          },
                          "title": {
                            "type": "string",
                            "description": "The page's own H1.",
                            "examples": [
                              "About Denys Ishchenko"
                            ]
                          },
                          "summary": {
                            "type": "string",
                            "description": "One line saying what is actually on the page — the same text /llms.txt uses, written to be read in a list rather than on its own.",
                            "examples": [
                              "biography and full career history, with dates and figures"
                            ]
                          },
                          "url": {
                            "type": "string",
                            "format": "uri",
                            "description": "Canonical HTML URL."
                          },
                          "markdownUrl": {
                            "type": "string",
                            "format": "uri",
                            "description": "The same page as Markdown. The canonical URL also serves it to `Accept: text/markdown`."
                          },
                          "apiUrl": {
                            "type": "string",
                            "format": "uri",
                            "description": "This page as JSON, including its full Markdown body."
                          },
                          "lastModified": {
                            "type": "string",
                            "format": "date",
                            "description": "The date the page's content last changed, not the last deploy.",
                            "examples": [
                              "2026-08-18"
                            ]
                          },
                          "priority": {
                            "type": "number",
                            "minimum": 0,
                            "maximum": 1,
                            "description": "Relative importance within the site, as in the sitemap."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Nothing is served at that path.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "This API is read-only. The `Allow` header names what the endpoint accepts.",
            "headers": {
              "Allow": {
                "description": "The methods this endpoint accepts.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "GET, HEAD, OPTIONS"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header refuses application/json, which is all this endpoint produces.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds reached the origin from one client address. Wait for `Retry-After` seconds, or read /llms-full.txt once instead of polling.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "examples": [
                    42
                  ]
                }
              },
              "RateLimit": {
                "description": "The live window state: `r` requests left, `t` seconds until it resets.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "\"content\";r=0;t=42"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/pages/{slug}": {
      "get": {
        "operationId": "getPage",
        "summary": "Get one page, including its full Markdown body",
        "description": "The complete content of a single page as Markdown, plus the same metadata listPages returns. The Markdown is the site's own hand-written representation of the page, not a conversion of its HTML.",
        "tags": [
          "pages"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Which page. This is the path without its leading slash; the homepage is `index`.",
            "schema": {
              "type": "string",
              "enum": [
                "index",
                "about",
                "playground",
                "fitline",
                "monroe",
                "help-center",
                "telegram-contest",
                "contact",
                "docs",
                "privacy"
              ]
            },
            "example": "about"
          }
        ],
        "responses": {
          "200": {
            "description": "The page and its body.",
            "headers": {
              "API-Version": {
                "description": "The response-shape version that produced this body.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "1.0.0"
                  ]
                }
              },
              "RateLimit-Policy": {
                "description": "The quota, as a Structured Fields list: policy name, `q` requests per `w` seconds.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "\"content\";q=600;w=60"
                  ]
                }
              },
              "RateLimit-Limit": {
                "description": "The same quota as a bare integer, for older clients.",
                "schema": {
                  "type": "integer",
                  "examples": [
                    600
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "title": "PageDocument",
                  "description": "A page's metadata together with its complete Markdown body.",
                  "required": [
                    "page",
                    "format",
                    "markdown"
                  ],
                  "properties": {
                    "page": {
                      "type": "object",
                      "title": "PageSummary",
                      "description": "One page of the site, without its body.",
                      "required": [
                        "path",
                        "slug",
                        "title",
                        "summary",
                        "url",
                        "markdownUrl",
                        "apiUrl",
                        "lastModified",
                        "priority"
                      ],
                      "properties": {
                        "path": {
                          "type": "string",
                          "description": "Site-relative path, always starting with a slash.",
                          "examples": [
                            "/about"
                          ]
                        },
                        "slug": {
                          "type": "string",
                          "description": "The identifier used by /api/pages/{slug}. The homepage is `index`.",
                          "enum": [
                            "index",
                            "about",
                            "playground",
                            "fitline",
                            "monroe",
                            "help-center",
                            "telegram-contest",
                            "contact",
                            "docs",
                            "privacy"
                          ]
                        },
                        "title": {
                          "type": "string",
                          "description": "The page's own H1.",
                          "examples": [
                            "About Denys Ishchenko"
                          ]
                        },
                        "summary": {
                          "type": "string",
                          "description": "One line saying what is actually on the page — the same text /llms.txt uses, written to be read in a list rather than on its own.",
                          "examples": [
                            "biography and full career history, with dates and figures"
                          ]
                        },
                        "url": {
                          "type": "string",
                          "format": "uri",
                          "description": "Canonical HTML URL."
                        },
                        "markdownUrl": {
                          "type": "string",
                          "format": "uri",
                          "description": "The same page as Markdown. The canonical URL also serves it to `Accept: text/markdown`."
                        },
                        "apiUrl": {
                          "type": "string",
                          "format": "uri",
                          "description": "This page as JSON, including its full Markdown body."
                        },
                        "lastModified": {
                          "type": "string",
                          "format": "date",
                          "description": "The date the page's content last changed, not the last deploy.",
                          "examples": [
                            "2026-08-18"
                          ]
                        },
                        "priority": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 1,
                          "description": "Relative importance within the site, as in the sitemap."
                        }
                      }
                    },
                    "format": {
                      "type": "string",
                      "description": "The media type of `markdown`.",
                      "const": "text/markdown"
                    },
                    "markdown": {
                      "type": "string",
                      "description": "The whole page as Markdown — byte-identical to what markdownUrl returns."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No page has that slug. The body lists every slug that exists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "This API is read-only. The `Allow` header names what the endpoint accepts.",
            "headers": {
              "Allow": {
                "description": "The methods this endpoint accepts.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "GET, HEAD, OPTIONS"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header refuses application/json, which is all this endpoint produces.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds reached the origin from one client address. Wait for `Retry-After` seconds, or read /llms-full.txt once instead of polling.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "examples": [
                    42
                  ]
                }
              },
              "RateLimit": {
                "description": "The live window state: `r` requests left, `t` seconds until it resets.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "\"content\";r=0;t=42"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/pages/{slug}": {
      "get": {
        "operationId": "getPageV1",
        "summary": "Get one page, including its full Markdown body (pinned to v1)",
        "description": "The complete content of a single page as Markdown, plus the same metadata listPages returns. The Markdown is the site's own hand-written representation of the page, not a conversion of its HTML.\n\nPinned to v1: this path answers with the v1 response shapes for as long as it exists, and a breaking change lands at /api/v2 instead. The unversioned path returns identical bytes but tracks whatever the current major is.",
        "tags": [
          "pages",
          "pinned"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Which page. This is the path without its leading slash; the homepage is `index`.",
            "schema": {
              "type": "string",
              "enum": [
                "index",
                "about",
                "playground",
                "fitline",
                "monroe",
                "help-center",
                "telegram-contest",
                "contact",
                "docs",
                "privacy"
              ]
            },
            "example": "about"
          }
        ],
        "responses": {
          "200": {
            "description": "The page and its body.",
            "headers": {
              "API-Version": {
                "description": "The response-shape version that produced this body.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "1.0.0"
                  ]
                }
              },
              "RateLimit-Policy": {
                "description": "The quota, as a Structured Fields list: policy name, `q` requests per `w` seconds.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "\"content\";q=600;w=60"
                  ]
                }
              },
              "RateLimit-Limit": {
                "description": "The same quota as a bare integer, for older clients.",
                "schema": {
                  "type": "integer",
                  "examples": [
                    600
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "title": "PageDocument",
                  "description": "A page's metadata together with its complete Markdown body.",
                  "required": [
                    "page",
                    "format",
                    "markdown"
                  ],
                  "properties": {
                    "page": {
                      "type": "object",
                      "title": "PageSummary",
                      "description": "One page of the site, without its body.",
                      "required": [
                        "path",
                        "slug",
                        "title",
                        "summary",
                        "url",
                        "markdownUrl",
                        "apiUrl",
                        "lastModified",
                        "priority"
                      ],
                      "properties": {
                        "path": {
                          "type": "string",
                          "description": "Site-relative path, always starting with a slash.",
                          "examples": [
                            "/about"
                          ]
                        },
                        "slug": {
                          "type": "string",
                          "description": "The identifier used by /api/pages/{slug}. The homepage is `index`.",
                          "enum": [
                            "index",
                            "about",
                            "playground",
                            "fitline",
                            "monroe",
                            "help-center",
                            "telegram-contest",
                            "contact",
                            "docs",
                            "privacy"
                          ]
                        },
                        "title": {
                          "type": "string",
                          "description": "The page's own H1.",
                          "examples": [
                            "About Denys Ishchenko"
                          ]
                        },
                        "summary": {
                          "type": "string",
                          "description": "One line saying what is actually on the page — the same text /llms.txt uses, written to be read in a list rather than on its own.",
                          "examples": [
                            "biography and full career history, with dates and figures"
                          ]
                        },
                        "url": {
                          "type": "string",
                          "format": "uri",
                          "description": "Canonical HTML URL."
                        },
                        "markdownUrl": {
                          "type": "string",
                          "format": "uri",
                          "description": "The same page as Markdown. The canonical URL also serves it to `Accept: text/markdown`."
                        },
                        "apiUrl": {
                          "type": "string",
                          "format": "uri",
                          "description": "This page as JSON, including its full Markdown body."
                        },
                        "lastModified": {
                          "type": "string",
                          "format": "date",
                          "description": "The date the page's content last changed, not the last deploy.",
                          "examples": [
                            "2026-08-18"
                          ]
                        },
                        "priority": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 1,
                          "description": "Relative importance within the site, as in the sitemap."
                        }
                      }
                    },
                    "format": {
                      "type": "string",
                      "description": "The media type of `markdown`.",
                      "const": "text/markdown"
                    },
                    "markdown": {
                      "type": "string",
                      "description": "The whole page as Markdown — byte-identical to what markdownUrl returns."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No page has that slug. The body lists every slug that exists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "This API is read-only. The `Allow` header names what the endpoint accepts.",
            "headers": {
              "Allow": {
                "description": "The methods this endpoint accepts.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "GET, HEAD, OPTIONS"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header refuses application/json, which is all this endpoint produces.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds reached the origin from one client address. Wait for `Retry-After` seconds, or read /llms-full.txt once instead of polling.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "examples": [
                    42
                  ]
                }
              },
              "RateLimit": {
                "description": "The live window state: `r` requests left, `t` seconds until it resets.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "\"content\";r=0;t=42"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/profile": {
      "get": {
        "operationId": "getProfile",
        "summary": "Get the canonical facts about Denys Ishchenko",
        "description": "Role, employer, location, contact address, career history, skills, awards and verified profiles elsewhere — plus what this site is and is not a good source for. Every field is published on a page of the site; nothing is inferred. Where this and a third-party profile disagree, this is canonical.",
        "tags": [
          "profile"
        ],
        "responses": {
          "200": {
            "description": "The profile.",
            "headers": {
              "API-Version": {
                "description": "The response-shape version that produced this body.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "1.0.0"
                  ]
                }
              },
              "RateLimit-Policy": {
                "description": "The quota, as a Structured Fields list: policy name, `q` requests per `w` seconds.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "\"content\";q=600;w=60"
                  ]
                }
              },
              "RateLimit-Limit": {
                "description": "The same quota as a bare integer, for older clients.",
                "schema": {
                  "type": "integer",
                  "examples": [
                    600
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "title": "Profile",
                  "description": "The canonical facts about Denys Ishchenko. Every field is published on a page of this site; nothing here is inferred.",
                  "required": [
                    "name",
                    "jobTitle",
                    "employer",
                    "location",
                    "email",
                    "summary"
                  ],
                  "properties": {
                    "name": {
                      "type": "string",
                      "examples": [
                        "Denys Ishchenko"
                      ]
                    },
                    "headline": {
                      "type": "string",
                      "description": "How the site titles him.",
                      "examples": [
                        "Product Designer"
                      ]
                    },
                    "jobTitle": {
                      "type": "string",
                      "examples": [
                        "Senior User Experience Designer"
                      ]
                    },
                    "employer": {
                      "type": "string",
                      "examples": [
                        "PM-International"
                      ]
                    },
                    "location": {
                      "type": "object",
                      "required": [
                        "locality",
                        "countryCode"
                      ],
                      "properties": {
                        "locality": {
                          "type": "string",
                          "examples": [
                            "Luxembourg"
                          ]
                        },
                        "countryCode": {
                          "type": "string",
                          "description": "ISO 3166-1 alpha-2.",
                          "examples": [
                            "LU"
                          ]
                        }
                      }
                    },
                    "email": {
                      "type": "string",
                      "format": "email",
                      "description": "The only contact channel. There is no form and no phone."
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "summary": {
                      "type": "string",
                      "description": "One paragraph safe to quote verbatim."
                    },
                    "expertise": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Skills, each evidenced by a page on this site."
                    },
                    "awards": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "roles": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "title": "Role",
                        "description": "One position from the career history published on /about.",
                        "required": [
                          "title",
                          "organization",
                          "period",
                          "notes"
                        ],
                        "properties": {
                          "title": {
                            "type": "string",
                            "description": "Job title."
                          },
                          "organization": {
                            "type": "string",
                            "description": "Employer or client."
                          },
                          "period": {
                            "type": "string",
                            "description": "Free-text date range, as written on the page.",
                            "examples": [
                              "April 2023 – present"
                            ]
                          },
                          "notes": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "What the role covered, one bullet per line on the page."
                          }
                        }
                      },
                      "description": "Career history, most recent first."
                    },
                    "profiles": {
                      "type": "array",
                      "description": "Verified profiles elsewhere, and the resume.",
                      "items": {
                        "type": "object",
                        "required": [
                          "label",
                          "url"
                        ],
                        "properties": {
                          "label": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string",
                            "format": "uri"
                          }
                        }
                      }
                    },
                    "goodFits": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Questions this site can answer well."
                    },
                    "poorFits": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Questions it cannot. Answering these from this site produces something wrong."
                    },
                    "howToUse": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "How an agent should call this site."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Nothing is served at that path.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "This API is read-only. The `Allow` header names what the endpoint accepts.",
            "headers": {
              "Allow": {
                "description": "The methods this endpoint accepts.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "GET, HEAD, OPTIONS"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header refuses application/json, which is all this endpoint produces.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds reached the origin from one client address. Wait for `Retry-After` seconds, or read /llms-full.txt once instead of polling.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "examples": [
                    42
                  ]
                }
              },
              "RateLimit": {
                "description": "The live window state: `r` requests left, `t` seconds until it resets.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "\"content\";r=0;t=42"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/profile": {
      "get": {
        "operationId": "getProfileV1",
        "summary": "Get the canonical facts about Denys Ishchenko (pinned to v1)",
        "description": "Role, employer, location, contact address, career history, skills, awards and verified profiles elsewhere — plus what this site is and is not a good source for. Every field is published on a page of the site; nothing is inferred. Where this and a third-party profile disagree, this is canonical.\n\nPinned to v1: this path answers with the v1 response shapes for as long as it exists, and a breaking change lands at /api/v2 instead. The unversioned path returns identical bytes but tracks whatever the current major is.",
        "tags": [
          "profile",
          "pinned"
        ],
        "responses": {
          "200": {
            "description": "The profile.",
            "headers": {
              "API-Version": {
                "description": "The response-shape version that produced this body.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "1.0.0"
                  ]
                }
              },
              "RateLimit-Policy": {
                "description": "The quota, as a Structured Fields list: policy name, `q` requests per `w` seconds.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "\"content\";q=600;w=60"
                  ]
                }
              },
              "RateLimit-Limit": {
                "description": "The same quota as a bare integer, for older clients.",
                "schema": {
                  "type": "integer",
                  "examples": [
                    600
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "title": "Profile",
                  "description": "The canonical facts about Denys Ishchenko. Every field is published on a page of this site; nothing here is inferred.",
                  "required": [
                    "name",
                    "jobTitle",
                    "employer",
                    "location",
                    "email",
                    "summary"
                  ],
                  "properties": {
                    "name": {
                      "type": "string",
                      "examples": [
                        "Denys Ishchenko"
                      ]
                    },
                    "headline": {
                      "type": "string",
                      "description": "How the site titles him.",
                      "examples": [
                        "Product Designer"
                      ]
                    },
                    "jobTitle": {
                      "type": "string",
                      "examples": [
                        "Senior User Experience Designer"
                      ]
                    },
                    "employer": {
                      "type": "string",
                      "examples": [
                        "PM-International"
                      ]
                    },
                    "location": {
                      "type": "object",
                      "required": [
                        "locality",
                        "countryCode"
                      ],
                      "properties": {
                        "locality": {
                          "type": "string",
                          "examples": [
                            "Luxembourg"
                          ]
                        },
                        "countryCode": {
                          "type": "string",
                          "description": "ISO 3166-1 alpha-2.",
                          "examples": [
                            "LU"
                          ]
                        }
                      }
                    },
                    "email": {
                      "type": "string",
                      "format": "email",
                      "description": "The only contact channel. There is no form and no phone."
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "summary": {
                      "type": "string",
                      "description": "One paragraph safe to quote verbatim."
                    },
                    "expertise": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Skills, each evidenced by a page on this site."
                    },
                    "awards": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "roles": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "title": "Role",
                        "description": "One position from the career history published on /about.",
                        "required": [
                          "title",
                          "organization",
                          "period",
                          "notes"
                        ],
                        "properties": {
                          "title": {
                            "type": "string",
                            "description": "Job title."
                          },
                          "organization": {
                            "type": "string",
                            "description": "Employer or client."
                          },
                          "period": {
                            "type": "string",
                            "description": "Free-text date range, as written on the page.",
                            "examples": [
                              "April 2023 – present"
                            ]
                          },
                          "notes": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "What the role covered, one bullet per line on the page."
                          }
                        }
                      },
                      "description": "Career history, most recent first."
                    },
                    "profiles": {
                      "type": "array",
                      "description": "Verified profiles elsewhere, and the resume.",
                      "items": {
                        "type": "object",
                        "required": [
                          "label",
                          "url"
                        ],
                        "properties": {
                          "label": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string",
                            "format": "uri"
                          }
                        }
                      }
                    },
                    "goodFits": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Questions this site can answer well."
                    },
                    "poorFits": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Questions it cannot. Answering these from this site produces something wrong."
                    },
                    "howToUse": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "How an agent should call this site."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Nothing is served at that path.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "This API is read-only. The `Allow` header names what the endpoint accepts.",
            "headers": {
              "Allow": {
                "description": "The methods this endpoint accepts.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "GET, HEAD, OPTIONS"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header refuses application/json, which is all this endpoint produces.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 600 requests in 60 seconds reached the origin from one client address. Wait for `Retry-After` seconds, or read /llms-full.txt once instead of polling.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "examples": [
                    42
                  ]
                }
              },
              "RateLimit": {
                "description": "The live window state: `r` requests left, `t` seconds until it resets.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "\"content\";r=0;t=42"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/markdown/{slug}": {
      "get": {
        "operationId": "getPageMarkdown",
        "summary": "Get one page as raw Markdown",
        "description": "The same body getPage returns, served as text/markdown rather than wrapped in JSON. Equivalent to requesting the page URL with `Accept: text/markdown`, or to fetching `/{slug}.md`. Not behind the API quota: ordinary page reads are served by this route.",
        "tags": [
          "pages"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Which page. This is the path without its leading slash; the homepage is `index`.",
            "schema": {
              "type": "string",
              "enum": [
                "index",
                "about",
                "playground",
                "fitline",
                "monroe",
                "help-center",
                "telegram-contest",
                "contact",
                "docs",
                "privacy"
              ]
            },
            "example": "about"
          }
        ],
        "responses": {
          "200": {
            "description": "The page as Markdown.",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No page has that slug. The body lists every page on the site, as Markdown.",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/markdown/{slug}": {
      "get": {
        "operationId": "getPageMarkdownV1",
        "summary": "Get one page as raw Markdown (pinned to v1)",
        "description": "The same body getPage returns, served as text/markdown rather than wrapped in JSON. Equivalent to requesting the page URL with `Accept: text/markdown`, or to fetching `/{slug}.md`. Not behind the API quota: ordinary page reads are served by this route.\n\nPinned to v1: this path answers with the v1 response shapes for as long as it exists, and a breaking change lands at /api/v2 instead. The unversioned path returns identical bytes but tracks whatever the current major is.",
        "tags": [
          "pages",
          "pinned"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Which page. This is the path without its leading slash; the homepage is `index`.",
            "schema": {
              "type": "string",
              "enum": [
                "index",
                "about",
                "playground",
                "fitline",
                "monroe",
                "help-center",
                "telegram-contest",
                "contact",
                "docs",
                "privacy"
              ]
            },
            "example": "about"
          }
        ],
        "responses": {
          "200": {
            "description": "The page as Markdown.",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No page has that slug. The body lists every page on the site, as Markdown.",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "getOpenApiSpec",
        "summary": "This OpenAPI description",
        "description": "The complete OpenAPI 3.1 description of every endpoint on this site, and the canonical URL for it. The same bytes are served at /openapi.yaml, for tooling that looks for that name, and at /api/openapi.json.",
        "tags": [
          "discovery"
        ],
        "responses": {
          "200": {
            "description": "The OpenAPI document.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "title": "OpenApiDocument",
                  "description": "An OpenAPI 3.1 document — this one. Its own shape is defined by the OpenAPI specification rather than restated here.",
                  "required": [
                    "openapi",
                    "info",
                    "paths"
                  ],
                  "properties": {
                    "openapi": {
                      "type": "string",
                      "examples": [
                        "3.1.1"
                      ]
                    },
                    "info": {
                      "type": "object",
                      "description": "Title, version, contact."
                    },
                    "servers": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "paths": {
                      "type": "object",
                      "description": "Every path this site serves."
                    },
                    "components": {
                      "type": "object",
                      "description": "The shared error responses."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "The description is not being served, which means it has moved. Every page of the site links to the current URL with `rel=\"service-desc\"`.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/openapi.json": {
      "get": {
        "operationId": "getOpenApiSpecUnderApi",
        "summary": "This OpenAPI description, under /api",
        "description": "Byte-identical to /openapi.json, served under /api because half of the tooling probes there first. The same bytes are also at /openapi.yaml. `Link: rel=\"canonical\"` points back at /openapi.json.",
        "tags": [
          "discovery"
        ],
        "responses": {
          "200": {
            "description": "The OpenAPI document.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "title": "OpenApiDocument",
                  "description": "An OpenAPI 3.1 document — this one. Its own shape is defined by the OpenAPI specification rather than restated here.",
                  "required": [
                    "openapi",
                    "info",
                    "paths"
                  ],
                  "properties": {
                    "openapi": {
                      "type": "string",
                      "examples": [
                        "3.1.1"
                      ]
                    },
                    "info": {
                      "type": "object",
                      "description": "Title, version, contact."
                    },
                    "servers": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "paths": {
                      "type": "object",
                      "description": "Every path this site serves."
                    },
                    "components": {
                      "type": "object",
                      "description": "The shared error responses."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "The description is not being served at this alias. /openapi.json is the canonical URL.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "summary": "Get the llms.txt site overview",
        "description": "The llmstxt.org v2 overview: what this site is, when it is worth consulting, when it is not, and a link to every page. About 7 KB.",
        "tags": [
          "files"
        ],
        "responses": {
          "200": {
            "description": "The llms.txt document.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "The file is not being served. These paths ship with every deployment, so this means the URL has moved rather than that the request was wrong — re-read /sitemap.xml or /llms.txt for the current ones.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/llms-full.txt": {
      "get": {
        "operationId": "getLlmsFullTxt",
        "summary": "Get the entire site in one response",
        "description": "Every page of the site concatenated as Markdown, about 18 KB or 4,400 tokens. This is the cheapest way to read the whole site: one fetch instead of 10.",
        "tags": [
          "files"
        ],
        "responses": {
          "200": {
            "description": "The whole site as Markdown.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "The file is not being served. These paths ship with every deployment, so this means the URL has moved rather than that the request was wrong — re-read /sitemap.xml or /llms.txt for the current ones.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/sitemap.xml": {
      "get": {
        "operationId": "getSitemap",
        "summary": "Get the XML sitemap",
        "description": "Every indexable URL with its last-modified date and priority, per sitemaps.org 0.9.",
        "tags": [
          "files"
        ],
        "responses": {
          "200": {
            "description": "The sitemap.",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "The file is not being served. These paths ship with every deployment, so this means the URL has moved rather than that the request was wrong — re-read /sitemap.xml or /llms.txt for the current ones.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/robots.txt": {
      "get": {
        "operationId": "getRobotsTxt",
        "summary": "Get the robots.txt policy",
        "description": "Crawling policy for the whole site. Everything is allowed, for every crawler named and for every one that is not, and the sitemap is named.",
        "tags": [
          "files"
        ],
        "responses": {
          "200": {
            "description": "The robots.txt file.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "The file is not being served. These paths ship with every deployment, so this means the URL has moved rather than that the request was wrong — re-read /sitemap.xml or /llms.txt for the current ones.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "title": "Error",
        "description": "The single error envelope used by every non-2xx response under /api. `code` is stable and machine-matchable; `hint` always names a concrete next call.",
        "required": [
          "error"
        ],
        "additionalProperties": false,
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "status",
              "code",
              "message",
              "hint",
              "documentation"
            ],
            "additionalProperties": false,
            "properties": {
              "status": {
                "type": "integer",
                "description": "The HTTP status code, repeated in the body.",
                "examples": [
                  404
                ]
              },
              "code": {
                "type": "string",
                "description": "Stable machine-readable identifier for the failure.",
                "enum": [
                  "not_found",
                  "page_not_found",
                  "not_acceptable",
                  "method_not_allowed",
                  "rate_limited"
                ]
              },
              "message": {
                "type": "string",
                "description": "One sentence naming what went wrong."
              },
              "hint": {
                "type": "string",
                "description": "What to do next, as a call that will succeed."
              },
              "documentation": {
                "type": "string",
                "format": "uri",
                "description": "Human-readable documentation for this API."
              },
              "allowed": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "On 405 only — the methods this endpoint accepts."
              },
              "produces": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "On 406 only — the media types this endpoint can send."
              },
              "received": {
                "type": "string",
                "description": "On 406 only — the Accept header that was refused."
              },
              "requestedSlug": {
                "type": "string",
                "description": "On 404 from /api/pages/{slug} — the slug that missed."
              },
              "availableSlugs": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "On 404 from /api/pages/{slug} — every valid slug."
              },
              "endpoints": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "On 404 from an unknown /api path — the real endpoints."
              },
              "versionedEndpoints": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "On 404 from an unknown /api path — the same endpoints at the pinned major."
              },
              "limit": {
                "type": "integer",
                "description": "On 429 only — requests allowed per window."
              },
              "window": {
                "type": "string",
                "description": "On 429 only — the window length, e.g. `60s`."
              },
              "retryAfter": {
                "type": "integer",
                "description": "On 429 only — seconds until the window resets."
              }
            }
          }
        }
      }
    }
  }
}
