{
  "openapi": "3.1.0",
  "info": {
    "title": "hehrmann.com content API",
    "version": "1.2.0",
    "summary": "Read-only HTTP surface of hehrmann.com, the site of Erik Hehrmann, fractional COO for creative agencies.",
    "description": "Every public page is available as HTML and as Markdown at the same URL through Accept-header negotiation (RFC 9110), or as a Markdown twin at <page>index.md, at <page>.md, or with ?mode=agent, each opening with title, description, canonical and last-updated frontmatter. The machine documents take .md as well (/api/openapi.json.md, /api/health.md, /.well-known/api-catalog.md): the same JSON inside a fenced block. Scoped llms.txt indexes: /developers/llms.txt, /services/llms.txt, /notes/llms.txt. Whole-site files (llms.txt, llms-full.txt, pricing.md, sitemap.xml), an MCP server at /mcp, and a health probe complete the surface. No authentication anywhere; nothing here writes.\n\nErrors: HTTP-level errors on /api/*, /mcp and /.well-known/* are RFC 9457 problem details (application/problem+json) with a stable `type` URI under https://hehrmann.com/developers/#errors. Inside /mcp, protocol errors are JSON-RPC 2.0 error objects.\n\nRate limits: /api/* and /mcp allow 100 requests per 60 seconds per client IP, counted by the edge instance serving the connection. Responses carry RateLimit-Policy and RateLimit (draft-ietf-httpapi-ratelimit-headers); a 429 adds Retry-After.\n\nVersioning and deprecation: paths are unversioned; additive changes ship without notice. A breaking change gets a new path (for example /api/v2/) and the old one keeps answering for at least 180 days with Deprecation (RFC 9745) and Sunset (RFC 8594) headers pointing at the replacement, announced at https://hehrmann.com/developers/ and in this description.",
    "contact": {
      "name": "Erik Hehrmann",
      "email": "erik@hehrmann.com",
      "url": "https://hehrmann.com/contact/"
    },
    "x-agent-guide": "https://hehrmann.com/llms.txt",
    "x-auth-model": "https://hehrmann.com/auth.md",
    "x-documentation": "https://hehrmann.com/developers/",
    "x-rate-limit": {
      "policy": "api",
      "limit": 100,
      "window": 60,
      "scope": "client IP, counted by the edge instance serving the connection; a 429 with Retry-After is authoritative",
      "paths": [
        "/api/*",
        "/mcp"
      ],
      "headers": [
        "RateLimit-Policy",
        "RateLimit",
        "Retry-After"
      ]
    },
    "x-deprecation-policy": {
      "notice": "P180D",
      "signals": [
        "Deprecation",
        "Sunset"
      ],
      "url": "https://hehrmann.com/developers/#versioning-and-deprecation"
    }
  },
  "externalDocs": {
    "description": "Developer guide: endpoints, errors, rate limits, versioning",
    "url": "https://hehrmann.com/developers/"
  },
  "servers": [
    {
      "url": "https://hehrmann.com"
    }
  ],
  "paths": {
    "/{page}/": {
      "get": {
        "operationId": "getPage",
        "summary": "A page, as HTML or Markdown",
        "description": "Any path listed in /sitemap.xml, including nested notes such as notes/timesheets. Send Accept: text/markdown for the Markdown representation; browsers get HTML. The site root (/) behaves the same way.",
        "parameters": [
          {
            "name": "page",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "examples": [
                "services",
                "about",
                "notes/timesheets",
                "developers"
              ]
            },
            "description": "Page path without leading or trailing slash."
          },
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "examples": [
                "text/markdown",
                "text/html"
              ]
            }
          },
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "agent"
              ]
            },
            "description": "mode=agent returns the Markdown twin regardless of the Accept header."
          }
        ],
        "responses": {
          "200": {
            "description": "The page in the negotiated representation. Carries Vary: Accept and an RFC 8288 Link header (api-catalog, service-doc, describedby, alternate).",
            "headers": {
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Link": {
                "$ref": "#/components/headers/Link"
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "$ref": "#/components/schemas/MarkdownDocument"
                }
              }
            }
          },
          "404": {
            "description": "No such page. A short Markdown recovery body with links to the sitemap and llms.txt, unless the client asked for text/html explicitly (browsers), which gets the HTML 404 page.",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "406": {
            "$ref": "#/components/responses/NotAcceptable"
          }
        }
      }
    },
    "/{page}/index.md": {
      "get": {
        "operationId": "getPageMarkdown",
        "summary": "The Markdown twin of a page",
        "parameters": [
          {
            "name": "page",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Markdown with frontmatter (title, description, canonical, last-updated)",
            "content": {
              "text/markdown": {
                "schema": {
                  "$ref": "#/components/schemas/MarkdownDocument"
                }
              }
            }
          },
          "404": {
            "description": "No such page. Markdown recovery body.",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/{page}.md": {
      "get": {
        "operationId": "getPageMarkdownSuffix",
        "summary": "The Markdown twin, append-.md form",
        "description": "Same document as /{page}/index.md. Works for nested pages too: /notes/timesheets.md.",
        "parameters": [
          {
            "name": "page",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "examples": [
                "services",
                "notes/timesheets"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Markdown with frontmatter; Link carries rel=canonical to the page",
            "content": {
              "text/markdown": {
                "schema": {
                  "$ref": "#/components/schemas/MarkdownDocument"
                }
              }
            }
          },
          "404": {
            "description": "No such page. Markdown recovery body.",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "summary": "Agent guide: who, when to use, canonical pages, machine access, as a link index",
        "responses": {
          "200": {
            "description": "Plain text (llmstxt.org)",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/llms-full.txt": {
      "get": {
        "operationId": "getLlmsFullTxt",
        "summary": "Every page in one plain-text file",
        "responses": {
          "200": {
            "description": "Plain text",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/developers/llms.txt": {
      "get": {
        "operationId": "getDevelopersLlmsTxt",
        "summary": "Scoped llms.txt for the machine surfaces",
        "responses": {
          "200": {
            "description": "Plain text (llmstxt.org)",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/services/llms.txt": {
      "get": {
        "operationId": "getServicesLlmsTxt",
        "summary": "Scoped llms.txt for the engagements and fees",
        "responses": {
          "200": {
            "description": "Plain text (llmstxt.org)",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/notes/llms.txt": {
      "get": {
        "operationId": "getNotesLlmsTxt",
        "summary": "Scoped llms.txt for the case studies",
        "responses": {
          "200": {
            "description": "Plain text (llmstxt.org)",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/pricing.md": {
      "get": {
        "operationId": "getPricing",
        "summary": "The seven engagements with fee, capacity and commitment, as Markdown",
        "description": "Same data as /services/ (the canonical page). USD. Opens with frontmatter.",
        "responses": {
          "200": {
            "description": "Markdown",
            "content": {
              "text/markdown": {
                "schema": {
                  "$ref": "#/components/schemas/MarkdownDocument"
                }
              }
            }
          }
        }
      }
    },
    "/pricing/": {
      "get": {
        "operationId": "pricingRedirect",
        "summary": "Redirects to /services/",
        "responses": {
          "301": {
            "description": "Moved permanently to /services/, the canonical pricing page.",
            "headers": {
              "Location": {
                "schema": {
                  "type": "string",
                  "const": "/services/"
                }
              }
            }
          }
        }
      }
    },
    "/sitemap.xml": {
      "get": {
        "operationId": "getSitemap",
        "summary": "Canonical URL list",
        "responses": {
          "200": {
            "description": "Sitemaps protocol XML",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "mcp",
        "summary": "MCP server (Streamable HTTP)",
        "description": "Model Context Protocol endpoint. Protocol versions 2026-07-28 (per-request _meta and MCP-Protocol-Version header, server/discover) and 2025-03-26 through 2025-11-25 (initialize handshake) are both served. Tools: list_pages (optional section), get_page (path), search_site (query, limit), contact_instructions (optional purpose). Resources: every page as text/markdown plus llms.txt and llms-full.txt. Stateless: no session id is issued. Rate limited (see info.x-rate-limit). Server card: /.well-known/mcp/server-card.json.",
        "parameters": [
          {
            "name": "MCP-Protocol-Version",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "examples": [
                "2026-07-28",
                "2025-11-25"
              ]
            }
          },
          {
            "name": "Accept",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "const": "application/json, text/event-stream"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcMessage"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response (a result, or a protocol-level JSON-RPC error such as an unknown method on a legacy request)",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "MCP-Protocol-Version": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "202": {
            "description": "Notification accepted; no body.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              }
            }
          },
          "400": {
            "description": "Malformed message, header mismatch, or unsupported protocol version.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown method on a 2026-07-28 request (JSON-RPC error -32601).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcErrorResponse"
                }
              }
            }
          },
          "413": {
            "description": "Body larger than 64 KiB (JSON-RPC error -32600).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "get": {
        "operationId": "mcpGet",
        "summary": "No server-initiated stream",
        "responses": {
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "health",
        "summary": "Liveness probe (RFC 9727 status relation)",
        "responses": {
          "200": {
            "description": "Healthy",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "description": "The asset layer did not answer",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          }
        }
      }
    },
    "/api/openapi.json": {
      "get": {
        "operationId": "openapi",
        "summary": "This document",
        "responses": {
          "200": {
            "description": "OpenAPI 3.1",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/openapi.json.md": {
      "get": {
        "operationId": "openapiMarkdown",
        "summary": "This document wrapped as Markdown",
        "description": "Every machine document answers at its path plus .md: frontmatter, heading, canonical URL, then the JSON in a fenced block. Also /api/health.md, /.well-known/api-catalog.md, /.well-known/ai-catalog.json.md, /.well-known/mcp/server-card.json.md.",
        "responses": {
          "200": {
            "description": "Markdown",
            "content": {
              "text/markdown": {
                "schema": {
                  "$ref": "#/components/schemas/MarkdownDocument"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/{path}": {
      "get": {
        "operationId": "apiUnknown",
        "summary": "Any other /api/ path",
        "parameters": [
          {
            "name": "path",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/.well-known/api-catalog": {
      "get": {
        "operationId": "apiCatalog",
        "summary": "RFC 9727 API catalog",
        "responses": {
          "200": {
            "description": "Linkset: the catalog's item links, then one context per API",
            "content": {
              "application/linkset+json": {
                "schema": {
                  "$ref": "#/components/schemas/Linkset"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/.well-known/ai-catalog.json": {
      "get": {
        "operationId": "aiCatalog",
        "summary": "ARD capability manifest (also at /.well-known/ard.json)",
        "responses": {
          "200": {
            "description": "ai-catalog 1.0 manifest",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/.well-known/agent-skills/index.json": {
      "get": {
        "operationId": "agentSkills",
        "summary": "Agent Skills discovery index (v0.2.0)",
        "responses": {
          "200": {
            "description": "Skills index",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/.well-known/mcp/server-card.json": {
      "get": {
        "operationId": "serverCard",
        "summary": "MCP server card with tools[] (also at /mcp/server-card)",
        "responses": {
          "200": {
            "description": "Server card",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/.well-known/{document}": {
      "get": {
        "operationId": "wellKnownUnknown",
        "summary": "Any other well-known path",
        "parameters": [
          {
            "name": "document",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. `type` is a stable URI under https://hehrmann.com/developers/#errors and is the field to branch on.",
        "required": [
          "type",
          "title",
          "status"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "enum": [
              "https://hehrmann.com/developers/#error-bad-request",
              "https://hehrmann.com/developers/#error-not-found",
              "https://hehrmann.com/developers/#error-method-not-allowed",
              "https://hehrmann.com/developers/#error-not-acceptable",
              "https://hehrmann.com/developers/#error-payload-too-large",
              "https://hehrmann.com/developers/#error-rate-limited",
              "https://hehrmann.com/developers/#error-service-unavailable"
            ]
          },
          "title": {
            "type": "string",
            "description": "Short, human-readable summary of the problem type"
          },
          "status": {
            "type": "integer",
            "minimum": 400,
            "maximum": 599
          },
          "detail": {
            "type": "string",
            "description": "What happened and where to look next"
          },
          "instance": {
            "type": "string",
            "description": "The request path"
          },
          "see": {
            "type": "string",
            "format": "uri",
            "description": "The document that lists what does exist"
          },
          "allow": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Accepted HTTP methods (405)"
          },
          "available": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Available media types (406)"
          }
        },
        "additionalProperties": true,
        "examples": [
          {
            "type": "https://hehrmann.com/developers/#error-not-found",
            "title": "Not Found",
            "status": 404,
            "detail": "No endpoint at /api/nope. The OpenAPI description at /api/openapi.json lists what exists; /developers/ explains it.",
            "instance": "/api/nope",
            "see": "https://hehrmann.com/api/openapi.json"
          }
        ]
      },
      "MarkdownDocument": {
        "type": "string",
        "description": "Markdown text that opens with a YAML frontmatter block carrying title, description, canonical and last-updated, followed by a top-level heading.",
        "examples": [
          "---\ntitle: \"Services\"\ndescription: \"Engagement menu for fractional COO work with creative agencies.\"\ncanonical: https://hehrmann.com/services/\nlast-updated: 2026-09-10\n---\n# Services\n"
        ]
      },
      "Linkset": {
        "type": "object",
        "required": [
          "linkset"
        ],
        "properties": {
          "linkset": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "anchor"
              ],
              "properties": {
                "anchor": {
                  "type": "string",
                  "format": "uri"
                },
                "item": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/LinkTarget"
                  }
                },
                "service-desc": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/LinkTarget"
                  }
                },
                "service-doc": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/LinkTarget"
                  }
                },
                "status": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/LinkTarget"
                  }
                }
              },
              "additionalProperties": true
            }
          }
        }
      },
      "LinkTarget": {
        "type": "object",
        "required": [
          "href"
        ],
        "properties": {
          "href": {
            "type": "string",
            "format": "uri"
          },
          "type": {
            "type": "string"
          }
        }
      },
      "JsonRpcMessage": {
        "type": "object",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              }
            ],
            "description": "Absent on notifications."
          },
          "method": {
            "type": "string",
            "examples": [
              "server/discover",
              "initialize",
              "tools/list",
              "tools/call",
              "resources/list",
              "resources/read",
              "ping"
            ]
          },
          "params": {
            "type": "object"
          }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "required": [
          "jsonrpc",
          "id"
        ],
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "result": {
            "type": "object"
          },
          "error": {
            "$ref": "#/components/schemas/JsonRpcError"
          }
        }
      },
      "JsonRpcErrorResponse": {
        "type": "object",
        "required": [
          "jsonrpc",
          "id",
          "error"
        ],
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "error": {
            "$ref": "#/components/schemas/JsonRpcError"
          }
        }
      },
      "JsonRpcError": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "integer",
            "description": "-32700 parse error, -32600 invalid request, -32601 method not found, -32602 invalid params, -32603 internal, -32002 resource not found, -32020 header mismatch, -32022 unsupported protocol version"
          },
          "message": {
            "type": "string"
          },
          "data": {
            "description": "Details such as the supported protocol versions or the valid tool names"
          }
        }
      },
      "Health": {
        "type": "object",
        "required": [
          "status",
          "service",
          "checks",
          "time"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "degraded"
            ]
          },
          "service": {
            "type": "string"
          },
          "checks": {
            "type": "object",
            "properties": {
              "assets": {
                "type": "integer",
                "description": "HTTP status the asset layer returned for /llms.txt"
              },
              "rateLimitBinding": {
                "type": "boolean",
                "description": "Whether the cross-instance rate-limit counter is wired (the in-memory window applies either way)"
              }
            }
          },
          "time": {
            "type": "string",
            "format": "date-time"
          },
          "links": {
            "type": "object",
            "properties": {
              "catalog": {
                "type": "string",
                "format": "uri"
              },
              "mcp": {
                "type": "string",
                "format": "uri"
              },
              "docs": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    },
    "responses": {
      "NotFound": {
        "description": "No document or endpoint at that path. `see` names the catalog that lists what exists.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "Wrong HTTP method. The Allow header and the `allow` member list the accepted ones.",
        "headers": {
          "Allow": {
            "$ref": "#/components/headers/Allow"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "NotAcceptable": {
        "description": "The Accept header ruled out both text/html and text/markdown. `available` lists them.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Request budget used up (100 per 60 s per client IP). Retry-After says when to try again.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          },
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      }
    },
    "headers": {
      "RateLimit-Policy": {
        "description": "Quota policy, draft-ietf-httpapi-ratelimit-headers: \"api\";q=100;w=60",
        "schema": {
          "type": "string",
          "examples": [
            "\"api\";q=100;w=60"
          ]
        }
      },
      "RateLimit": {
        "description": "Remaining quota r and seconds until reset t: \"api\";r=97;t=41",
        "schema": {
          "type": "string",
          "examples": [
            "\"api\";r=97;t=41"
          ]
        }
      },
      "Retry-After": {
        "description": "Seconds to wait before retrying (on 429)",
        "schema": {
          "type": "integer"
        }
      },
      "Allow": {
        "description": "Accepted methods (on 405)",
        "schema": {
          "type": "string",
          "examples": [
            "GET, HEAD, OPTIONS",
            "POST, OPTIONS"
          ]
        }
      },
      "Link": {
        "description": "RFC 8288 discovery links: api-catalog, service-doc (llms.txt), describedby (ai-catalog.json), alternate (the page's Markdown twin)",
        "schema": {
          "type": "string"
        }
      },
      "Vary": {
        "description": "Accept",
        "schema": {
          "type": "string",
          "const": "Accept"
        }
      }
    }
  }
}
