Files
stonks-oracle/docs/api-reference.md
T
Celes Renata 88ad1e8d99 feat: comprehensive docs, unit tests, docker-compose app services
- Add scheduler and ingestion unit tests (test_scheduler_unit.py, test_ingestion_unit.py)
- Add all 13 app services + dashboard to docker-compose.yml
- Add full documentation suite: API reference, Helm reference, Docker deployment guide,
  3 architecture diagrams (K8s, Docker Compose, data pipeline), AI agent guide,
  backup/restore guide, observability/metrics reference, per-service docs
- Add intelligence pipeline deep-dive docs with Mermaid diagrams
- Update README with documentation index and links
- Add specs for comprehensive-quality-docs, intelligence-pipeline-deep-dive,
  sanitized-pipeline-docs
2026-04-22 02:56:41 +00:00

42 KiB
Raw Blame History

Stonks Oracle — API Reference

This document covers every HTTP endpoint exposed by the four FastAPI services in the Stonks Oracle platform. For each endpoint: HTTP method, path, query parameters (with type, default, and constraints), request body schema, response schema, and error codes.

Live endpoints:

Service Base URL Source
Query API https://stonks-api.celestium.life services/api/app.py
Symbol Registry https://stonks-registry.celestium.life services/symbol_registry/app.py
Trading Engine https://stonks-trading.celestium.life services/trading/app.py
Risk Engine (cluster-internal) services/risk/app.py

Common error format: All services return errors as {"detail": "error message"} with the appropriate HTTP status code.


Table of Contents


1. Query API

Source: services/api/app.py Base path: / (most endpoints prefixed with /api/)

1.1 Health and Metrics

GET /health

Liveness probe. Verifies database connectivity.

  • Response: {"status": "ok"}
  • Errors: 503 — Database unavailable

GET /metrics

Prometheus metrics endpoint for scraping.

  • Response: Prometheus text format (text/plain)

1.2 Companies

GET /api/companies

List tracked companies with optional filters.

Parameter Type Default Description
active bool true Filter by active status
sector string Filter by sector
ticker string Filter by ticker (auto-uppercased)
  • Response: Array of company objects with id, ticker, legal_name, exchange, sector, industry, market_cap_bucket, active, created_at, updated_at

GET /api/companies/{company_id}

Get a single company with aliases and active source count.

  • Path params: company_id (UUID string)
  • Response: Company object + aliases[] + active_source_count
  • Errors: 404 — Company not found

GET /api/companies/{company_id}/sources

List sources configured for a company.

  • Path params: company_id (UUID string)
  • Response: Array of source objects with id, source_type, source_name, config, credibility_score, retention_days, access_policy, active

1.3 Documents

GET /api/documents

List documents with optional filters, ordered by published_at descending.

Parameter Type Default Constraints Description
ticker string Filter by ticker
company_id string Filter by company UUID
document_type string Filter by type
status string Filter by processing status
since string ISO 8601 timestamp Documents published after this time
limit int 50 max 200 Page size
offset int 0 Pagination offset
  • Response: Array of document objects

GET /api/documents/{document_id}

Get a single document with intelligence extraction and company mentions.

  • Path params: document_id (UUID string)
  • Response: Document object + company_mentions[] + intelligence (with company_impacts[])
  • Errors: 404 — Document not found

GET /api/trends

List trend summaries with optional filters.

Parameter Type Default Constraints Description
ticker string Filter by entity_id (ticker)
entity_type string "company" Entity type filter
window string Time window filter
limit int 50 max 200 Page size
offset int 0 Pagination offset
  • Response: Array of trend objects with JSONB fields parsed, plus projection sub-object from trend_projections

GET /api/trends/history

Historical trend snapshots for charting (time series from trend_history table).

Parameter Type Default Constraints Description
ticker string Filter by entity_id
window string Time window filter
limit int 200 max 1000 Max rows
  • Response: Array of trend history objects ordered by generated_at ascending

GET /api/trends/{trend_id}

Get a single trend summary by ID.

  • Path params: trend_id (UUID string)
  • Response: Trend object with parsed JSONB fields
  • Errors: 404 — Trend not found

GET /api/trends/{trend_id}/evidence

