{
  "openapi": "3.1.0",
  "info": {
    "title": "Encoders Research API",
    "version": "1.0.0",
    "description": "Deep research over real, outcome-labeled field-service resolutions. Each successful research run uses one prepaid credit ($0.40-2.00/run; packs at https://www.encoders.ai/api/). An MCP endpoint is also available at POST /research/mcp (Streamable HTTP, same auth).",
    "contact": {"email": "contact@encoders.ai", "url": "https://www.encoders.ai/api/"}
  },
  "servers": [{"url": "https://api.bloomtechsupport.com/api/v1"}],
  "security": [{"ApiKeyAuth": []}],
  "paths": {
    "/research/corpus": {
      "post": {
        "operationId": "researchCorpus",
        "summary": "Run deep research synchronously (20-80s; prefer the async jobs endpoint)",
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ResearchRequest"}}}},
        "responses": {
          "200": {"description": "Evidence-grounded research brief", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ResearchBrief"}}}},
          "402": {"description": "Out of credits"},
          "429": {"description": "Rate limited (Retry-After header set)"}
        }
      }
    },
    "/research/corpus/jobs": {
      "post": {
        "operationId": "startResearchJob",
        "summary": "Start an async research job (recommended)",
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ResearchRequest"}}}},
        "responses": {
          "202": {"description": "Job accepted", "content": {"application/json": {"schema": {
            "type": "object",
            "properties": {"job_id": {"type": "string"}, "status": {"type": "string"}, "eta_seconds": {"type": "integer"}, "poll": {"type": "string"}}
          }}}},
          "402": {"description": "Out of credits"},
          "429": {"description": "Rate limited"}
        }
      }
    },
    "/research/corpus/jobs/{job_id}": {
      "get": {
        "operationId": "getResearchJob",
        "summary": "Poll an async research job",
        "parameters": [{"name": "job_id", "in": "path", "required": true, "schema": {"type": "string"}}],
        "responses": {
          "200": {"description": "Job status; brief present when status=done", "content": {"application/json": {"schema": {
            "type": "object",
            "properties": {"job_id": {"type": "string"}, "status": {"type": "string", "enum": ["running", "done", "error"]}, "brief": {"$ref": "#/components/schemas/ResearchBrief"}, "error": {"type": "string"}}
          }}}},
          "404": {"description": "Unknown or expired job (jobs expire after 1 hour)"}
        }
      }
    },
    "/research/credits": {
      "get": {
        "operationId": "getCredits",
        "summary": "Remaining prepaid credits for this key",
        "responses": {"200": {"description": "Balance", "content": {"application/json": {"schema": {
          "type": "object",
          "properties": {"credits_remaining": {"type": ["integer", "null"]}, "buy_more": {"type": "string"}}
        }}}}}
      }
    }
  },
  "components": {
    "securitySchemes": {"ApiKeyAuth": {"type": "apiKey", "in": "header", "name": "X-API-Key"}},
    "schemas": {
      "ResearchRequest": {
        "type": "object",
        "required": ["problem"],
        "properties": {"problem": {"type": "string", "description": "Concise problem description: symptoms, device/product, error messages, what the customer needs."}}
      },
      "ResearchBrief": {
        "type": "object",
        "properties": {
          "summary": {"type": "string"},
          "corpus_had_relevant_cases": {"type": "boolean"},
          "cases": {"type": "array", "items": {"type": "object", "properties": {"title": {"type": "string"}, "snippet": {"type": "string"}}}},
          "proven_steps": {"type": "array", "items": {"type": "string"}},
          "pitfalls": {"type": "array", "items": {"type": "string"}},
          "clarifying_questions": {"type": "array", "items": {"type": "string"}},
          "device_notes": {"type": "string"},
          "credits_remaining": {"type": "integer", "description": "Present on prepaid keys after a successful run"}
        }
      }
    }
  }
}
