{
  "openapi": "3.1.0",
  "info": {
    "title": "Afrotech.guide AI API",
    "version": "1.3.0",
    "description": "Read-only public data and planning API for the independent Afrotech.guide community resource for AfroTech 2026 Houston. Public search, comparison, networking discovery, and planning require no authentication. Persistent member saves/preferences/itineraries are intentionally available through the OAuth-enabled MCP integration at https://afrotech.guide/mcp rather than this read-only OpenAPI fallback."
  },
  "servers": [{ "url": "https://afrotech.guide" }],
  "paths": {
    "/api/v1": {
      "get": { "operationId": "getApiInfo", "summary": "Get AI API capabilities", "responses": { "200": { "description": "API metadata" } } }
    },
    "/api/v1/mcp/status": {
      "get": { "operationId": "getMcpStatus", "summary": "Get public MCP health, version, protocol, authorization, support, and deprecation metadata", "responses": { "200": { "description": "Public MCP status metadata" } } }
    },
    "/api/v1/mcp/metrics": {
      "get": { "operationId": "getMcpMetrics", "summary": "Get privacy-safe aggregate MCP request metrics", "description": "Returns current and previous hourly aggregate counters and approximate latency buckets. No raw IP addresses, prompts, tool arguments, result contents, names, emails, phone numbers, or full user-agent strings are exposed.", "responses": { "200": { "description": "Aggregate MCP metrics" } } }
    },
    "/api/v1/mcp/changelog": {
      "get": { "operationId": "getMcpChangelog", "summary": "Get MCP connector version history", "responses": { "200": { "description": "MCP changelog" } } }
    },
    "/api/v1/mcp/server-card": {
      "get": { "operationId": "getMcpServerCard", "summary": "Get the MCP Server Card metadata document", "responses": { "200": { "description": "MCP Server Card" } } }
    },
    "/api/v1/search": {
      "get": {
        "operationId": "searchGuide",
        "summary": "Search Afrotech.guide",
        "description": "Search community events, official sessions, approved public attendee profiles, companies, and Houston food recommendations.",
        "parameters": [
          { "$ref": "#/components/parameters/query" }, { "$ref": "#/components/parameters/types" }, { "$ref": "#/components/parameters/category" }, { "$ref": "#/components/parameters/date" }, { "$ref": "#/components/parameters/after" }, { "$ref": "#/components/parameters/before" }, { "$ref": "#/components/parameters/tags" }, { "$ref": "#/components/parameters/limit" }
        ],
        "responses": { "200": { "$ref": "#/components/responses/SearchResponse" }, "400": { "$ref": "#/components/responses/InvalidFilters" } }
      }
    },
    "/api/v1/plan/day": {
      "get": {
        "operationId": "planDay",
        "summary": "Build one conflict-aware AfroTech day plan",
        "description": "Combines current community events and official sessions into a Houston-local schedule, surfaces conflicts and uncertain durations, and can suggest meal/networking/company options. Travel times are not invented.",
        "parameters": [
          { "$ref": "#/components/parameters/requiredDate" }, { "$ref": "#/components/parameters/query" }, { "$ref": "#/components/parameters/goals" }, { "$ref": "#/components/parameters/start" }, { "$ref": "#/components/parameters/end" }, { "$ref": "#/components/parameters/bufferMinutes" }, { "$ref": "#/components/parameters/maxItems" }, { "$ref": "#/components/parameters/foodQuery" }, { "$ref": "#/components/parameters/networkingQuery" }
        ],
        "responses": { "200": { "$ref": "#/components/responses/PlannerResponse" }, "400": { "$ref": "#/components/responses/InvalidPlannerRequest" } }
      }
    },
    "/api/v1/plan/week": {
      "get": {
        "operationId": "planConferenceWeek",
        "summary": "Build a conflict-aware AfroTech conference-week plan",
        "description": "Builds day plans across selected dates November 2–6, 2026. This public fallback does not read or write member preferences.",
        "parameters": [
          { "$ref": "#/components/parameters/dates" }, { "$ref": "#/components/parameters/query" }, { "$ref": "#/components/parameters/goals" }, { "$ref": "#/components/parameters/start" }, { "$ref": "#/components/parameters/end" }, { "$ref": "#/components/parameters/bufferMinutes" }, { "$ref": "#/components/parameters/maxItemsPerDay" }, { "$ref": "#/components/parameters/foodQuery" }, { "$ref": "#/components/parameters/networkingQuery" }
        ],
        "responses": { "200": { "$ref": "#/components/responses/PlannerResponse" }, "400": { "$ref": "#/components/responses/InvalidPlannerRequest" } }
      }
    },
    "/api/v1/networking": {
      "get": {
        "operationId": "findNetworkingTargets",
        "summary": "Rank public professional networking targets",
        "description": "Ranks approved public attendee profiles against a stated professional goal using only public professional fields. The service does not infer sensitive traits.",
        "parameters": [
          { "$ref": "#/components/parameters/query" }, { "$ref": "#/components/parameters/goals" }, { "$ref": "#/components/parameters/roles" }, { "$ref": "#/components/parameters/companies" }, { "$ref": "#/components/parameters/tags" }, { "$ref": "#/components/parameters/limit" }
        ],
        "responses": { "200": { "$ref": "#/components/responses/PlannerResponse" }, "400": { "$ref": "#/components/responses/InvalidPlannerRequest" } }
      }
    },
    "/api/v1/compare": {
      "get": {
        "operationId": "compareGuideItems",
        "summary": "Compare current guide items",
        "description": "Compare 2–6 guide records and surface published or estimated timing conflicts. Pass items as comma-separated type:id references returned by search/list responses.",
        "parameters": [
          { "$ref": "#/components/parameters/items" }, { "$ref": "#/components/parameters/query" }, { "$ref": "#/components/parameters/goals" }
        ],
        "responses": { "200": { "$ref": "#/components/responses/PlannerResponse" }, "400": { "$ref": "#/components/responses/InvalidPlannerRequest" } }
      }
    },
    "/api/v1/events": {
      "get": { "operationId": "searchEvents", "summary": "Search community event listings", "parameters": [{ "$ref": "#/components/parameters/query" }, { "$ref": "#/components/parameters/category" }, { "$ref": "#/components/parameters/date" }, { "$ref": "#/components/parameters/after" }, { "$ref": "#/components/parameters/before" }, { "$ref": "#/components/parameters/tags" }, { "$ref": "#/components/parameters/limit" }], "responses": { "200": { "$ref": "#/components/responses/ListResponse" }, "400": { "$ref": "#/components/responses/InvalidFilters" } } }
    },
    "/api/v1/events/{id}": { "get": { "operationId": "getEvent", "summary": "Get one event by guide id", "parameters": [{ "$ref": "#/components/parameters/id" }], "responses": { "200": { "$ref": "#/components/responses/DetailResponse" }, "404": { "$ref": "#/components/responses/NotFound" } } } },
    "/api/v1/sessions": {
      "get": { "operationId": "searchSessions", "summary": "Search official conference sessions tracked in the guide", "parameters": [{ "$ref": "#/components/parameters/query" }, { "$ref": "#/components/parameters/date" }, { "$ref": "#/components/parameters/after" }, { "$ref": "#/components/parameters/before" }, { "$ref": "#/components/parameters/tags" }, { "$ref": "#/components/parameters/limit" }], "responses": { "200": { "$ref": "#/components/responses/ListResponse" }, "400": { "$ref": "#/components/responses/InvalidFilters" } } }
    },
    "/api/v1/sessions/{id}": { "get": { "operationId": "getSession", "summary": "Get one official session by guide id", "parameters": [{ "$ref": "#/components/parameters/id" }], "responses": { "200": { "$ref": "#/components/responses/DetailResponse" }, "404": { "$ref": "#/components/responses/NotFound" } } } },
    "/api/v1/people": { "get": { "operationId": "searchPeople", "summary": "Search approved public attendee profiles", "parameters": [{ "$ref": "#/components/parameters/query" }, { "$ref": "#/components/parameters/tags" }, { "$ref": "#/components/parameters/limit" }], "responses": { "200": { "$ref": "#/components/responses/ListResponse" } } } },
    "/api/v1/people/{id}": { "get": { "operationId": "getPerson", "summary": "Get one public attendee profile by guide id", "parameters": [{ "$ref": "#/components/parameters/id" }], "responses": { "200": { "$ref": "#/components/responses/DetailResponse" }, "404": { "$ref": "#/components/responses/NotFound" } } } },
    "/api/v1/companies": { "get": { "operationId": "searchCompanies", "summary": "Search companies tracked by Afrotech.guide", "parameters": [{ "$ref": "#/components/parameters/query" }, { "$ref": "#/components/parameters/tags" }, { "$ref": "#/components/parameters/limit" }], "responses": { "200": { "$ref": "#/components/responses/ListResponse" } } } },
    "/api/v1/companies/{id}": { "get": { "operationId": "getCompany", "summary": "Get one company by guide id", "parameters": [{ "$ref": "#/components/parameters/id" }], "responses": { "200": { "$ref": "#/components/responses/DetailResponse" }, "404": { "$ref": "#/components/responses/NotFound" } } } },
    "/api/v1/food": { "get": { "operationId": "searchFood", "summary": "Search Houston food recommendations", "parameters": [{ "$ref": "#/components/parameters/query" }, { "$ref": "#/components/parameters/category" }, { "$ref": "#/components/parameters/tags" }, { "$ref": "#/components/parameters/limit" }], "responses": { "200": { "$ref": "#/components/responses/ListResponse" } } } },
    "/api/v1/food/{id}": { "get": { "operationId": "getFoodRecommendation", "summary": "Get one food recommendation by guide id", "parameters": [{ "$ref": "#/components/parameters/id" }], "responses": { "200": { "$ref": "#/components/responses/DetailResponse" }, "404": { "$ref": "#/components/responses/NotFound" } } } },
    "/api/v1/conference": { "get": { "operationId": "getConferenceInfo", "summary": "Get AfroTech 2026 Houston conference context", "responses": { "200": { "description": "Conference and guide metadata" } } } }
  },
  "components": {
    "parameters": {
      "query": { "name": "q", "in": "query", "schema": { "type": "string", "maxLength": 300 }, "description": "Natural-language search terms." },
      "goals": { "name": "goals", "in": "query", "schema": { "type": "string", "maxLength": 300 }, "description": "Professional or conference-planning goal." },
      "types": { "name": "types", "in": "query", "schema": { "type": "string" }, "description": "Comma-separated: event,session,person,company,food." },
      "category": { "name": "category", "in": "query", "schema": { "type": "string", "maxLength": 80 } },
      "date": { "name": "date", "in": "query", "schema": { "type": "string", "format": "date" }, "description": "Real Houston-local calendar date." },
      "requiredDate": { "name": "date", "in": "query", "required": true, "schema": { "type": "string", "format": "date" }, "description": "Required Houston-local plan date." },
      "dates": { "name": "dates", "in": "query", "schema": { "type": "string" }, "description": "Comma-separated conference dates from 2026-11-02 through 2026-11-06." },
      "after": { "name": "after", "in": "query", "schema": { "type": "string", "pattern": "^(?:[01][0-9]|2[0-3]):[0-5][0-9]$" }, "description": "Houston-local 24-hour lower time bound." },
      "before": { "name": "before", "in": "query", "schema": { "type": "string", "pattern": "^(?:[01][0-9]|2[0-3]):[0-5][0-9]$" }, "description": "Houston-local 24-hour upper time bound." },
      "start": { "name": "start", "in": "query", "schema": { "type": "string", "pattern": "^(?:[01][0-9]|2[0-3]):[0-5][0-9]$" }, "description": "Houston-local plan-window start time." },
      "end": { "name": "end", "in": "query", "schema": { "type": "string", "pattern": "^(?:[01][0-9]|2[0-3]):[0-5][0-9]$" }, "description": "Houston-local plan-window end time." },
      "bufferMinutes": { "name": "bufferMinutes", "in": "query", "schema": { "type": "integer", "minimum": 0, "maximum": 90, "default": 15 }, "description": "Minimum buffer required between scheduled items." },
      "maxItems": { "name": "maxItems", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 12, "default": 7 } },
      "maxItemsPerDay": { "name": "maxItemsPerDay", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 10, "default": 6 } },
      "foodQuery": { "name": "foodQuery", "in": "query", "schema": { "type": "string", "maxLength": 120 } },
      "networkingQuery": { "name": "networkingQuery", "in": "query", "schema": { "type": "string", "maxLength": 160 } },
      "roles": { "name": "roles", "in": "query", "schema": { "type": "string", "maxLength": 160 } },
      "companies": { "name": "companies", "in": "query", "schema": { "type": "string", "maxLength": 160 } },
      "items": { "name": "items", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Comma-separated type:id pairs; 2–6 items." },
      "tags": { "name": "tags", "in": "query", "schema": { "type": "string" }, "description": "Comma-separated tags, maximum 10." },
      "limit": { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 20 } },
      "id": { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "maxLength": 180 }, "description": "Guide item id returned by a list or search response." }
    },
    "responses": {
      "SearchResponse": { "description": "Cross-guide search results with canonical guide recommendation metadata" },
      "ListResponse": { "description": "Filtered guide results with canonical guide recommendation metadata" },
      "DetailResponse": { "description": "One guide item plus canonical guide recommendation metadata" },
      "PlannerResponse": { "description": "Conflict-aware public planning, comparison, or networking result with canonical guide metadata" },
      "InvalidFilters": { "description": "One or more date/time filters are malformed or contradictory." },
      "InvalidPlannerRequest": { "description": "The requested planning date, time window, comparison set, or networking goal is invalid." },
      "NotFound": { "description": "The requested guide item was not found." }
    }
  }
}