Drill down from a trend window to contributing documents and raw artifacts. Full provenance chain.

  • Path params: trend_id (UUID string)
  • Response: { trend, evidence[] } — each evidence item includes intelligence and company_impacts[]
  • Errors: 404 — Trend not found

GET /api/trends/{trend_id}/projection

Trend projection for a specific trend window.

  • Path params: trend_id (UUID string)
  • Response: Projection object with projected_direction, projected_strength, projected_confidence, projection_horizon, driving_factors, macro_contribution_pct, diverges_from_current
  • Errors: 404 — Trend not found

1.5 Market Prices

GET /api/market/prices/{ticker}

Historical close prices from market_snapshots.

Parameter Type Default Constraints Description
limit int 30 max 200 Max bars returned
  • Path params: ticker (auto-uppercased)
  • Response: Array of OHLCV objects ordered oldest-first

1.6 Recommendations

GET /api/recommendations

List recommendations with optional filters.

Parameter Type Default Constraints Description
ticker string Filter by ticker
action string Filter by action (buy/sell/hold)
mode string Filter by mode
since string ISO 8601 Generated after this time
min_confidence float 0.01.0 Minimum confidence threshold
limit int 50 max 200 Page size
offset int 0 Pagination offset
latest bool true Return only latest per ticker
  • Response: Array of recommendation objects

GET /api/recommendations/{recommendation_id}

Get a single recommendation with evidence and risk evaluation.

  • Path params: recommendation_id (UUID string)
  • Response: Recommendation + evidence[] + risk_evaluation
  • Errors: 404 — Recommendation not found

GET /api/recommendations/{recommendation_id}/evidence

Full evidence drill-down: provenance chain from recommendation to source documents and raw artifacts.

  • Path params: recommendation_id (UUID string)
  • Response: { recommendation, evidence[], trend_window } — each evidence item includes intelligence and company_impacts[]
  • Errors: 404 — Recommendation not found

1.7 Orders

GET /api/orders

List orders with optional filters.

Parameter Type Default Constraints Description
ticker string Filter by ticker
status string Filter by order status
side string Filter by side (buy/sell)
since string ISO 8601 Created after this time
limit int 50 max 200 Page size
offset int 0 Pagination offset
  • Response: Array of order objects

GET /api/orders/{order_id}

Get a single order with events, decision trace, and full audit trail.

  • Path params: order_id (UUID string)
  • Response: Order object + events[] + audit_trail
  • Errors: 404 — Order not found

1.8 Positions

GET /api/positions

List current positions.

Parameter Type Default Description
ticker string Filter by ticker
  • Response: Array of position objects with id, broker_account_id, ticker, quantity, avg_entry_price, current_price, unrealized_pnl, realized_pnl, updated_at

1.9 Audit Trail

GET /api/audit/{entity_type}/{entity_id}

Get audit events for any entity type and ID.

  • Path params: entity_type (string), entity_id (string)
  • Response: Array of audit event objects
  • Errors: 404 — No audit events found

1.10 Admin: Source Health

GET /api/admin/sources/health

Source health overview with latest ingestion status and failure counts.

Parameter Type Default Description
source_type string Filter by source type
company_id string Filter by company UUID
active_only bool true Only show active sources
  • Response: Array of source health objects with source_id, source_type, source_name, credibility_score, ticker, legal_name, last_run_status, last_run_at, last_error, last_items_fetched, last_items_new, total_runs_24h, failed_runs_24h, total_items_24h

GET /api/admin/sources/{source_id}/runs

Recent ingestion runs for a specific source.

Parameter Type Default Constraints Description
limit int 20 max 100 Page size
offset int 0 Pagination offset

PUT /api/admin/sources/{source_id}/toggle

Enable or disable a source.

Parameter Type Default Description
active bool true New active state
  • Errors: 404 — Source not found

PUT /api/admin/sources/{source_id}/credibility

Update a source's credibility score.

Parameter Type Default Constraints Description
credibility_score float 0.01.0 New credibility score
  • Errors: 404 — Source not found

1.11 Admin: Company Management

PUT /api/admin/companies/{company_id}/toggle

Enable or disable a tracked company.

Parameter Type Default Description
active bool true New active state
  • Errors: 404 — Company not found

