{
  "openapi": "3.1.1",
  "info": {
    "title": "Dhruv Suthar (dhrv.pw) public site API",
    "version": "1.0.0",
    "description": "Public read-only resources. No authentication is required. Unknown /api paths return 404 JSON with error.code, error.message, and error.hint. No write operations, MCP server, or SDK are offered."
  },
  "servers": [
    {
      "url": "https://dhrv.pw"
    }
  ],
  "externalDocs": {
    "description": "dhrv.pw developer resources",
    "url": "https://dhrv.pw/developers"
  },
  "security": [],
  "paths": {
    "/": {
      "get": {
        "operationId": "getHomepage",
        "summary": "Dhruv Suthar homepage",
        "description": "Use a listed media type in Accept. Quality values are supported. The homepage defaults to HTML and selects HTML on a tie.",
        "responses": {
          "200": {
            "description": "Public read-only resource.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "405": {
            "description": "Use GET or HEAD.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              },
              "Allow": {
                "schema": {
                  "type": "string",
                  "const": "GET, HEAD"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header excludes the available representations.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be processed. Retry later.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "head": {
        "operationId": "headHomepage",
        "summary": "Dhruv Suthar homepage response headers",
        "description": "Use a listed media type in Accept. Quality values are supported. The homepage defaults to HTML and selects HTML on a tie.",
        "responses": {
          "200": {
            "description": "Same headers as GET, without a response body.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "405": {
            "description": "Use GET or HEAD.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              },
              "Allow": {
                "schema": {
                  "type": "string",
                  "const": "GET, HEAD"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header excludes the available representations.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be processed. Retry later.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/api/site": {
      "get": {
        "operationId": "getSite",
        "summary": "Read the public homepage profile, content, and links",
        "description": "Use a listed media type in Accept. Quality values are supported. The homepage defaults to HTML and selects HTML on a tie.",
        "responses": {
          "200": {
            "description": "Public read-only resource.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Site"
                }
              }
            }
          },
          "405": {
            "description": "Use GET or HEAD.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              },
              "Allow": {
                "schema": {
                  "type": "string",
                  "const": "GET, HEAD"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header excludes the available representations.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be processed. Retry later.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "head": {
        "operationId": "headSite",
        "summary": "Read the public homepage profile, content, and links response headers",
        "description": "Use a listed media type in Accept. Quality values are supported. The homepage defaults to HTML and selects HTML on a tie.",
        "responses": {
          "200": {
            "description": "Same headers as GET, without a response body.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "405": {
            "description": "Use GET or HEAD.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              },
              "Allow": {
                "schema": {
                  "type": "string",
                  "const": "GET, HEAD"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header excludes the available representations.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be processed. Retry later.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/index.md": {
      "get": {
        "operationId": "getHomepageMarkdown",
        "summary": "Read the homepage as Markdown",
        "description": "Use a listed media type in Accept. Quality values are supported. The homepage defaults to HTML and selects HTML on a tie.",
        "responses": {
          "200": {
            "description": "Public read-only resource.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "405": {
            "description": "Use GET or HEAD.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              },
              "Allow": {
                "schema": {
                  "type": "string",
                  "const": "GET, HEAD"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header excludes the available representations.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be processed. Retry later.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "head": {
        "operationId": "headHomepageMarkdown",
        "summary": "Read the homepage as Markdown response headers",
        "description": "Use a listed media type in Accept. Quality values are supported. The homepage defaults to HTML and selects HTML on a tie.",
        "responses": {
          "200": {
            "description": "Same headers as GET, without a response body.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "405": {
            "description": "Use GET or HEAD.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              },
              "Allow": {
                "schema": {
                  "type": "string",
                  "const": "GET, HEAD"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header excludes the available representations.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be processed. Retry later.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getAgentIndex",
        "summary": "Discover agent and developer resources",
        "description": "Use a listed media type in Accept. Quality values are supported. The homepage defaults to HTML and selects HTML on a tie.",
        "responses": {
          "200": {
            "description": "Public read-only resource.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "405": {
            "description": "Use GET or HEAD.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              },
              "Allow": {
                "schema": {
                  "type": "string",
                  "const": "GET, HEAD"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header excludes the available representations.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be processed. Retry later.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "head": {
        "operationId": "headAgentIndex",
        "summary": "Discover agent and developer resources response headers",
        "description": "Use a listed media type in Accept. Quality values are supported. The homepage defaults to HTML and selects HTML on a tie.",
        "responses": {
          "200": {
            "description": "Same headers as GET, without a response body.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "405": {
            "description": "Use GET or HEAD.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              },
              "Allow": {
                "schema": {
                  "type": "string",
                  "const": "GET, HEAD"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header excludes the available representations.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be processed. Retry later.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "getOpenApi",
        "summary": "Read this OpenAPI specification",
        "description": "Use a listed media type in Accept. Quality values are supported. The homepage defaults to HTML and selects HTML on a tie.",
        "responses": {
          "200": {
            "description": "Public read-only resource.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "405": {
            "description": "Use GET or HEAD.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              },
              "Allow": {
                "schema": {
                  "type": "string",
                  "const": "GET, HEAD"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header excludes the available representations.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be processed. Retry later.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "head": {
        "operationId": "headOpenApi",
        "summary": "Read this OpenAPI specification response headers",
        "description": "Use a listed media type in Accept. Quality values are supported. The homepage defaults to HTML and selects HTML on a tie.",
        "responses": {
          "200": {
            "description": "Same headers as GET, without a response body.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "405": {
            "description": "Use GET or HEAD.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              },
              "Allow": {
                "schema": {
                  "type": "string",
                  "const": "GET, HEAD"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header excludes the available representations.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be processed. Retry later.",
            "headers": {
              "Vary": {
                "description": "Accept selects the representation.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Negotiated representations are not cached.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "code",
              "message",
              "hint"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "NOT_FOUND",
                  "METHOD_NOT_ALLOWED",
                  "NOT_ACCEPTABLE",
                  "INTERNAL_ERROR"
                ]
              },
              "message": {
                "type": "string"
              },
              "hint": {
                "type": "string"
              }
            }
          }
        }
      },
      "Site": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "url",
          "description",
          "content",
          "links"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "description": {
            "type": "string"
          },
          "content": {
            "type": "string",
            "minLength": 500
          },
          "links": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title",
                "url"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          }
        }
      }
    }
  }
}
