{
  "openapi": "3.1.0",
  "info": {
    "title": "Coattail Research API",
    "version": "1.0.0-beta",
    "description": "Read-only, invite-only developer beta for stored research previews. An account must be enabled for each requested dataset. No private watchlists, portfolios, live prices, trading, or bulk exports. Keys expire in 30 days; all keys for an account share 60 requests per minute and four concurrent requests. No monthly credits at launch."
  },
  "servers": [{ "url": "https://pro.coattail.co/api/v1" }],
  "security": [{ "ApiKey": [] }],
  "paths": {
    "/investors": {
      "get": {
        "operationId": "searchInvestors",
        "summary": "Find tracked investors by name",
        "description": "Returns up to 12 politician, insider, and hedge-fund metadata matches. No live pricing.",
        "parameters": [{ "name": "query", "in": "query", "required": true, "schema": { "type": "string", "minLength": 2, "maxLength": 60 }, "example": "Pelosi" }],
        "responses": { "200": { "$ref": "#/components/responses/Research" }, "400": { "$ref": "#/components/responses/Error" }, "401": { "$ref": "#/components/responses/Error" }, "403": { "$ref": "#/components/responses/Error" }, "429": { "$ref": "#/components/responses/Limited" }, "503": { "$ref": "#/components/responses/Error" }, "504": { "$ref": "#/components/responses/Error" } }
      }
    },
    "/disclosures": {
      "get": {
        "operationId": "getDisclosures",
        "summary": "Look up recent stock or investor disclosures",
        "description": "Provide exactly one of ticker or investor_id. Returns up to six disclosures with available source URLs. This is a limited preview, not a complete history. filed_at is the disclosure date, traded_at is the reported transaction date and may be unknown. Values can be ranges. An empty result is not evidence of no activity.",
        "parameters": [
          { "name": "ticker", "in": "query", "schema": { "type": "string", "minLength": 1, "maxLength": 15 }, "example": "NVDA" },
          { "name": "investor_id", "in": "query", "schema": { "type": "string", "minLength": 1, "maxLength": 160 }, "example": "house_nancy_pelosi" },
          { "name": "category", "in": "query", "schema": { "type": "string", "enum": ["all", "politician", "insider", "hedge_fund"], "default": "all" } }
        ],
        "responses": { "200": { "$ref": "#/components/responses/Research" }, "400": { "$ref": "#/components/responses/Error" }, "401": { "$ref": "#/components/responses/Error" }, "403": { "$ref": "#/components/responses/Error" }, "429": { "$ref": "#/components/responses/Limited" }, "503": { "$ref": "#/components/responses/Error" }, "504": { "$ref": "#/components/responses/Error" } }
      }
    },
    "/intel": {
      "get": {
        "operationId": "getStockIntel",
        "summary": "Read enabled stock intelligence",
        "description": "Six stored records per page. Dataset-specific preview rules and database RLS apply. No raw earnings transcripts. Off-exchange volume does not establish buying or selling direction. Each record retains its report, award, filing, or action date.",
        "parameters": [
          { "name": "ticker", "in": "query", "required": true, "schema": { "type": "string", "minLength": 1, "maxLength": 15 }, "example": "NVDA" },
          { "name": "type", "in": "query", "required": true, "schema": { "type": "string", "enum": ["contracts", "lobbying", "short", "fda", "darkpool", "earnings"] } },
          { "name": "offset", "in": "query", "schema": { "type": "integer", "minimum": 0, "maximum": 120, "default": 0 } }
        ],
        "responses": { "200": { "$ref": "#/components/responses/Research" }, "400": { "$ref": "#/components/responses/Error" }, "401": { "$ref": "#/components/responses/Error" }, "403": { "$ref": "#/components/responses/Error" }, "429": { "$ref": "#/components/responses/Limited" }, "503": { "$ref": "#/components/responses/Error" }, "504": { "$ref": "#/components/responses/Error" } }
      }
    }
  },
  "components": {
    "securitySchemes": { "ApiKey": { "type": "http", "scheme": "bearer", "bearerFormat": "ct_live_ followed by 64 hexadecimal characters", "description": "Create a key at https://pro.coattail.co/developers. Send it in Authorization: Bearer, never in the URL. Keep the key on your server." } },
    "schemas": {
      "Research": {
        "type": "object",
        "required": ["rows", "hasMore", "fetchedAt", "note"],
        "properties": {
          "rows": { "type": "array", "maxItems": 12, "items": { "type": "object", "additionalProperties": true } },
          "hasMore": { "type": "boolean", "description": "Additional records exist beyond the page or preview." },
          "fetchedAt": { "type": "string", "format": "date-time", "description": "Retrieval time, not the source reporting date. Cached results retain original retrieval time." },
          "note": { "type": "string" },
          "nextOffset": { "type": ["integer", "null"], "maximum": 120, "description": "Intel only. Follow only when non-null; do not generate an offset beyond the preview cap." },
          "previewLimit": { "oneOf": [{ "type": "integer", "const": 6 }, { "type": "boolean" }] }
        }
      },
      "Error": { "type": "object", "required": ["error"], "properties": { "error": { "type": "object", "required": ["code", "message"], "properties": { "code": { "type": "string" }, "message": { "type": "string" } } } } }
    },
    "responses": {
      "Research": { "description": "Bounded stored-data preview", "headers": { "RateLimit-Limit": { "schema": { "type": "integer" } }, "RateLimit-Remaining": { "schema": { "type": "integer" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Research" } } } },
      "Error": { "description": "400 invalid parameters; 401 invalid/expired/revoked key; 403 dataset not enabled; 503 temporary failure; 504 cancelled/timed out. Errors contain no credentials or provider response bodies.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Limited": { "description": "Account request/concurrency limit reached. Wait before retrying.", "headers": { "Retry-After": { "schema": { "type": "integer" }, "description": "Seconds before retrying" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    }
  }
}