PUT /api/admin/companies/{company_id}/sector

Update a company's sector and industry classification.

Parameter Type Default Description
sector string Required. New sector
industry string Optional new industry
  • Errors: 404 — Company not found

GET /api/admin/companies/coverage

Source coverage overview per active company. Shows active source counts by type.

  • Response: Array of objects with company_id, ticker, legal_name, sector, active_sources, market_sources, news_sources, filings_sources, web_scrape_sources, broker_sources

1.12 Admin: Trading Configuration

GET /api/admin/trading/config

Get the current active risk/trading configuration.

  • Response: Risk config object with id, name, trading_mode, config (JSONB), active, timestamps

PUT /api/admin/trading/mode

Switch the active trading mode.

Parameter Type Constraints Description
mode string paper, live, or disabled Required. New trading mode

PUT /api/admin/trading/config

Update the active risk configuration JSON.

  • Body: dict[str, Any] — partial or full risk config object
  • Response: Updated config object

GET /api/admin/trading/approvals

List pending operator approval requests for live trading orders.

  • Response: Array of approval objects with order_job (JSONB), recommendation_id, ticker, side, quantity, estimated_value, status, expires_at, etc.

PUT /api/admin/trading/approvals/{approval_id}

Approve or reject a pending operator approval request.

Parameter Type Default Description
approved bool Required. Approve or reject
reviewed_by string "operator" Reviewer identity
review_note string "" Optional note
  • Errors: 404 — Approval not found or no longer pending

GET /api/admin/trading/lockouts

List active symbol lockouts (news-shock, cooldown, manual).

POST /api/admin/trading/lockouts

Create a manual symbol lockout.

  • Body: { ticker: string, reason: string, duration_minutes: int, lockout_type?: string }
  • Errors: 400 — Missing or invalid fields

DELETE /api/admin/trading/lockouts/{lockout_id}

Delete a symbol lockout (early removal).

  • Errors: 404 — Lockout not found

GET /api/admin/trading/approval-config

Get operator approval settings from the active risk config.

  • Response: { auto_approve_paper, require_approval_for_live, approval_timeout_minutes }

PUT /api/admin/trading/approval-config

Update operator approval settings.

  • Body: { auto_approve_paper?: bool, require_approval_for_live?: bool, approval_timeout_minutes?: int }
  • Response: Updated approval settings

1.13 Operational Dashboard

GET /api/ops/ingestion/throughput

Ingestion throughput over time, bucketed by interval.

Parameter Type Default Constraints Description
hours int 24 1168 Time window
bucket string "1h" 15m, 1h, 6h, 1d Bucket interval
  • Response: Array of bucketed throughput objects by source type

GET /api/ops/ingestion/summary

High-level ingestion summary for the operational dashboard.

Parameter Type Default Constraints Description
hours int 24 1168 Time window
  • Response: { total_runs, completed, failed, pending, running, total_items_fetched, total_items_new, active_sources, active_companies, by_source_type[], hours }

GET /api/ops/model/failures

Recent model extraction failures with error details.

Parameter Type Default Constraints Description
hours int 24 1168 Time window
limit int 50 max 200 Max results

GET /api/ops/model/performance

Aggregated model performance metrics.

Parameter Type Default Constraints Description
hours int 24 1168 Time window
model_name string Filter by model

GET /api/ops/pipeline/health

Pipeline stage health summary across ingestion, parsing, extraction, and aggregation.

Parameter Type Default Constraints Description
hours int 24 1168 Time window
  • Response: { hours, pipeline_enabled, document_stages[], parsing, extraction, aggregation, queue_depths }

GET /api/ops/pipeline/stream

Server-Sent Events stream of live pipeline status. Pushes queue depths and document stage counts every 3 seconds.

  • Response: text/event-stream with JSON data payloads

POST /api/ops/pipeline/retry-failed

Re-enqueue documents stuck in extraction_failed for another attempt (up to 200).

  • Response: { retried: int, message: string }

GET /api/ops/pipeline/toggle

Get the current pipeline enabled/disabled state.

  • Response: { pipeline_enabled: bool }

POST /api/ops/pipeline/toggle

Toggle the pipeline on or off.

  • Body: { enabled: bool }
  • Response: { pipeline_enabled: bool, message: string }

