Files
invest-copilot/docs/api/openapi.yaml
T

1294 lines
32 KiB
YAML
Raw Normal View History

2026-05-30 11:28:59 -04:00
openapi: 3.1.0
info:
title: Invest Copilot API
description: AI-native investment research and portfolio copilot
version: 0.1.0
contact:
name: Invest Copilot Team
email: dev@invest-copilot.local
servers:
- url: http://localhost:3000/api/v1
description: Development server
- url: https://api.invest-copilot.local/api/v1
description: Production server
tags:
- name: stocks
description: Stock search, profiles, and data
- name: watchlists
description: Watchlist management
- name: strategies
description: Strategy creation and management
- name: screeners
description: Stock screeners
- name: sectors
description: Sector rotation analysis
- name: alerts
description: Real-time alerts and notifications
- name: streaming
description: Server-Sent Events for real-time updates
paths:
# ─── Stock Search & Profile ──────────────────────────────
/search:
get:
tags: [stocks]
summary: Search stocks by ticker or name
operationId: searchStocks
parameters:
- name: q
in: query
required: true
description: Search query (ticker or company name)
schema:
type: string
minLength: 1
maxLength: 50
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 50
default: 10
responses:
200:
description: Search results
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/SearchResult'
400:
description: Invalid search query
/stocks/{ticker}:
get:
tags: [stocks]
summary: Get full stock profile with all data
operationId: getStockProfile
parameters:
- name: ticker
in: path
required: true
schema:
type: string
example: AAPL
responses:
200:
description: Complete stock profile
content:
application/json:
schema:
$ref: '#/components/schemas/StockProfileResponse'
404:
description: Stock not found
/stocks/{ticker}/peers:
get:
tags: [stocks]
summary: Get peer group with relative performance
operationId: getStockPeers
parameters:
- name: ticker
in: path
required: true
schema:
type: string
example: AAPL
responses:
200:
description: Peer group data
content:
application/json:
schema:
$ref: '#/components/schemas/PeerGroupResponse'
/stocks/{ticker}/price/history:
get:
tags: [stocks]
summary: Get historical price data
operationId: getPriceHistory
parameters:
- name: ticker
in: path
required: true
schema:
type: string
example: AAPL
- name: interval
in: query
schema:
type: string
enum: [1m, 5m, 15m, 30m, 1h, 1d, 1w, 1M]
default: 1d
- name: start
in: query
required: true
schema:
type: string
format: date-time
example: "2024-01-01T00:00:00Z"
- name: end
in: query
required: true
schema:
type: string
format: date-time
example: "2024-12-31T23:59:59Z"
responses:
200:
description: Price history
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/PriceEvent'
/stocks/{ticker}/sec-filings:
get:
tags: [stocks]
summary: Get SEC filings with analysis
operationId: getSecFilings
parameters:
- name: ticker
in: path
required: true
schema:
type: string
example: AAPL
- name: form_type
in: query
description: Filter by form type
schema:
type: string
enum: [10-K, 10-Q, 8-K, 4, 13F, 13D, 13G]
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
responses:
200:
description: SEC filings
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/SecFiling'
/stocks/{ticker}/insider-trades:
get:
tags: [stocks]
summary: Get insider trading activity
operationId: getInsiderTrades
parameters:
- name: ticker
in: path
required: true
schema:
type: string
example: AAPL
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
responses:
200:
description: Insider trades
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/InsiderTrade'
/stocks/{ticker}/sentiment:
get:
tags: [stocks]
summary: Get sentiment signals from all sources
operationId: getStockSentiment
parameters:
- name: ticker
in: path
required: true
schema:
type: string
example: AAPL
responses:
200:
description: Sentiment signals
content:
application/json:
schema:
$ref: '#/components/schemas/SentimentResponse'
# ─── Watchlists ─────────────────────────────────────────
/watchlists:
get:
tags: [watchlists]
summary: Get all user watchlists
operationId: getUserWatchlists
responses:
200:
description: List of watchlists
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Watchlist'
post:
tags: [watchlists]
summary: Create a new watchlist
operationId: createWatchlist
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [name]
properties:
name:
type: string
minLength: 1
maxLength: 255
description:
type: string
maxLength: 1000
responses:
201:
description: Watchlist created
content:
application/json:
schema:
$ref: '#/components/schemas/Watchlist'
/watchlists/{id}:
get:
tags: [watchlists]
summary: Get watchlist with items and live prices
operationId: getWatchlist
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
200:
description: Watchlist with items
content:
application/json:
schema:
$ref: '#/components/schemas/WatchlistWithPrices'
put:
tags: [watchlists]
summary: Update watchlist
operationId: updateWatchlist
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
requestBody:
content:
application/json:
schema:
type: object
properties:
name:
type: string
description:
type: string
responses:
200:
description: Watchlist updated
delete:
tags: [watchlists]
summary: Delete watchlist
operationId: deleteWatchlist
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
204:
description: Watchlist deleted
/watchlists/{id}/items:
get:
tags: [watchlists]
summary: Get watchlist items
operationId: getWatchlistItems
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
200:
description: Watchlist items
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/WatchlistItem'
post:
tags: [watchlists]
summary: Add ticker to watchlist
operationId: addWatchlistItem
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [ticker]
properties:
ticker:
type: string
maxLength: 20
type:
type: string
enum: [stock, etf, index]
notes:
type: string
maxLength: 500
responses:
201:
description: Item added
delete:
tags: [watchlists]
summary: Remove ticker from watchlist
operationId: removeWatchlistItem
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
- name: ticker
in: query
required: true
schema:
type: string
responses:
204:
description: Item removed
# ─── Strategies ─────────────────────────────────────────
/strategies:
get:
tags: [strategies]
summary: Get all user strategies
operationId: getUserStrategies
responses:
200:
description: List of strategies
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Strategy'
post:
tags: [strategies]
summary: Create a new strategy
operationId: createStrategy
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [name, type, conditions]
properties:
name:
type: string
minLength: 1
maxLength: 255
description:
type: string
maxLength: 1000
type:
type: string
enum: [technical, fundamental, hybrid]
conditions:
type: object
required: [rules, logic]
properties:
rules:
type: array
items:
type: object
required: [indicator, operator, value]
properties:
indicator:
type: string
operator:
type: string
enum: [lt, gt, lte, gte, eq, neq, crossover, crossbelow]
value:
type: number
period:
type: integer
source:
type: string
description:
type: string
logic:
type: string
enum: [AND, OR]
timeframe:
type: string
responses:
201:
description: Strategy created
/strategies/{id}:
get:
tags: [strategies]
summary: Get strategy details
operationId: getStrategy
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
200:
description: Strategy details
put:
tags: [strategies]
summary: Update strategy
operationId: updateStrategy
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
requestBody:
content:
application/json:
schema:
type: object
properties:
name:
type: string
description:
type: string
conditions:
type: object
responses:
200:
description: Strategy updated
delete:
tags: [strategies]
summary: Delete strategy
operationId: deleteStrategy
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
204:
description: Strategy deleted
/strategies/{id}/backtest:
post:
tags: [strategies]
summary: Run backtest on a strategy
operationId: backtestStrategy
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
requestBody:
content:
application/json:
schema:
type: object
properties:
start_date:
type: string
format: date
end_date:
type: string
format: date
watchlist_id:
type: string
format: uuid
responses:
200:
description: Backtest results
content:
application/json:
schema:
$ref: '#/components/schemas/BacktestResult'
# ─── Screeners ──────────────────────────────────────────
/screeners:
get:
tags: [screeners]
summary: Get user screeners
operationId: getUserScreeners
responses:
200:
description: List of screeners
post:
tags: [screeners]
summary: Create a new screener
operationId: createScreener
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [name, conditions]
properties:
name:
type: string
description:
type: string
conditions:
type: array
items:
type: object
required: [field, operator, value]
properties:
field:
type: string
operator:
type: string
enum: [lt, gt, lte, gte, eq, neq]
value:
type: number
responses:
201:
description: Screener created
/screeners/{id}/run:
post:
tags: [screeners]
summary: Execute a screener
operationId: runScreener
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
200:
description: Screener results
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
$ref: '#/components/schemas/ScreenerResult'
total:
type: integer
runAt:
type: string
format: date-time
/screeners/{id}/results:
get:
tags: [screeners]
summary: Get last screener results
operationId: getScreenerResults
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
200:
description: Screener results
# ─── Sector Rotation ────────────────────────────────────
/sectors/rotation:
get:
tags: [sectors]
summary: Get current sector rotation analysis
operationId: getSectorRotation
responses:
200:
description: Current rotation analysis
content:
application/json:
schema:
$ref: '#/components/schemas/SectorRotationResponse'
post:
tags: [sectors]
summary: Trigger manual rotation scan
operationId: triggerRotationScan
responses:
200:
description: Scan completed
content:
application/json:
schema:
$ref: '#/components/schemas/SectorRotationResponse'
/sectors/rotation/history:
get:
tags: [sectors]
summary: Get historical rotation data
operationId: getRotationHistory
parameters:
- name: from
in: query
required: true
schema:
type: string
format: date
- name: to
in: query
schema:
type: string
format: date
- name: sector
in: query
schema:
type: string
example: XLK
responses:
200:
description: Historical rotations
# ─── Alerts ─────────────────────────────────────────────
/alerts:
get:
tags: [alerts]
summary: Get user alerts
operationId: getUserAlerts
parameters:
- name: status
in: query
description: Filter by status
schema:
type: string
enum: [active, resolved, dismissed]
default: active
- name: limit
in: query
schema:
type: integer
default: 50
maximum: 200
responses:
200:
description: List of alerts
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Alert'
delete:
tags: [alerts]
summary: Clear resolved alerts
operationId: clearResolvedAlerts
responses:
204:
description: Alerts cleared
/alerts/{id}/resolve:
post:
tags: [alerts]
summary: Mark alert as resolved
operationId: resolveAlert
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
200:
description: Alert resolved
/alerts/{id}/dismiss:
post:
tags: [alerts]
summary: Dismiss an alert
operationId: dismissAlert
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
200:
description: Alert dismissed
# ─── Streaming (SSE) ───────────────────────────────────
/stream/alerts:
get:
tags: [streaming]
summary: Server-Sent Events stream for real-time alerts
operationId: getAlertStream
responses:
200:
description: SSE stream
content:
text/event-stream:
schema:
type: string
example: |
event: alert
data: {"id":"abc","message":"RSI oversold on AAPL","ticker":"AAPL"}
event: rotation
data: {"sector":"XLK","signal":"in","rankChange":3}
components:
schemas:
# ─── Stock Data ───────────────────────────────────────
SearchResult:
type: object
properties:
ticker:
type: string
name:
type: string
exchange:
type: string
sector:
type: string
marketCap:
type: number
PriceEvent:
type: object
properties:
date:
type: string
format: date-time
open:
type: number
high:
type: number
low:
type: number
close:
type: number
volume:
type: integer
adjustedClose:
type: number
StockProfileResponse:
type: object
properties:
profile:
$ref: '#/components/schemas/StockProfile'
price:
$ref: '#/components/schemas/PriceEvent'
peers:
type: array
items:
$ref: '#/components/schemas/Peer'
sentiment:
$ref: '#/components/schemas/SentimentResponse'
secFilings:
type: array
items:
$ref: '#/components/schemas/SecFiling'
insiderTrades:
type: array
items:
$ref: '#/components/schemas/InsiderTrade'
StockProfile:
type: object
properties:
ticker:
type: string
name:
type: string
exchange:
type: string
sector:
type: string
industry:
type: string
marketCap:
type: number
description:
type: string
website:
type: string
nullable: true
ceo:
type: string
nullable: true
employees:
type: integer
nullable: true
peRatio:
type: number
nullable: true
eps:
type: number
nullable: true
dividendYield:
type: number
nullable: true
beta:
type: number
nullable: true
Peer:
type: object
properties:
ticker:
type: string
name:
type: string
similarityScore:
type: number
relativeStrength:
type: number
priceChange1d:
type: number
priceChange5d:
type: number
priceChange30d:
type: number
PeerGroupResponse:
type: object
properties:
ticker:
type: string
peers:
type: array
items:
$ref: '#/components/schemas/Peer'
benchmark:
type: string
benchmarkChange1d:
type: number
SecFiling:
type: object
properties:
ticker:
type: string
cik:
type: string
formType:
type: string
filingDate:
type: string
format: date
reportDate:
type: string
format: date
accessionNumber:
type: string
url:
type: string
contentSummary:
type: string
sentimentScore:
type: number
tags:
type: array
items:
type: string
InsiderTrade:
type: object
properties:
ticker:
type: string
insiderName:
type: string
insiderTitle:
type: string
transactionDate:
type: string
format: date
transactionType:
type: string
enum: [BUY, SELL, GIFT, IN_EX]
shares:
type: integer
pricePerShare:
type: number
totalValue:
type: number
sharesOwnedAfter:
type: integer
filingDate:
type: string
format: date
SentimentResponse:
type: object
properties:
ticker:
type: string
signals:
type: array
items:
$ref: '#/components/schemas/SentimentSignal'
averageScore:
type: number
confidence:
type: number
SentimentSignal:
type: object
properties:
source:
type: string
score:
type: number
minimum: -1
maximum: 1
confidence:
type: number
timestamp:
type: string
format: date-time
context:
type: string
# ─── Watchlists ───────────────────────────────────────
Watchlist:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
description:
type: string
nullable: true
isDefault:
type: boolean
itemCount:
type: integer
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
WatchlistWithPrices:
allOf:
- $ref: '#/components/schemas/Watchlist'
- type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/WatchlistItemWithPrice'
WatchlistItem:
type: object
properties:
ticker:
type: string
type:
type: string
enum: [stock, etf, index]
notes:
type: string
nullable: true
addedAt:
type: string
format: date-time
priceAtAddition:
type: number
nullable: true
WatchlistItemWithPrice:
allOf:
- $ref: '#/components/schemas/WatchlistItem'
- type: object
properties:
currentPrice:
type: number
priceChange1d:
type: number
priceChangePercent:
type: number
marketCap:
type: number
nullable: true
# ─── Strategies ───────────────────────────────────────
Strategy:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
description:
type: string
type:
type: string
enum: [technical, fundamental, hybrid]
conditions:
type: object
properties:
rules:
type: array
items:
type: object
properties:
indicator:
type: string
operator:
type: string
value:
type: number
period:
type: integer
source:
type: string
description:
type: string
logic:
type: string
enum: [AND, OR]
timeframe:
type: string
backtestResults:
$ref: '#/components/schemas/BacktestResult'
nullable: true
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
BacktestResult:
type: object
properties:
startDate:
type: string
format: date
endDate:
type: string
format: date
totalReturn:
type: number
annualizedReturn:
type: number
maxDrawdown:
type: number
sharpeRatio:
type: number
winRate:
type: number
totalTrades:
type: integer
avgHoldTime:
type: string
equityCurve:
type: array
items:
type: number
# ─── Screeners ────────────────────────────────────────
Screener:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
description:
type: string
nullable: true
lastRunAt:
type: string
format: date-time
nullable: true
resultsCount:
type: integer
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
ScreenerResult:
type: object
properties:
ticker:
type: string
matchScore:
type: number
rankedPosition:
type: integer
resultData:
type: object
# ─── Sector Rotation ──────────────────────────────────
SectorRotation:
type: object
properties:
detectionDate:
type: string
format: date
sectorTicker:
type: string
sectorName:
type: string
rankNow:
type: integer
rankPrevious:
type: integer
rankChange:
type: integer
momentum20d:
type: number
momentum50d:
type: number
momentum200d:
type: number
relativeStrength:
type: number
signal:
type: string
enum: [in, out, stable, accelerating]
analysisSummary:
type: string
SectorRotationResponse:
type: object
properties:
date:
type: string
format: date
rotations:
type: array
items:
$ref: '#/components/schemas/SectorRotation'
inRotation:
type: array
items:
type: string
outOfRotation:
type: array
items:
type: string
macroContext:
type: object
nullable: true
# ─── Alerts ───────────────────────────────────────────
Alert:
type: object
properties:
id:
type: string
format: uuid
watchlistId:
type: string
format: uuid
strategyId:
type: string
format: uuid
nullable: true
ticker:
type: string
type:
type: string
enum: [strategy_trigger, sec_filing, sentiment, rotation, price]
triggerType:
type: string
message:
type: string
severity:
type: string
enum: [info, warning, critical]
status:
type: string
enum: [active, resolved, dismissed]
triggeredAt:
type: string
format: date-time
resolvedAt:
type: string
format: date-time
nullable: true
metadata:
type: object