{
  "openapi": "3.1.0",
  "info": {
    "title": "The Notetakers API",
    "version": "1.0.0",
    "description": "Read-only, public API over The Notetakers reviews of AI notetakers. No sign up, API key or auth.\n\nVersioning: v1 is the current version, carried in the URL path (/api/v1). Breaking changes ship under a new path such as /api/v2. Errors use RFC 9457 problem details (application/problem+json).",
    "contact": {
      "email": "hello@thenotetakers.com"
    }
  },
  "servers": [
    {
      "url": "https://thenotetakers.com"
    }
  ],
  "security": [],
  "paths": {
    "/api/v1/posts": {
      "get": {
        "operationId": "listPosts",
        "summary": "List or search posts",
        "description": "Finds or lists published posts, newest updated first, with slug, title, description, URLs and updated date but no body. With q, returns only posts whose title, description or body contains q, case-insensitive. Use it to discover slugs, then getPost or getPostMarkdown for the full text.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Text to search for, up to 200 characters. Omit to list all posts.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of posts to return, 1 to 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching posts",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostList"
                }
              }
            }
          },
          "400": {
            "description": "q or limit is invalid",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/posts/{slug}": {
      "get": {
        "operationId": "getPost",
        "summary": "Get one post",
        "description": "Returns one post by slug as JSON with its full Markdown, the same document served at /{slug}.md. Use when you already have a slug from listPosts. To read every post at once, use getLlmsFullTxt.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Post slug from listPosts",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[a-z0-9-]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The post",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Post"
                }
              }
            }
          },
          "400": {
            "description": "The slug is longer than 200 characters",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No post has this slug",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api": {
      "get": {
        "operationId": "getApiIndex",
        "summary": "API index",
        "description": "Returns links to the API endpoints, this OpenAPI document, the MCP endpoint and the developer docs.",
        "responses": {
          "200": {
            "description": "Links to the API entry points",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string"
                    },
                    "links": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string",
                        "format": "uri"
                      }
                    }
                  },
                  "required": [
                    "name",
                    "version",
                    "links"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "summary": "Get llms.txt",
        "description": "Returns the site llms.txt index: what the site covers and every post with its Markdown URL. Use for a whole-site overview, not for finding one post; use listPosts for that.",
        "responses": {
          "200": {
            "description": "The llms.txt file",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/llms-full.txt": {
      "get": {
        "operationId": "getLlmsFullTxt",
        "summary": "Get llms-full.txt",
        "description": "Returns every post body as Markdown in one plain text file. Use for bulk reading of the whole site; for one post, use getPostMarkdown.",
        "responses": {
          "200": {
            "description": "The llms-full.txt file",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/{slug}.md": {
      "get": {
        "operationId": "getPostMarkdown",
        "summary": "Get a post as Markdown",
        "description": "Returns one post as Markdown with YAML frontmatter. Use when you already have a slug from listPosts and want the raw Markdown instead of JSON.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Post slug from listPosts",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[a-z0-9-]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The post as Markdown",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/sitemap.xml": {
      "get": {
        "operationId": "getSitemap",
        "summary": "Get the sitemap",
        "description": "Returns the XML sitemap of every page on the site.",
        "responses": {
          "200": {
            "description": "The sitemap",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/mcp": {
      "post": {
        "operationId": "callMcp",
        "summary": "Call the MCP server",
        "description": "Model Context Protocol endpoint over Streamable HTTP. Send one JSON-RPC 2.0 message per request. Read-only tools: search_posts finds posts and their slugs, get_post_markdown returns one post as Markdown, and get_llms_txt returns llms.txt or, with full set to true, llms-full.txt.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "jsonrpc": {
                    "type": "string",
                    "const": "2.0"
                  },
                  "id": {
                    "type": [
                      "string",
                      "integer"
                    ]
                  },
                  "method": {
                    "type": "string",
                    "description": "For example initialize, tools/list or tools/call"
                  },
                  "params": {
                    "type": "object"
                  }
                },
                "required": [
                  "jsonrpc",
                  "method"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC 2.0 response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jsonrpc": {
                      "type": "string",
                      "const": "2.0"
                    },
                    "id": {
                      "type": [
                        "string",
                        "integer"
                      ]
                    },
                    "result": {
                      "type": "object"
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "integer"
                        },
                        "message": {
                          "type": "string"
                        },
                        "data": {}
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "jsonrpc"
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Notification or response accepted, no body"
          },
          "405": {
            "description": "Only POST is supported",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "PostSummary": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "description": "Post slug, used in every post URL"
          },
          "title": {
            "type": "string",
            "description": "Post title"
          },
          "description": {
            "type": "string",
            "description": "One sentence summary of the post"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Canonical HTML URL"
          },
          "markdownUrl": {
            "type": "string",
            "format": "uri",
            "description": "Markdown version of the post"
          },
          "updated": {
            "type": "string",
            "format": "date",
            "description": "Last updated, YYYY-MM-DD"
          }
        },
        "required": [
          "slug",
          "title",
          "description",
          "url",
          "markdownUrl",
          "updated"
        ]
      },
      "Post": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "description": "Post slug, used in every post URL"
          },
          "title": {
            "type": "string",
            "description": "Post title"
          },
          "description": {
            "type": "string",
            "description": "One sentence summary of the post"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Canonical HTML URL"
          },
          "markdownUrl": {
            "type": "string",
            "format": "uri",
            "description": "Markdown version of the post"
          },
          "updated": {
            "type": "string",
            "format": "date",
            "description": "Last updated, YYYY-MM-DD"
          },
          "markdown": {
            "type": "string",
            "description": "The post as Markdown with YAML frontmatter"
          }
        },
        "required": [
          "slug",
          "title",
          "description",
          "url",
          "markdownUrl",
          "updated",
          "markdown"
        ]
      },
      "PostList": {
        "type": "object",
        "properties": {
          "posts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PostSummary"
            }
          }
        },
        "required": [
          "posts"
        ]
      },
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri-reference"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "instance": {
            "type": "string",
            "format": "uri-reference"
          }
        },
        "required": [
          "type",
          "title",
          "status"
        ]
      }
    }
  }
}