GET /api/ops/sources/coverage-gaps

Identify symbols with missing or insufficient source coverage.

  • Response: { missing_source_types[], stale_sources[] }

1.14 System

GET /api/system/rate-limits

Current rate limit configuration and usage.

  • Response: { polygon_global_limit, polygon_source_types, per_type_limits, cadences_seconds, market_api: { rate_per_minute, cadence_seconds, max_tickers_per_cycle, active_sources }, news_api: {...} }

1.15 Analytics

POST /api/analytics/query

Proxy SQL to Trino with row limits.

  • Body: { sql: string, limit?: int (default 1000, max 10000) }
  • Response: { columns[], rows[][], row_count, elapsed_ms }
  • Errors: 400 — Empty SQL; 502 — Trino connection error; 504 — Trino timeout

GET /api/analytics/schema

Trino catalog/schema/table/column metadata for the schema browser.

  • Response: { catalog, schema, tables[{ name, columns[{ name, type }] }] }

GET /api/analytics/pg-schema

PostgreSQL table/column metadata with primary keys, foreign keys, and row estimates.

  • Response: { catalog: "postgresql", schema: "public", tables[] }

POST /api/analytics/pg-query

Run read-only SQL against PostgreSQL directly. Only SELECT statements allowed.

  • Body: { sql: string, limit?: int (default 1000, max 10000) }
  • Response: { columns[], rows[][], row_count, elapsed_ms }
  • Errors: 400 — Non-SELECT query, syntax error, table not found, or query error

GET /api/analytics/saved-queries

List all saved queries.

POST /api/analytics/saved-queries (201)

Save a new query.

  • Body: { name: string, description?: string, sql_text: string }

DELETE /api/analytics/saved-queries/{query_id}

Delete a saved query.

  • Errors: 404 — Query not found

1.16 Macro Signal Layer

GET /api/admin/macro/status

Return the current macro signal layer enabled/disabled state.

  • Response: { macro_enabled: bool, source: "default" | "risk_configs" }

PUT /api/admin/macro/toggle

Toggle the macro signal layer on or off. Records an audit event.

  • Body: { enabled: bool, operator?: string (default "operator") }
  • Response: { macro_enabled, previous_enabled, toggled_by }

1.17 Macro Events and Impacts

GET /api/macro/events

List recent global events with filtering.

Parameter Type Default Constraints Description
severity string Filter by severity
region string Filter by affected region
sector string Filter by affected sector
since string ISO 8601 Events after this time
until string ISO 8601 Events before this time
limit int 50 max 200 Page size
offset int 0 Pagination offset

GET /api/macro/events/{event_id}

Event detail with affected companies and macro impact scores.

  • Errors: 404 — Global event not found

GET /api/macro/impacts/{ticker}

Macro impacts and exposure profile for a specific company.

Parameter Type Default Constraints Description
since string ISO 8601 Impacts after this time
limit int 50 max 200 Page size
offset int 0 Pagination offset
  • Response: { exposure_profile, impacts[] }

1.18 Competitive Signal Layer

GET /api/admin/competitive/status

Return the current competitive signal layer enabled/disabled state.

  • Response: { competitive_enabled: bool, source: "default" | "risk_configs" }

PUT /api/admin/competitive/toggle

Toggle the competitive signal layer on or off. Records an audit event.

  • Body: { enabled: bool, operator?: string (default "operator") }
  • Response: { competitive_enabled, previous_enabled, toggled_by }

1.19 Patterns and Competitive Signals

GET /api/patterns/{ticker}

Historical patterns for a company.

Parameter Type Default Description
catalyst_type string Filter by catalyst type
time_horizon string Filter by time horizon
  • Response: { ticker, patterns[], count }

GET /api/patterns/{ticker}/competitors

Cross-company patterns showing how this company's catalysts affected competitors.

Parameter Type Default Description
catalyst_type string Filter by catalyst type
time_horizon string Filter by time horizon
  • Response: { ticker, cross_company_patterns[], count }

GET /api/patterns/{ticker}/competitive-signals

Recent competitive signals targeting this company (limit 100).

  • Response: { ticker, competitive_signals[], count }

GET /api/patterns/{ticker}/decisions

