{
  "openapi": "3.1.0",
  "info": {
    "title": "Dhruvil Mistry Portfolio & AI Systems API",
    "description": "Production-grade REST and NLWeb API for Dhruvil Mistry - AI Engineer. Supports NLWeb natural language queries, conversational chat, paginated projects directory, async job tasks, and Model Context Protocol (MCP).",
    "version": "1.0.0",
    "x-deprecation-policy": "https://bydhruvil.in/deprecation",
    "contact": {
      "name": "Dhruvil Mistry",
      "email": "dhruvilmistry16@gmail.com",
      "url": "https://bydhruvil.in"
    }
  },
  "servers": [
    {
      "url": "https://bydhruvil.in",
      "description": "Production Server"
    },
    {
      "url": "https://bydhruvil.in/v1",
      "description": "v1 Versioned API Root"
    }
  ],
  "paths": {
    "/ask": {
      "get": {
        "summary": "NLWeb Natural Language Query",
        "description": "Ask grounded questions about Dhruvil Mistry, his projects, technical stack, or hiring availability using standard NLWeb query parameters.",
        "operationId": "askGet",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "The question or query string",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "stream",
            "in": "query",
            "required": false,
            "description": "Whether to stream SSE responses",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Unique key to ensure idempotent request execution",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful natural language response",
            "headers": {
              "RateLimit-Limit": {
                "schema": { "type": "integer" },
                "description": "Maximum requests allowed per minute"
              },
              "RateLimit-Remaining": {
                "schema": { "type": "integer" },
                "description": "Remaining requests in the current window"
              },
              "RateLimit-Reset": {
                "schema": { "type": "integer" },
                "description": "Seconds until the window resets"
              },
              "Idempotency-Key": {
                "schema": { "type": "string" }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AskResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request / Missing Query",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate Limit Exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "NLWeb Natural Language Query (POST)",
        "description": "Submit a question or conversational message to the NLWeb query endpoint.",
        "operationId": "askPost",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Unique idempotency key",
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AskRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "headers": {
              "RateLimit-Limit": { "schema": { "type": "integer" } },
              "RateLimit-Remaining": { "schema": { "type": "integer" } },
              "RateLimit-Reset": { "schema": { "type": "integer" } },
              "Idempotency-Key": { "schema": { "type": "string" } }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AskResponse"
                }
              },
              "text/event-stream": {
                "schema": { "type": "string" }
              }
            }
          },
          "400": {
            "description": "Invalid Request",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "429": {
            "description": "Rate Limited",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        }
      }
    },
    "/v1/ask": {
      "post": {
        "summary": "v1 NLWeb Natural Language Query",
        "description": "Version 1 API endpoint for natural language queries.",
        "operationId": "v1AskPost",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/AskRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/AskResponse" }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        }
      }
    },
    "/v1/projects": {
      "get": {
        "summary": "List Projects (Paginated)",
        "description": "Retrieve Dhruvil Mistry's portfolio projects with standard pagination parameters (limit, offset, cursor).",
        "operationId": "listProjects",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Number of projects to return (1-50)",
            "schema": { "type": "integer", "default": 10, "minimum": 1, "maximum": 50 }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Offset from beginning",
            "schema": { "type": "integer", "default": 0, "minimum": 0 }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor",
            "schema": { "type": "string" }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Filter by category ('ai', 'voice', 'healthcare', 'tools')",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated projects response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedProjectsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        }
      }
    },
    "/v1/tasks": {
      "post": {
        "summary": "Create Async Evaluation Task",
        "description": "Initiates an asynchronous evaluation or analytical task adhering to standard REST async-job pattern.",
        "operationId": "createTask",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "task_type": { "type": "string", "example": "portfolio_evaluation" },
                  "input": { "type": "object" }
                },
                "required": ["task_type"]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Task Accepted for Processing",
            "headers": {
              "Location": {
                "schema": { "type": "string" },
                "description": "URI to poll for task completion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateTaskResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        }
      }
    },
    "/v1/tasks/{taskId}": {
      "get": {
        "summary": "Poll Async Task Status",
        "description": "Poll the status and output of an asynchronous task.",
        "operationId": "getTaskStatus",
        "parameters": [
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Task status and result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskStatusResponse"
                }
              }
            }
          },
          "404": {
            "description": "Task Not Found",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "summary": "Model Context Protocol JSON-RPC Endpoint",
        "description": "Standard MCP 2024-11-05 JSON-RPC 2.0 handshake and tool execution endpoint.",
        "operationId": "mcpPost",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "jsonrpc": { "type": "string", "example": "2.0" },
                  "method": { "type": "string", "example": "initialize" },
                  "id": { "type": "integer", "example": 1 },
                  "params": { "type": "object" }
                },
                "required": ["jsonrpc", "method"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "MCP JSON-RPC response",
            "content": {
              "application/json": {
                "schema": { "type": "object" }
              }
            }
          },
          "400": {
            "description": "Invalid JSON-RPC payload",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AskRequest": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "description": "Question to ask"
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "role": { "type": "string" },
                "content": { "type": "string" }
              }
            }
          },
          "stream": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "AskResponse": {
        "type": "object",
        "properties": {
          "answer": {
            "type": "string",
            "description": "Answer generated from Dhruvil's knowledge base"
          },
          "sources": {
            "type": "array",
            "items": { "type": "string" }
          },
          "agent": {
            "type": "string",
            "example": "Dhruvil AI"
          },
          "confidence": {
            "type": "number",
            "example": 1.0
          },
          "timestamp": {
            "type": "string"
          }
        },
        "required": ["answer"]
      },
      "ProjectItem": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "tagline": { "type": "string" },
          "description": { "type": "string" },
          "category": { "type": "string" },
          "tech_stack": {
            "type": "array",
            "items": { "type": "string" }
          },
          "url": { "type": "string" }
        },
        "required": ["id", "name", "description"]
      },
      "PaginationMeta": {
        "type": "object",
        "properties": {
          "total": { "type": "integer" },
          "limit": { "type": "integer" },
          "offset": { "type": "integer" },
          "has_more": { "type": "boolean" },
          "next_offset": { "type": ["integer", "null"] },
          "next_cursor": { "type": ["string", "null"] }
        },
        "required": ["total", "limit", "offset", "has_more"]
      },
      "PaginatedProjectsResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/ProjectItem" }
          },
          "pagination": { "$ref": "#/components/schemas/PaginationMeta" }
        },
        "required": ["data", "pagination"]
      },
      "CreateTaskResponse": {
        "type": "object",
        "properties": {
          "task_id": { "type": "string" },
          "status": { "type": "string", "enum": ["queued", "processing"] },
          "poll_url": { "type": "string" },
          "created_at": { "type": "string" }
        },
        "required": ["task_id", "status", "poll_url"]
      },
      "TaskStatusResponse": {
        "type": "object",
        "properties": {
          "task_id": { "type": "string" },
          "status": { "type": "string", "enum": ["pending", "processing", "completed", "failed"] },
          "progress": { "type": "integer", "minimum": 0, "maximum": 100 },
          "result": { "type": "object" },
          "updated_at": { "type": "string" }
        },
        "required": ["task_id", "status", "progress"]
      },
      "ErrorDetail": {
        "type": "object",
        "properties": {
          "code": { "type": "string" },
          "message": { "type": "string" },
          "status": { "type": "integer" },
          "timestamp": { "type": "string" },
          "documentation_url": { "type": "string" }
        },
        "required": ["code", "message", "status"]
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": { "$ref": "#/components/schemas/ErrorDetail" }
        },
        "required": ["error"]
      }
    },
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Free self-serve access: all public endpoints are open without authentication requirements. Optional bearer token."
      }
    }
  }
}
