{
  "openapi": "3.0.3",
  "info": {
    "title": "WatchfulEye API",
    "version": "1.0.0",
    "description": "AI-powered market & geopolitical intelligence. Agents: fetch https://api.watchfuleye.us/llms.txt for a complete self-serve guide including zero-click key provisioning (POST /api/v1/keys/create with {username,password})."
  },
  "servers": [
    {
      "url": "https://api.watchfuleye.us"
    },
    {
      "url": "https://watchfuleye.us"
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Developer key (wfe_ + 64 hex). Provision programmatically via POST /api/v1/keys/create."
      }
    },
    "schemas": {
      "Envelope": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "error": {
            "type": "string"
          }
        }
      }
    }
  },
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "paths": {
    "/api/v1/keys/create": {
      "post": {
        "summary": "Provision an API key with account credentials (no browser needed)",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "username",
                  "password"
                ],
                "properties": {
                  "username": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "rateLimit": {
                    "type": "integer",
                    "minimum": 10,
                    "maximum": 1000
                  },
                  "expiresInDays": {
                    "type": "integer",
                    "maximum": 365
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One-time raw key in `key` (wfe_...). Not retrievable again."
          }
        }
      }
    },
    "/api/v1/keys/list": {
      "post": {
        "summary": "List your API keys (prefixes only)",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "username",
                  "password"
                ],
                "properties": {
                  "username": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Key list"
          }
        }
      }
    },
    "/api/v1/keys/revoke": {
      "post": {
        "summary": "Revoke an API key",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "username",
                  "password",
                  "keyId"
                ],
                "properties": {
                  "username": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  },
                  "keyId": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Revoked"
          }
        }
      }
    },
    "/api/v1/articles": {
      "get": {
        "summary": "List intelligence articles (newest first)",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "min_impact",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Articles with classification metadata"
          }
        }
      }
    },
    "/api/v1/articles/{id}": {
      "get": {
        "summary": "Single article with full body, sentiment, AI classification",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Article"
          },
          "404": {
            "description": "Not found"
          }
        }
      }
    },
    "/api/v1/search": {
      "get": {
        "summary": "Keyword search across article titles/descriptions",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching articles"
          }
        }
      }
    },
    "/api/v1/intel-reports": {
      "get": {
        "summary": "AI-generated intel briefings",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Reports"
          }
        }
      }
    },
    "/api/v1/intel-reports/{id}": {
      "get": {
        "summary": "Full report content with sources and quality score",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Report"
          }
        }
      }
    },
    "/api/v1/predictions": {
      "get": {
        "summary": "Market predictions with confidence, targets, outcome scores (T+1/3/7/14/30)",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "evaluated",
                "pending"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Predictions"
          }
        }
      }
    },
    "/api/v1/predictions/performance": {
      "get": {
        "summary": "Aggregate win rate and accuracy stats",
        "responses": {
          "200": {
            "description": "Performance stats"
          }
        }
      }
    },
    "/api/v1/market/mood": {
      "get": {
        "summary": "Current AI sentiment composite with regime classification",
        "responses": {
          "200": {
            "description": "Market mood"
          }
        }
      }
    },
    "/api/v1/called-it/scorecard": {
      "get": {
        "summary": "Verified-predictions scorecard: hit rate, Brier, confirmation timing, loss reasons",
        "responses": {
          "200": {
            "description": "Scorecard (cached 60s)"
          }
        }
      }
    },
    "/api/v1/called-it/recent": {
      "get": {
        "summary": "Most recent confirmed wins",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Recent wins"
          }
        }
      }
    },
    "/api/v1/stats": {
      "get": {
        "summary": "Platform statistics overview",
        "responses": {
          "200": {
            "description": "Stats"
          }
        }
      }
    },
    "/api/v1/articles/{articleId}/analyze": {
      "post": {
        "summary": "Run AI quick-analysis on an article (consumes credits)",
        "parameters": [
          {
            "name": "articleId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Structured analysis with analysisId"
          },
          "404": {
            "description": "Article not found"
          }
        }
      }
    },
    "/api/v1/analyses/{analysisId}": {
      "get": {
        "summary": "Retrieve a completed analysis by id",
        "parameters": [
          {
            "name": "analysisId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Analysis"
          },
          "404": {
            "description": "Not found"
          }
        }
      }
    },
    "/api/v1/analyses/{analysisId}/share": {
      "post": {
        "summary": "Create a public share link for an analysis",
        "parameters": [
          {
            "name": "analysisId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Share URL"
          }
        }
      }
    },
    "/api/v1/articles/{articleId}/analyze-and-share": {
      "post": {
        "summary": "Analyze an article and create a share link in one call (consumes credits)",
        "parameters": [
          {
            "name": "articleId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Analysis + share URL"
          },
          "404": {
            "description": "Article not found"
          }
        }
      }
    },
    "/api/v1/called-it/list": {
      "get": {
        "summary": "Paginated published Called It list",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "wins",
                "losses",
                "all"
              ],
              "default": "wins"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List"
          }
        }
      }
    },
    "/api/v1/called-it/by-article/{articleId}": {
      "get": {
        "summary": "Predictions a given article confirmed (max 5)",
        "parameters": [
          {
            "name": "articleId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Predictions"
          }
        }
      }
    },
    "/api/v1/called-it/{slug}": {
      "get": {
        "summary": "Single prediction detail + confirmation events (max 20)",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Detail"
          }
        }
      }
    },
    "/api/v1/causal/hypotheses": {
      "get": {
        "summary": "Causal hypotheses linking events to sectors/tickers/second-order effects",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "active"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Hypotheses"
          }
        }
      }
    },
    "/api/v1/causal/hypotheses/{id}": {
      "get": {
        "summary": "Hypothesis detail with outcome scores, channels, evidence",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Hypothesis"
          }
        }
      }
    },
    "/api/v1/causal/narratives": {
      "get": {
        "summary": "Tracked market narratives with momentum and stage progression",
        "responses": {
          "200": {
            "description": "Narratives"
          }
        }
      }
    },
    "/api/v1/asset-exposures": {
      "get": {
        "summary": "Per-ticker exposure assessments to active hypotheses",
        "responses": {
          "200": {
            "description": "Exposures"
          }
        }
      }
    },
    "/api/v1/saved-articles": {
      "get": {
        "summary": "Bookmarked articles (scoped to key owner)",
        "responses": {
          "200": {
            "description": "Saved articles"
          }
        }
      }
    },
    "/api/v1/conversations": {
      "get": {
        "summary": "Eye chat conversations (scoped to key owner)",
        "responses": {
          "200": {
            "description": "Conversations"
          }
        }
      }
    },
    "/api/v1/conversations/{id}/messages": {
      "get": {
        "summary": "Messages within a conversation",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Messages"
          }
        }
      }
    },
    "/api/v1/credits": {
      "get": {
        "summary": "Remaining credit balance and subscription tier",
        "responses": {
          "200": {
            "description": "Credits"
          }
        }
      }
    },
    "/api/v1/insider/signals": {
      "get": {
        "summary": "List SEC insider conviction signals (Form 4 derived)",
        "description": " Requires an active paid WatchfulEye subscription on the account that owns the API key (402 otherwise).",
        "tags": [
          "Insider"
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "402": {
            "description": "Paid subscription required"
          }
        },
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "Lookback window, 1-365 (default 30)"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "1-200 (default 50)"
          },
          {
            "name": "minScore",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "Minimum conviction score 1-99 (default 20)"
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by ticker, company, title, or insider name"
          },
          {
            "name": "stressOnly",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "true = only issuers with financial-stress factor tags"
          },
          {
            "name": "clusterOnly",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "true = only cluster-buy signals"
          }
        ]
      }
    },
    "/api/v1/insider/signals/{id}": {
      "get": {
        "summary": "Insider signal detail with transaction, SEC filing, and outcomes",
        "description": " Requires an active paid WatchfulEye subscription on the account that owns the API key (402 otherwise).",
        "tags": [
          "Insider"
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "402": {
            "description": "Paid subscription required"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ]
      }
    },
    "/api/v1/insider/signals/{id}/context": {
      "get": {
        "summary": "AI-generated issuer & insider context for a signal",
        "description": " Requires an active paid WatchfulEye subscription on the account that owns the API key (402 otherwise).",
        "tags": [
          "Insider"
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "402": {
            "description": "Paid subscription required"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ]
      }
    },
    "/api/v1/insider/ticker/{symbol}": {
      "get": {
        "summary": "Insider signals for a ticker (latest 50)",
        "description": " Requires an active paid WatchfulEye subscription on the account that owns the API key (402 otherwise).",
        "tags": [
          "Insider"
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "402": {
            "description": "Paid subscription required"
          }
        },
        "parameters": [
          {
            "name": "symbol",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/insider/companies": {
      "get": {
        "summary": "Companies with stored insider signals (typeahead)",
        "description": " Requires an active paid WatchfulEye subscription on the account that owns the API key (402 otherwise).",
        "tags": [
          "Insider"
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "402": {
            "description": "Paid subscription required"
          }
        },
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": ""
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "1-30 (default 12)"
          }
        ]
      }
    },
    "/api/v1/insider/stats": {
      "get": {
        "summary": "Insider pipeline stats",
        "description": " Requires an active paid WatchfulEye subscription on the account that owns the API key (402 otherwise).",
        "tags": [
          "Insider"
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "402": {
            "description": "Paid subscription required"
          }
        }
      }
    }
  }
}