Major corporate decision history with trend outcomes and pattern statistics.

Parameter Type Default Description
time_horizon string Filter by time horizon
  • Response: { ticker, decisions[], count } — each decision includes pattern_statistics[]

1.20 AI Agents

GET /api/agents

List all AI agent configurations.

Parameter Type Default Description
active_only bool false Only show active agents

GET /api/agents/{agent_id}

Get a single agent configuration.

  • Errors: 404 — Agent not found

POST /api/agents (201)

Create a new user-defined agent.

  • Body: AgentCreateBody
Field Type Default Description
name string Required
slug string auto-generated URL-safe identifier
purpose string "" Agent purpose
model_provider string "ollama" LLM provider
model_name string "llama3.1:8b" Model identifier
system_prompt string "" System prompt
user_prompt_template string "" User prompt template
prompt_version string "" Prompt version tag
schema_version string "1.0.0" Output schema version
temperature float 0.0 Sampling temperature
max_tokens int 32768 Max output tokens
timeout_seconds int 120 Request timeout
max_retries int 2 Max retry attempts

PUT /api/agents/{agent_id}

Update an agent configuration. Partial updates supported.

  • Body: AgentUpdateBody — all fields optional (same fields as create)
  • Errors: 400 — No fields to update; 404 — Agent not found

DELETE /api/agents/{agent_id}

Delete a user-created agent. System agents cannot be deleted.

  • Errors: 403 — Cannot delete system agents; 404 — Agent not found

GET /api/agents/{agent_id}/performance

Aggregated performance metrics for an agent.

Parameter Type Default Constraints Description
hours int 24 max 720 Time window
  • Response: { total_invocations, successes, failures, avg_duration_ms, p95_duration_ms, avg_confidence, avg_retries, total_input_tokens, total_output_tokens, success_rate }

GET /api/agents/{agent_id}/performance/history

Hourly performance time-series for an agent.

Parameter Type Default Constraints Description
hours int 24 max 720 Time window
  • Response: Array of { hour, invocations, successes, avg_duration_ms, avg_confidence }

1.21 Agent Variants

GET /api/agents/{agent_id}/variants

List all variants for an agent, ordered by created_at ascending.

GET /api/agents/{agent_id}/variants/{variant_id}

Get a single variant.

  • Errors: 404 — Variant not found

POST /api/agents/{agent_id}/variants (201)

Create a new variant for an agent.

  • Body: VariantCreateBody
Field Type Default Description
variant_name string Required
variant_slug string auto-generated URL-safe identifier
description string "" Variant description
model_provider string "ollama" LLM provider
model_name string Required. Model identifier
system_prompt string "" System prompt
user_prompt_template string "" User prompt template
prompt_version string "" Prompt version tag
temperature float 0.0 Sampling temperature
max_tokens int 32768 Max output tokens
context_window int 0 Context window size
input_token_limit int 0 Input token limit
token_budget int 0 Token budget
timeout_seconds int 120 Request timeout
max_retries int 2 Max retry attempts
  • Errors: 409 — Duplicate variant slug

PUT /api/agents/{agent_id}/variants/{variant_id}

Partial update a variant.

  • Body: VariantUpdateBody — all fields optional
  • Errors: 400 — No fields to update; 404 — Variant not found

DELETE /api/agents/{agent_id}/variants/{variant_id}

Delete a variant. Cannot delete active variants.

  • Errors: 400 — Cannot delete active variant; 404 — Variant not found

POST /api/agents/{agent_id}/clone (201)

Clone an agent's configuration as a new variant with optional overrides.

  • Body: VariantCloneBody { variant_name, variant_slug?, ...optional overrides }
  • Errors: 404 — Agent not found; 409 — Duplicate slug

POST /api/agents/{agent_id}/variants/{variant_id}/clone (201)

Clone an existing variant as a new variant with optional overrides.

  • Body: VariantCloneBody
  • Errors: 404 — Source variant not found; 409 — Duplicate slug

POST /api/agents/{agent_id}/variants/{variant_id}/activate

Set a variant as the active variant for its agent. Deactivates any currently active variant in a transaction.

  • Errors: 404 — Variant not found

POST /api/agents/{agent_id}/variants/deactivate

Deactivate the currently active variant. Agent falls back to base configuration.

