{
  "openapi": "3.1.0",
  "info": {
    "title": "The Woof Back — public content API",
    "version": "1.0.0",
    "description": "Read-only access to this brand’s already-public published content: articles, facts, feeds, and an MCP endpoint. No authentication. Errors use RFC 9457 problem+json. Rate limits are advertised via RateLimit-* response headers; back off on 429 using Retry-After."
  },
  "servers": [
    {
      "url": "https://thewoofback.com",
      "description": "Production. The version is carried in info.version."
    }
  ],
  "x-api-versioning": {
    "current": "1.0.0",
    "scheme": "semver",
    "policy": "Backward-compatible additive changes only within a major version. Breaking changes ship under a new major; the prior version is marked with Deprecation and Sunset headers for at least 90 days.",
    "deprecationHeaders": [
      "Deprecation",
      "Sunset"
    ]
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. Every error response uses this shape.",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "Problem type identifier."
          },
          "title": {
            "type": "string",
            "description": "Short, human-readable summary."
          },
          "status": {
            "type": "integer",
            "description": "HTTP status code."
          },
          "detail": {
            "type": "string",
            "description": "Explanation specific to this occurrence."
          },
          "instance": {
            "type": "string",
            "description": "URI of the specific occurrence."
          }
        },
        "required": [
          "title",
          "status"
        ]
      },
      "Fact": {
        "type": "object",
        "description": "A verifiable claim with its named publisher and date.",
        "properties": {
          "claim": {
            "type": "string"
          },
          "value": {
            "type": "string"
          },
          "sourceUrl": {
            "type": "string",
            "format": "uri"
          },
          "sourcePublisher": {
            "type": "string"
          },
          "sourceDate": {
            "type": "string",
            "description": "ISO date of the source."
          }
        },
        "required": [
          "claim",
          "value"
        ]
      },
      "FactsResponse": {
        "type": "object",
        "properties": {
          "brand": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "url": {
                "type": "string",
                "format": "uri"
              }
            }
          },
          "facts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Fact"
            }
          }
        },
        "required": [
          "facts"
        ]
      },
      "FaqPage": {
        "type": "object",
        "description": "schema.org FAQPage (JSON-LD).",
        "properties": {
          "@context": {
            "type": "string"
          },
          "@type": {
            "type": "string"
          },
          "mainEntity": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "@type": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "acceptedAnswer": {
                  "type": "object",
                  "properties": {
                    "@type": {
                      "type": "string"
                    },
                    "text": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "LlmsIndex": {
        "type": "object",
        "properties": {
          "brand": {
            "type": "object"
          },
          "articles": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "JsonRpcRequest": {
        "type": "object",
        "properties": {
          "jsonrpc": {
            "type": "string",
            "enum": [
              "2.0"
            ]
          },
          "id": {
            "type": [
              "string",
              "number"
            ]
          },
          "method": {
            "type": "string",
            "description": "tools/list or tools/call"
          },
          "params": {
            "type": "object"
          }
        },
        "required": [
          "jsonrpc",
          "method"
        ]
      },
      "JsonRpcResponse": {
        "type": "object",
        "properties": {
          "jsonrpc": {
            "type": "string",
            "enum": [
              "2.0"
            ]
          },
          "id": {
            "type": [
              "string",
              "number"
            ]
          },
          "result": {
            "type": "object"
          },
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "integer"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "headers": {
      "RateLimitLimit": {
        "description": "Requests permitted in the current window.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitRemaining": {
        "description": "Requests remaining in the current window.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitReset": {
        "description": "Seconds until the window resets.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "Error": {
        "description": "Error (typed problem+json).",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found (typed problem+json).",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests — back off using Retry-After.",
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before retrying.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      }
    }
  },
  "paths": {
    "/{slug}": {
      "get": {
        "operationId": "getArticle",
        "summary": "Fetch one published article. Send Accept: text/markdown for the markdown body, or Accept: text/html for the page.",
        "description": "Fetch one published article. Send Accept: text/markdown for the markdown body, or Accept: text/html for the page.",
        "responses": {
          "200": {
            "description": "Success. RateLimit-* headers advertise the self-throttling budget.",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "The article slug (see /sitemap.xml for the full list).",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/qa.json": {
      "get": {
        "operationId": "getQa",
        "summary": "Every answer-first block and FAQ as a schema.org FAQPage (JSON-LD).",
        "description": "Every answer-first block and FAQ as a schema.org FAQPage (JSON-LD).",
        "responses": {
          "200": {
            "description": "Success. RateLimit-* headers advertise the self-throttling budget.",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/ld+json": {
                "schema": {
                  "$ref": "#/components/schemas/FaqPage"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/facts.json": {
      "get": {
        "operationId": "getFacts",
        "summary": "The brand’s verifiable, sourced-and-dated facts.",
        "description": "The brand’s verifiable, sourced-and-dated facts.",
        "responses": {
          "200": {
            "description": "Success. RateLimit-* headers advertise the self-throttling budget.",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FactsResponse"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/llms.json": {
      "get": {
        "operationId": "getLlmsJson",
        "summary": "Structured index of the brand and its published content for LLMs.",
        "description": "Structured index of the brand and its published content for LLMs.",
        "responses": {
          "200": {
            "description": "Success. RateLimit-* headers advertise the self-throttling budget.",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LlmsIndex"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "summary": "Plain-text overview: what the site is and when to use it.",
        "description": "Plain-text overview: what the site is and when to use it.",
        "responses": {
          "200": {
            "description": "Success. RateLimit-* headers advertise the self-throttling budget.",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/agents.txt": {
      "get": {
        "operationId": "getAgentsTxt",
        "summary": "Agent guidance: fact base, MCP endpoint and citation policy.",
        "description": "Agent guidance: fact base, MCP endpoint and citation policy.",
        "responses": {
          "200": {
            "description": "Success. RateLimit-* headers advertise the self-throttling budget.",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/feed.xml": {
      "get": {
        "operationId": "getRssFeed",
        "summary": "RSS feed of published articles.",
        "description": "RSS feed of published articles.",
        "responses": {
          "200": {
            "description": "Success. RateLimit-* headers advertise the self-throttling budget.",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/rss+xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/atom.xml": {
      "get": {
        "operationId": "getAtomFeed",
        "summary": "Atom feed of published articles.",
        "description": "Atom feed of published articles.",
        "responses": {
          "200": {
            "description": "Success. RateLimit-* headers advertise the self-throttling budget.",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/atom+xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/sitemap.xml": {
      "get": {
        "operationId": "getSitemap",
        "summary": "Every published URL.",
        "description": "Every published URL.",
        "responses": {
          "200": {
            "description": "Success. RateLimit-* headers advertise the self-throttling budget.",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "callMcp",
        "summary": "Model Context Protocol server (JSON-RPC 2.0) exposing read-only content tools: list_articles, get_facts, search_content, get_article, list_topics.",
        "description": "Model Context Protocol server (JSON-RPC 2.0) exposing read-only content tools: list_articles, get_facts, search_content, get_article, list_topics.",
        "responses": {
          "200": {
            "description": "Success. RateLimit-* headers advertise the self-throttling budget.",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "requestBody": {
          "required": true,
          "description": "JSON-RPC 2.0 request. method is one of tools/list, tools/call.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcRequest"
              }
            }
          }
        }
      }
    }
  }
}