{
  "openapi": "3.1.0",
  "info": {
    "title": "0si.ai Disclosure API",
    "version": "1.0.0",
    "description": "Pro users can access analyzed Korean market disclosures and realtime SSE events."
  },
  "servers": [
    { "url": "https://app.0si.ai/api/v1" }
  ],
  "security": [
    { "bearerAuth": [] }
  ],
  "paths": {
    "/status": {
      "get": {
        "operationId": "getStatus",
        "summary": "Validate API access",
        "responses": {
          "200": { "description": "API access is active" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/disclosures": {
      "get": {
        "operationId": "listDisclosures",
        "summary": "List analyzed disclosures",
        "parameters": [
          { "name": "cursor", "in": "query", "schema": { "type": "integer", "minimum": 0 }, "description": "Return rows older than this sequence." },
          { "name": "after", "in": "query", "schema": { "type": "integer", "minimum": 0 }, "description": "Return rows newer than this sequence in ascending order." },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 } },
          { "name": "stock_code", "in": "query", "schema": { "type": "string", "maxLength": 12 } },
          { "name": "market", "in": "query", "schema": { "type": "string", "enum": ["KOSPI", "KOSDAQ", "KONEX"] } },
          { "name": "sector", "in": "query", "schema": { "type": "string", "maxLength": 80 } },
          { "name": "q", "in": "query", "schema": { "type": "string", "maxLength": 120 } },
          { "name": "sentiment", "in": "query", "schema": { "$ref": "#/components/schemas/Sentiment" } },
          { "name": "source", "in": "query", "schema": { "type": "string", "enum": ["KIND", "OpenDART"] } },
          { "name": "submitted_from", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "submitted_to", "in": "query", "schema": { "type": "string", "format": "date-time" } }
        ],
        "responses": {
          "200": {
            "description": "Disclosure list",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DisclosureList" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/disclosures/{disclosure_id}": {
      "get": {
        "operationId": "getDisclosure",
        "summary": "Get a disclosure and collected document text",
        "parameters": [
          { "$ref": "#/components/parameters/DisclosureId" }
        ],
        "responses": {
          "200": {
            "description": "Disclosure detail",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DisclosureDetail" } } }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/disclosures/{disclosure_id}/market-reaction": {
      "get": {
        "operationId": "getMarketReaction",
        "summary": "Get the 30-minute pre/post disclosure market window",
        "parameters": [
          { "$ref": "#/components/parameters/DisclosureId" }
        ],
        "responses": {
          "200": { "description": "Market reaction and minute points" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/stream": {
      "get": {
        "operationId": "streamDisclosures",
        "summary": "Stream disclosure events with Server-Sent Events",
        "parameters": [
          { "name": "cursor", "in": "query", "schema": { "type": "integer", "minimum": 0 } },
          { "name": "Last-Event-ID", "in": "header", "schema": { "type": "integer", "minimum": 0 } }
        ],
        "responses": {
          "200": {
            "description": "SSE stream with stream.ready, disclosure.created, disclosure.updated, and heartbeat events",
            "content": { "text/event-stream": { "schema": { "type": "string" } } }
          },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "osi_live_..."
      }
    },
    "parameters": {
      "DisclosureId": {
        "name": "disclosure_id",
        "in": "path",
        "required": true,
        "schema": { "type": "string" },
        "example": "kind:20260722000912"
      }
    },
    "schemas": {
      "Sentiment": {
        "type": "string",
        "enum": ["very_positive", "positive", "neutral", "negative", "very_negative"]
      },
      "Analysis": {
        "type": "object",
        "required": ["status", "signal", "signal_label", "confidence", "summary", "key_points", "risk_flags", "tags"],
        "properties": {
          "status": { "type": "string", "example": "succeeded" },
          "signal": { "$ref": "#/components/schemas/Sentiment" },
          "signal_label": { "type": "string", "example": "긍정" },
          "confidence": { "type": "string", "enum": ["high", "medium", "low"] },
          "summary": { "type": "string" },
          "key_points": { "type": "array", "items": { "type": "string" } },
          "risk_flags": { "type": "array", "items": { "type": "string" } },
          "tags": { "type": "array", "items": { "type": "string" } },
          "is_correction": { "type": "boolean" },
          "correction_materiality": { "type": "string" }
        }
      },
      "Disclosure": {
        "type": "object",
        "required": ["id", "sequence", "company_name", "title", "source", "analysis", "market_reaction"],
        "properties": {
          "id": { "type": "string" },
          "sequence": { "type": "integer" },
          "stock_code": { "type": "string" },
          "company_name": { "type": "string" },
          "market": { "type": "string" },
          "sector": { "type": "string" },
          "title": { "type": "string" },
          "source": { "type": "string" },
          "source_url": { "type": "string", "format": "uri" },
          "submitted_at": { "type": ["string", "null"], "format": "date-time" },
          "detected_at": { "type": ["string", "null"], "format": "date-time" },
          "published_at": { "type": ["string", "null"], "format": "date-time" },
          "analysis": { "$ref": "#/components/schemas/Analysis" },
          "market_reaction": { "type": "object", "additionalProperties": true }
        }
      },
      "DisclosureList": {
        "type": "object",
        "required": ["object", "data", "pagination", "meta"],
        "properties": {
          "object": { "const": "list" },
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/Disclosure" } },
          "pagination": { "type": "object", "additionalProperties": true },
          "meta": { "type": "object", "additionalProperties": true }
        }
      },
      "DisclosureDetail": {
        "type": "object",
        "required": ["object", "data", "meta"],
        "properties": {
          "object": { "const": "disclosure" },
          "data": {
            "allOf": [
              { "$ref": "#/components/schemas/Disclosure" },
              {
                "type": "object",
                "properties": {
                  "document": {
                    "type": "object",
                    "properties": {
                      "text": { "type": "string" },
                      "character_count": { "type": "integer" }
                    }
                  }
                }
              }
            ]
          },
          "meta": { "type": "object", "additionalProperties": true }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "detail": {
            "type": "object",
            "properties": {
              "code": { "type": "string" },
              "message": { "type": "string" }
            }
          }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "API key is missing, invalid, or revoked",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "Forbidden": {
        "description": "An active Pro plan or required scope is missing",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "NotFound": {
        "description": "Disclosure was not found",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "RateLimited": {
        "description": "Rate or concurrent stream limit exceeded",
        "headers": {
          "Retry-After": { "schema": { "type": "integer" } },
          "X-RateLimit-Limit": { "schema": { "type": "integer" } },
          "X-RateLimit-Remaining": { "schema": { "type": "integer" } },
          "X-RateLimit-Reset": { "schema": { "type": "integer" } }
        },
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    }
  }
}