GET /api/agents/{agent_id}/variants/{variant_id}/performance

Aggregated performance metrics for a specific variant.

Parameter Type Default Constraints Description
hours int 24 max 720 Time window

GET /api/agents/{agent_id}/variants/{variant_id}/performance/history

Hourly performance time-series for a specific variant.

Parameter Type Default Constraints Description
hours int 24 max 720 Time window

2. Symbol Registry API

Source: services/symbol_registry/app.py with routers from exposure.py, competitors.py, competitor_inference.py

2.1 Health

GET /health

Liveness probe. Verifies database connectivity.

  • Response: {"status": "ok"}
  • Errors: 503 — Database unavailable

2.2 Companies

POST /companies (201)

Create a new tracked company.

  • Body: CompanyCreate
Field Type Default Constraints Description
ticker string 110 uppercase letters Required. Stock ticker
legal_name string Required. Company name
exchange string null Stock exchange
sector string null Sector classification
industry string null Industry classification
market_cap_bucket string null Market cap bucket
  • Response: CompanyResponse { id, ticker, legal_name, exchange, sector, industry, market_cap_bucket, active }
  • Errors: 409 — Company already exists; 422 — Invalid ticker format

GET /companies

List tracked companies.

Parameter Type Default Description
active bool true Filter by active status
  • Response: Array of CompanyResponse

GET /companies/{company_id}

Get a single company.

  • Errors: 404 — Company not found

PUT /companies/{company_id}

Update a company.

  • Body: CompanyCreate (same as create)
  • Errors: 404 — Company not found

2.3 Aliases

POST /companies/{company_id}/aliases (201)

Add an alias for a company.

  • Body: { alias: string, alias_type?: string (default "brand") }
  • Response: { id, alias, alias_type }

GET /companies/{company_id}/aliases

List aliases for a company.

  • Response: Array of { id, alias, alias_type }

2.4 Watchlists

POST /watchlists (201)

Create a new watchlist.

  • Body: { name: string, description?: string }
  • Errors: 409 — Watchlist name already exists

GET /watchlists

List all watchlists.

POST /watchlists/{watchlist_id}/members/{company_id} (201)

Add a company to a watchlist.

  • Errors: 409 — Already a member; 404 — Watchlist or company not found

GET /watchlists/{watchlist_id}/members

List companies in a watchlist.

  • Response: Array of CompanyResponse

2.5 Sources

POST /companies/{company_id}/sources (201)

Add a data source for a company.

  • Body: SourceCreate
Field Type Default Constraints Description
source_type string market_api, news_api, filings_api, web_scrape, broker Required
source_name string Required
config dict {} URLs validated for base_url Source configuration
credibility_score float 0.5 Source credibility
retention_days int 365 Data retention period
access_policy string "internal" internal, public, restricted Access policy
  • Errors: 404 — Company not found; 422 — Invalid source_type or access_policy

GET /companies/{company_id}/sources

List sources for a company.

2.6 Exposure Profiles

GET /companies/{company_id}/exposure

Get the current active exposure profile for a company.

  • Response: ExposureProfileResponse { id, company_id, geographic_revenue_mix, supply_chain_regions, key_input_commodities, regulatory_jurisdictions, market_position_tier, export_dependency_pct, source, confidence, version, active, created_at, updated_at }
  • Errors: 404 — No active exposure profile found

PUT /companies/{company_id}/exposure

Create or update an exposure profile. Archives the previous active version.

  • Body: ExposureProfileCreate
Field Type Default Constraints Description
geographic_revenue_mix dict[str, float] {} Region to revenue percentage
supply_chain_regions list[str] [] Supply chain regions
key_input_commodities list[str] [] Key input commodities
regulatory_jurisdictions list[str] [] Regulatory jurisdictions
market_position_tier string "regional" global_leader, multinational, regional, domestic Market position
export_dependency_pct float 0.0 0.01.0 Export dependency
source string "manual" manual, inferred Data source
confidence float 1.0 0.01.0 Confidence score
  • Errors: 404 — Company not found

GET /companies/{company_id}/exposure/history

Get all exposure profile versions for a company, ordered by version descending.

2.7 Competitor Relationships

POST /companies/{company_id}/competitors (201)

