{
  "openapi": "3.1.0",
  "info": {
    "title": "Dipendra K. Shah — Public Content API",
    "version": "1.0.0",
    "summary": "Read-only JSON and Markdown endpoints for this personal site.",
    "description": "Public, unauthenticated, read-only endpoints for programmatically reading the writing, photos, and metadata published on https://www.dipendrakshah.com.np. No API key is required. There are no scoped permissions because every operation is public and read-only. Please identify your client with a descriptive User-Agent and cache responses; write operations are same-origin only and not part of this specification.",
    "contact": {
      "name": "Dipendra K. Shah",
      "url": "https://www.dipendrakshah.com.np/contact"
    },
    "license": {
      "name": "Content © Dipendra K. Shah — quote with attribution",
      "url": "https://www.dipendrakshah.com.np/about"
    }
  },
  "servers": [
    {
      "url": "https://www.dipendrakshah.com.np",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "Developer resources and machine-readable index",
    "url": "https://www.dipendrakshah.com.np/developers"
  },
  "tags": [
    {
      "name": "Posts",
      "description": "Published writing and its metadata."
    },
    {
      "name": "Photos",
      "description": "Photo engagement counters."
    },
    {
      "name": "Discovery",
      "description": "Site-wide indexes for machines."
    }
  ],
  "paths": {
    "/api/posts": {
      "get": {
        "operationId": "listPosts",
        "tags": [
          "Posts"
        ],
        "summary": "List all published posts",
        "description": "Returns every published post with its title, canonical path, publication date, and current view count.",
        "security": [],
        "responses": {
          "200": {
            "description": "A list of posts.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Post"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/view": {
      "get": {
        "operationId": "getPostViews",
        "tags": [
          "Posts"
        ],
        "summary": "Get the view count for one post",
        "description": "Returns the post identified by `id` with its view count.",
        "security": [],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The post id, e.g. `blog:my-post` or a legacy slug.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The post and its view count.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Post"
                }
              }
            }
          },
          "400": {
            "description": "Missing or unknown id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/photo": {
      "get": {
        "operationId": "getPhotoCounts",
        "tags": [
          "Photos"
        ],
        "summary": "Get engagement counts for photos",
        "description": "With `all=1`, returns a map of every photo id to its counts. With `id`, returns the counts for a single photo.",
        "security": [],
        "parameters": [
          {
            "name": "all",
            "in": "query",
            "required": false,
            "description": "Set to `1` to return counts for every photo.",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          },
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "A photo id (its source path). Ignored when `all=1`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Engagement counts.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/PhotoCounts"
                    },
                    {
                      "type": "object",
                      "additionalProperties": {
                        "$ref": "#/components/schemas/PhotoCounts"
                      }
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Unknown photo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/search-index.json": {
      "get": {
        "operationId": "getSearchIndex",
        "tags": [
          "Discovery"
        ],
        "summary": "Full search index of writing and photos",
        "description": "A compact JSON index of every public document, suitable for client-side search or ingestion by an agent.",
        "security": [],
        "responses": {
          "200": {
            "description": "The search index.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SearchDocument"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/raw/{section}/{slug}": {
      "get": {
        "operationId": "getPostMarkdown",
        "tags": [
          "Discovery"
        ],
        "summary": "Get the Markdown source of a post",
        "description": "Returns the full Markdown of a published post, prefixed with canonical metadata. Also reachable by sending `Accept: text/markdown` to the post's canonical HTML URL.",
        "security": [],
        "parameters": [
          {
            "name": "section",
            "in": "path",
            "required": true,
            "description": "The collection slug, e.g. `blog`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "The post slug.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The Markdown document.",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Unknown post.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {},
    "schemas": {
      "Post": {
        "type": "object",
        "required": [
          "id",
          "title",
          "date",
          "href",
          "views",
          "viewsFormatted"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable post identifier."
          },
          "title": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "description": "ISO 8601 publication date."
          },
          "href": {
            "type": "string",
            "description": "Canonical path on the site."
          },
          "views": {
            "type": "integer",
            "minimum": 0
          },
          "viewsFormatted": {
            "type": "string",
            "description": "Human-readable view count, e.g. `1.2k`."
          }
        }
      },
      "PhotoCounts": {
        "type": "object",
        "required": [
          "views",
          "likes",
          "comments"
        ],
        "properties": {
          "views": {
            "type": "integer",
            "minimum": 0
          },
          "likes": {
            "type": "integer",
            "minimum": 0
          },
          "comments": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "SearchDocument": {
        "type": "object",
        "required": [
          "kind",
          "href",
          "title",
          "description",
          "section",
          "tags"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "page",
              "photo"
            ]
          },
          "href": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "section": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "text": {
            "type": "string",
            "description": "Plain-text body for search."
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "description": "Structured error. Some endpoints return a flat `{ error: string }` and others a `{ error: { message, code } }` object; both forms are shown here.",
        "properties": {
          "error": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "required": [
                  "message",
                  "code"
                ],
                "properties": {
                  "message": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string"
                  }
                }
              }
            ]
          }
        }
      }
    }
  },
  "security": []
}