Create a competitor relationship. Records an audit event.

  • Body: CompetitorRelationshipCreate
Field Type Default Constraints Description
company_b_id string UUID Required. Other company
relationship_type string direct_rival, same_sector, overlapping_products, supply_chain_adjacent Required
strength float 0.5 01 Relationship strength
bidirectional bool true Bidirectional relationship
source string "manual" manual, inferred Data source
  • Errors: 400 — Self-reference; 404 — Company not found; 409 — Relationship already exists

GET /companies/{company_id}/competitors

List active competitor relationships, enriched with ticker and legal_name of the other company.

  • Errors: 404 — Company not found

PUT /companies/{company_id}/competitors/{relationship_id}

Update a competitor relationship. Records an audit event with previous state.

  • Body: CompetitorRelationshipCreate
  • Errors: 404 — Relationship not found

DELETE /companies/{company_id}/competitors/{relationship_id}

Soft-delete a competitor relationship (sets active=false). Records an audit event.

  • Errors: 404 — Active relationship not found

2.8 Competitor Inference

POST /companies/{company_id}/competitors/infer

Auto-infer competitor relationships based on sector/industry match and document co-mention frequency.

Strength formula: 0.3 * sector_match + 0.7 * normalized_co_mention_count

Upserts relationships with source='inferred' and relationship_type='same_sector'.

  • Response: Array of CompetitorRelationship objects sorted by strength descending
  • Errors: 400 — Company missing sector or industry; 404 — Company not found

3. Trading Engine API

Source: services/trading/app.py

3.1 Health and Readiness

GET /health

Liveness probe.

  • Response: {"status": "ok"}

GET /ready

Readiness probe — reports whether the engine is running.

  • Response: {"ready": bool}

3.2 Debug

GET /api/trading/debug

Diagnostic endpoint showing engine internals for troubleshooting.

  • Response: { running, has_pool, has_redis, config_enabled, polling_interval, last_poll, portfolio_state: { active_pool, reserve_pool, total_value, open_positions }, risk_tier, tasks, processed_rec_count }

3.3 Engine Status and Control

GET /api/trading/status

Return current engine state.

  • Response: { enabled, paused, risk_tier, circuit_breaker_status, active_pool, reserve_pool, portfolio_heat, open_positions, last_decision_at }
  • Errors: 503 — Engine not initialised

PUT /api/trading/config

Update trading engine configuration. Returns previous and new values for audit trail.

  • Body: ConfigUpdateRequest
Field Type Description
enabled bool Enable/disable engine
risk_tier string Risk tier level
reserve_siphon_pct float Reserve pool siphon percentage
polling_interval_seconds int Polling interval
absolute_position_cap float Max position value
active_pool_minimum float Minimum active pool
micro_trading_enabled bool Enable micro trades
max_open_positions int Max concurrent positions

All fields optional. Only provided fields are updated.

  • Response: { previous, updated, change_source: "api", changed_at }
  • Errors: 503 — Engine not initialised

POST /api/trading/pause

Pause the trading engine.

  • Response: {"paused": true}

POST /api/trading/resume

Resume the trading engine.

  • Response: {"paused": false}

POST /api/trading/reset

Full paper trading reset: liquidate broker positions, cancel orders, clear trading state, reset capital.

  • Body: { initial_capital?: float (default 0.0) } — if 0, uses broker balance or defaults to 100,000
  • Response: { reset: true, initial_capital, active_pool, reserve_pool, broker: { orders_cancelled, positions_closed, portfolio_value, cash, buying_power } }
  • Errors: 503 — Engine not initialised; 500 — Database reset failed

3.4 Decision Audit Trail

GET /api/trading/decisions

Return recent trading decisions from the database.

Parameter Type Default Constraints Description
ticker string Filter by ticker
decision string Filter by decision type
is_micro_trade bool Filter micro trades
limit int 50 max 200 Page size
offset int 0 Pagination offset

3.5 Performance Metrics

GET /api/trading/metrics

Return current performance metrics.

  • Response: { total_portfolio_value, active_pool, reserve_pool, unrealized_pnl, realized_pnl, daily_pnl, win_rate, profit_factor, sharpe_ratio, max_drawdown, portfolio_heat }
  • Errors: 503 — Engine not initialised

GET /api/trading/metrics/history

Return historical daily portfolio snapshots.

Parameter Type Default Constraints Description
limit int 30 max 365 Max snapshots

3.6 Backtesting

POST /api/trading/backtest

Launch a backtest run asynchronously.

  • Body: BacktestRequest
Field Type Default Description
start_date string Required. ISO date (YYYY-MM-DD)
end_date string Required. ISO date (YYYY-MM-DD)
initial_capital float 500.0 Starting capital
risk_tier string "moderate" Risk tier for backtest
  • Response: { id: string, status: "running" }
  • Errors: 503 — Engine not initialised

GET /api/trading/backtest/{backtest_id}

Retrieve backtest results.

  • Response: { id, start_date, end_date, initial_capital, risk_tier, config, total_return, sharpe_ratio, max_drawdown, win_rate, profit_factor, trade_count, equity_curve[], trades[], status, completed_at, created_at }
  • Status values: running, completed, not_found, pending

3.7 Notifications

GET /api/trading/notifications/config

Return current notification configuration.

  • Response: { sms_enabled, email_enabled, phone_number, email_recipient }
  • Errors: 503 — Engine not initialised

PUT /api/trading/notifications/config

Update notification preferences.

  • Body: NotificationConfigRequest
Field Type Description
sms_enabled bool Enable SMS notifications
email_enabled bool Enable email notifications
phone_number string SMS phone number
email_recipient string Email recipient address

All fields optional.

  • Errors: 503 — Engine not initialised

GET /api/trading/notifications/history

Return recent notifications.

Parameter Type Default Constraints Description
limit int 50 max 200 Max results

3.8 Override Orders

POST /api/trading/override/order (202)

Submit a manual override order to the broker queue. Auto-registers untracked tickers in the Symbol Registry.

  • Body: OverrideOrderRequest
Field Type Default Constraints Description
ticker string 110 alphabetic chars Required. Stock ticker
side string buy or sell Required. Order side
quantity float Must be positive Required. Share quantity
order_type string "market" market, limit, stop, stop_limit Order type
limit_price float null Required for limit/stop_limit Limit price
stop_price float null Required for stop/stop_limit Stop price
  • Response: OverrideOrderResponse { job_id, status: "queued", ticker, side, quantity, auto_registered }
  • Errors: 503 — Engine not initialised or broker queue unavailable; 422 — Validation errors

4. Risk Engine API

Source: services/risk/app.py

4.1 Health

GET /health

Liveness probe.

  • Response: {"status": "ok"}

4.2 Order Evaluation

POST /evaluate

Evaluate a proposed order against risk rules.

  • Body: EvaluateRequest
Field Type Description
order ProposedOrder Required. The order to evaluate
config PortfolioRiskConfig Optional. Risk config (uses defaults if null)
state AccountRiskState Optional. Current account state

ProposedOrder schema:

Field Type Default Description
recommendation_id string null Source recommendation
ticker string Required. Stock ticker
sector string "" Company sector
action string "buy" buy or sell
quantity float 0.0 Share quantity
estimated_value float 0.0 Estimated order value
confidence float 0.0 Recommendation confidence
  • Response: RiskEvaluation { evaluation_id, recommendation_id, ticker, eligible, allowed_mode, checks[], rejection_reasons[], config_snapshot, state_snapshot, evaluated_at }

4.3 Approvals

GET /approvals/pending

List pending approval requests.

  • Response: Array of approval request objects (serialized via to_dict())
  • Errors: 503 — Database not ready

GET /approvals/{approval_id}

Get a single approval request.

  • Errors: 404 — Approval not found; 503 — Database not ready

POST /approvals/{approval_id}/review

Approve or reject a pending approval request.

  • Body: ReviewRequest
Field Type Default Description
approved bool Required. Approve or reject
reviewed_by string "operator" Reviewer identity
review_note string "" Optional review note
  • Response: { approval_id, status }
  • Errors: 404 — Approval not found or no longer pending; 503 — Database not ready

4.4 Approval Expiration

POST /approvals/expire

Expire stale approvals that have passed their expiration time.

  • Response: { expired: int, items: [] }
  • Errors: 503 — Database not ready