Developer referenceOpenAPI 3.1.0

SignalForge API

Versioned financial-intelligence infrastructure API for explainable signals, rankings, ticker theses, normalized evidence, provider/readiness metadata, and derived research context.

Quick Start

1

Sign in to the dashboard.

2

Create an organization API key.

3

Copy the one-time secret.

4

Send a first request with x-api-key or Authorization: Bearer.

5

Read a ticker thesis.

6

Inspect evidence IDs from the response.

7

Check provider and readiness status.

8

Keep beta data limitations visible downstream.

Authentication

Customer API requests accept x-api-key or Authorization: Bearer. Dashboard routes use Supabase Auth cookies.

Rate Limits

API responses include x-ratelimit-limit, x-ratelimit-remaining, x-ratelimit-reset, x-ratelimit-plan, and x-request-id.

Data Boundary

SignalForge returns derived intelligence, normalized evidence summaries, readiness metadata, and usage data. Raw vendor payloads and secrets stay server-side.

curl
curl "https://api.bennbots.com/v1/tickers/MSFT/thesis" \
  -H "x-api-key: sf_live_example_1234567890"
TypeScript
const response = await fetch(
  "https://api.bennbots.com/v1/tickers/MSFT/thesis",
  {
    headers: {
      "Authorization": "Bearer sf_live_example_1234567890"
    }
  }
);

if (!response.ok) {
  throw new Error(`SignalForge request failed: ${response.status}`);
}

const { data, meta } = await response.json();
Python
import requests

response = requests.get(
    "https://api.bennbots.com/v1/evidence/ev_d4db7f1d420ba224",
    headers={"x-api-key": "sf_live_example_1234567890"},
    timeout=20,
)
response.raise_for_status()
payload = response.json()

System

GET/api/v1/health

Check API health

Production

Auth

Public

Scopes

None

Surface

Public customer API

Secret-safe service liveness only.

Responses
StatusDescriptionSchema
200Service is available.HealthEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/health
{
  "data": {
    "ok": true,
    "service": "SignalForge API",
    "version": "v1",
    "checked_at": "2026-06-27T19:30:00.000Z",
    "environment": "production",
    "data_mode": "live",
    "mock_data_enabled": false,
    "live_sources_configured": true,
    "missing_required_config": []
  },
  "meta": {
    "environment": "production",
    "data_mode": "live",
    "mock_data": false,
    "api_version": "v1",
    "request_id": "7e2f27ef-7848-47a4-8dd3-c6f5bcab0035",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}
GET/api/v1/health/readiness

Check production readiness and data freshness

Combines API liveness, Supabase reachability, provider status, latest ingestion status, source mix, provider issues, and data freshness into a production-safe readiness verdict.

Production

Auth

Public

Scopes

None

Surface

Public customer API

Secret-safe readiness and freshness metadata only.

Responses
StatusDescriptionSchema
200Production is ready or degraded but still serving.ReadinessEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
503A critical dependency or freshness invariant is unavailable.ReadinessEnvelope
Example response
GET /api/v1/health/readiness
{
  "data": {
    "status": "ready",
    "checked_at": "2026-06-27T19:30:00.000Z",
    "environment": "production",
    "supabase_configured": true,
    "components": [
      {
        "name": "api",
        "status": "ok",
        "message": "API is serving requests."
      }
    ],
    "counts": {
      "daily_rankings": 25,
      "ingestion_runs": 14,
      "macro_snapshots": 1,
      "news_mentions": 240,
      "signals": 125,
      "source_records": 620
    },
    "latest_ingestion_run": null,
    "latest_source_mix": null,
    "freshness": [],
    "provider_status": [],
    "recent_provider_issues": [],
    "thresholds": {
      "ingestion_run_minutes": 180,
      "running_ingestion_minutes": 30,
      "signals_minutes": 1440,
      "daily_rankings_minutes": 1440,
      "macro_snapshot_minutes": 2880,
      "news_mentions_minutes": 720
    }
  },
  "meta": {
    "api_version": "v1",
    "request_id": "7e2f27ef-7848-47a4-8dd3-c6f5bcab0035",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}
GET/api/v1/providers/status

List configured normalized data providers

Production

Auth

API key

Scopes

signals:read

Surface

Public customer API

Shows provider names, selected adapters, capabilities, and missing configuration names only; never secret values.

Responses
StatusDescriptionSchema
200Provider names, selected adapters, missing config variable names, mock status, and capabilities; never secret values.ProviderStatusEnvelope
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/providers/status
{
  "data": [
    {
      "category": "market",
      "provider": "mock_market",
      "configured": false,
      "using_mock": true,
      "selected_provider": "fmp",
      "missing_config": [
        "FMP_API_KEY"
      ],
      "capabilities": [
        "profiles",
        "prices",
        "earnings",
        "analysts",
        "financials"
      ]
    }
  ],
  "meta": {
    "api_version": "v1",
    "request_id": "7e2f27ef-7848-47a4-8dd3-c6f5bcab0035",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}
GET/api/v1/ingestion/status

Inspect ingestion readiness and recent provider issues

Returns storage mode, persisted intelligence counts, latest ingestion run metadata, and sanitized provider fallback messages.

Beta

Auth

API key

Scopes

signals:read

Surface

Public customer API

Operational status is sanitized and does not include provider secrets or raw payloads.

Responses
StatusDescriptionSchema
200Ingestion and provider readiness status.object { data, meta }
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/ingestion/status
{
  "data": {
    "serving_mode": "bundled_fallback",
    "supabase_configured": false,
    "using_fallback": true,
    "fallback_reason": "local_development_files",
    "counts": {
      "daily_rankings": 25,
      "ingestion_runs": 4,
      "macro_observations": 12,
      "macro_snapshots": 1,
      "news_mentions": 90,
      "signals": 120,
      "source_records": 400
    },
    "latest_ingestion_run": null,
    "latest_source_mix": null,
    "recent_provider_issues": [],
    "runtime_config": {
      "environment": "development",
      "mock_fallback_enabled": true,
      "dev_tools_enabled": false,
      "secret_status": {
        "cron_secret_configured": false,
        "dashboard_api_key_configured": false,
        "supabase_service_key_configured": false
      },
      "cron": {
        "configured": false,
        "jobs": []
      },
      "gdelt": {
        "base_url_host": "api.gdeltproject.org/api/v2",
        "request_delay_ms": {
          "value": 10000,
          "source": "default"
        },
        "max_retries": {
          "value": 0,
          "source": "default"
        },
        "retry_delay_ms": {
          "value": 5500,
          "source": "default"
        },
        "news_burst_limit": {
          "value": 25,
          "source": "default"
        },
        "cooldown_minutes": {
          "value": 360,
          "source": "default"
        },
        "request_limit_posture": "gentle"
      },
      "sec": {
        "request_delay_ms": {
          "value": 100,
          "source": "default"
        },
        "max_retries": {
          "value": 2,
          "source": "default"
        },
        "retry_delay_ms": {
          "value": 500,
          "source": "default"
        },
        "cooldown_minutes": {
          "value": 10,
          "source": "default"
        },
        "request_limit_posture": "gentle"
      },
      "safe_config_hints": []
    }
  },
  "meta": {
    "api_version": "v1",
    "request_id": "7e2f27ef-7848-47a4-8dd3-c6f5bcab0035",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}

Signals

GET/api/v1/signals

List recent signals

Production

Auth

API key

Scopes

signals:read

Surface

Public customer API

Returns derived intelligence and normalized summaries only; raw vendor payloads and secrets are not exposed.

Parameters
NameInRequiredSchema
tickerqueryNostring
signal_typequeryNoSignalType
sourcequeryNostring
min_scorequeryNonumber
from_datequeryNostring
to_datequeryNostring
limitqueryNointeger
Responses
StatusDescriptionSchema
200Matching signalsobject { data, meta }
400Malformed request, invalid JSON, or invalid query parameter.ErrorEnvelope
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/signals
{
  "data": [
    {
      "id": "sig_429498d6dba2ffc6",
      "ticker": "AMD",
      "signal_type": "earnings_momentum",
      "score": 80,
      "confidence": 0.4,
      "reason": "AMD reports FY2026 Q2 earnings in 6 days; fundamental momentum inputs are pending.",
      "event_date": "2026-07-01",
      "generated_at": "2026-06-25T16:35:16.302Z",
      "effective_at": "2026-06-25T23:59:59.999Z",
      "as_of": "2026-06-25",
      "scoring_version": "2026-06-20.v1",
      "input_hash": "9b0502e5ef6ffe3f",
      "coverage": 0.1,
      "score_components": {
        "eps_surprise": 0,
        "revenue_surprise": 0,
        "estimate_revisions": 0,
        "guidance": 0,
        "event_recency": 80
      },
      "score_explanation": "Score 80 is a bounded 0-100 weighted blend led by event recency, with 10% input coverage. 4 components lacked enough data and contributed 0.",
      "components": [
        {
          "key": "eps_surprise",
          "label": "EPS surprise",
          "raw_value": null,
          "normalized_score": 0,
          "weight": 0.3,
          "contribution": 0,
          "reason_code": "EPS_SURPRISE_UNAVAILABLE"
        },
        {
          "key": "event_recency",
          "label": "Event recency",
          "raw_value": 6,
          "normalized_score": 80,
          "weight": 0.1,
          "contribution": 8,
          "reason_code": "EARNINGS_RECENCY"
        }
      ],
      "source_names": [
        "mock_market"
      ],
      "source_event_ids": [
        "raw_earnings_amd_1"
      ],
      "evidence_ids": [
        "ev_bed10e9ca24a8eda"
      ],
      "evidence_status": "available",
      "source_lineage": [
        {
          "evidence_id": "ev_bed10e9ca24a8eda",
          "provider": "mock_market",
          "source_type": "earnings",
          "source_url": null,
          "external_id": "raw_earnings_amd_1",
          "observed_at": "2026-06-25T16:35:16.301Z",
          "event_date": "2026-07-01",
          "ticker": "AMD",
          "company_name": null,
          "summary": "AMD earnings event for FY2026 Q2 expected 2026-07-01.",
          "confidence": 0.55,
          "source_quality": "mock"
        }
      ],
      "metadata": {
        "fiscal_period": "FY2026 Q2",
        "data_status": "scheduled"
      }
    }
  ],
  "meta": {
    "count": 1,
    "api_version": "v1",
    "request_id": "16b263fb-0be4-4239-a732-0dfec5b3dd40",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}
GET/api/v1/signals/{id}

Get a signal

Production

Auth

API key

Scopes

signals:read

Surface

Public customer API

Returns derived intelligence and normalized summaries only; raw vendor payloads and secrets are not exposed.

Parameters
NameInRequiredSchema
idpathYesstring
Responses
StatusDescriptionSchema
200Signal details.object { data, meta }
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
404Signal lookup miss. This route currently returns an API envelope with a 404 status.LookupNotFoundEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/signals/{id}
{
  "data": {
    "id": "sig_429498d6dba2ffc6",
    "ticker": "AMD",
    "signal_type": "earnings_momentum",
    "score": 80,
    "confidence": 0.4,
    "reason": "AMD reports FY2026 Q2 earnings in 6 days; fundamental momentum inputs are pending.",
    "event_date": "2026-07-01",
    "generated_at": "2026-06-25T16:35:16.302Z",
    "effective_at": "2026-06-25T23:59:59.999Z",
    "as_of": "2026-06-25",
    "scoring_version": "2026-06-20.v1",
    "input_hash": "9b0502e5ef6ffe3f",
    "coverage": 0.1,
    "score_components": {
      "eps_surprise": 0,
      "revenue_surprise": 0,
      "estimate_revisions": 0,
      "guidance": 0,
      "event_recency": 80
    },
    "score_explanation": "Score 80 is a bounded 0-100 weighted blend led by event recency, with 10% input coverage. 4 components lacked enough data and contributed 0.",
    "components": [
      {
        "key": "eps_surprise",
        "label": "EPS surprise",
        "raw_value": null,
        "normalized_score": 0,
        "weight": 0.3,
        "contribution": 0,
        "reason_code": "EPS_SURPRISE_UNAVAILABLE"
      },
      {
        "key": "event_recency",
        "label": "Event recency",
        "raw_value": 6,
        "normalized_score": 80,
        "weight": 0.1,
        "contribution": 8,
        "reason_code": "EARNINGS_RECENCY"
      }
    ],
    "source_names": [
      "mock_market"
    ],
    "source_event_ids": [
      "raw_earnings_amd_1"
    ],
    "evidence_ids": [
      "ev_bed10e9ca24a8eda"
    ],
    "evidence_status": "available",
    "source_lineage": [
      {
        "evidence_id": "ev_bed10e9ca24a8eda",
        "provider": "mock_market",
        "source_type": "earnings",
        "source_url": null,
        "external_id": "raw_earnings_amd_1",
        "observed_at": "2026-06-25T16:35:16.301Z",
        "event_date": "2026-07-01",
        "ticker": "AMD",
        "company_name": null,
        "summary": "AMD earnings event for FY2026 Q2 expected 2026-07-01.",
        "confidence": 0.55,
        "source_quality": "mock"
      }
    ],
    "metadata": {
      "fiscal_period": "FY2026 Q2",
      "data_status": "scheduled"
    }
  },
  "meta": {
    "api_version": "v1",
    "request_id": "7e2f27ef-7848-47a4-8dd3-c6f5bcab0035",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}
GET/api/v1/tickers/{ticker}/signals

List signals for a ticker

Production

Auth

API key

Scopes

signals:read

Surface

Public customer API

Returns derived intelligence and normalized summaries only; raw vendor payloads and secrets are not exposed.

Parameters
NameInRequiredSchema
tickerpathYesstring
Responses
StatusDescriptionSchema
200Ticker signals.object { data, meta }
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/tickers/{ticker}/signals
{
  "data": [
    {
      "id": "sig_429498d6dba2ffc6",
      "ticker": "AMD",
      "signal_type": "earnings_momentum",
      "score": 80,
      "confidence": 0.4,
      "reason": "AMD reports FY2026 Q2 earnings in 6 days; fundamental momentum inputs are pending.",
      "event_date": "2026-07-01",
      "generated_at": "2026-06-25T16:35:16.302Z",
      "effective_at": "2026-06-25T23:59:59.999Z",
      "as_of": "2026-06-25",
      "scoring_version": "2026-06-20.v1",
      "input_hash": "9b0502e5ef6ffe3f",
      "coverage": 0.1,
      "score_components": {
        "eps_surprise": 0,
        "revenue_surprise": 0,
        "estimate_revisions": 0,
        "guidance": 0,
        "event_recency": 80
      },
      "score_explanation": "Score 80 is a bounded 0-100 weighted blend led by event recency, with 10% input coverage. 4 components lacked enough data and contributed 0.",
      "components": [
        {
          "key": "eps_surprise",
          "label": "EPS surprise",
          "raw_value": null,
          "normalized_score": 0,
          "weight": 0.3,
          "contribution": 0,
          "reason_code": "EPS_SURPRISE_UNAVAILABLE"
        },
        {
          "key": "event_recency",
          "label": "Event recency",
          "raw_value": 6,
          "normalized_score": 80,
          "weight": 0.1,
          "contribution": 8,
          "reason_code": "EARNINGS_RECENCY"
        }
      ],
      "source_names": [
        "mock_market"
      ],
      "source_event_ids": [
        "raw_earnings_amd_1"
      ],
      "evidence_ids": [
        "ev_bed10e9ca24a8eda"
      ],
      "evidence_status": "available",
      "source_lineage": [
        {
          "evidence_id": "ev_bed10e9ca24a8eda",
          "provider": "mock_market",
          "source_type": "earnings",
          "source_url": null,
          "external_id": "raw_earnings_amd_1",
          "observed_at": "2026-06-25T16:35:16.301Z",
          "event_date": "2026-07-01",
          "ticker": "AMD",
          "company_name": null,
          "summary": "AMD earnings event for FY2026 Q2 expected 2026-07-01.",
          "confidence": 0.55,
          "source_quality": "mock"
        }
      ],
      "metadata": {
        "fiscal_period": "FY2026 Q2",
        "data_status": "scheduled"
      }
    }
  ],
  "meta": {
    "count": 1,
    "api_version": "v1",
    "request_id": "16b263fb-0be4-4239-a732-0dfec5b3dd40",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}
GET/api/v1/news-bursts

List derived abnormal news-coverage signals

Beta

Auth

API key

Scopes

signals:read

Surface

Public customer API

Returns derived intelligence and normalized summaries only; raw vendor payloads and secrets are not exposed.

Parameters
NameInRequiredSchema
limitqueryNointeger
Responses
StatusDescriptionSchema
200Recent news burst signals.object { data, meta }
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/news-bursts
{
  "data": [
    {
      "id": "sig_news_burst_msft",
      "ticker": "AMD",
      "signal_type": "news_burst",
      "score": 80,
      "confidence": 0.4,
      "reason": "MSFT coverage is elevated relative to its recent baseline.",
      "event_date": "2026-07-01",
      "generated_at": "2026-06-25T16:35:16.302Z",
      "effective_at": "2026-06-25T23:59:59.999Z",
      "as_of": "2026-06-25",
      "scoring_version": "2026-06-20.v1",
      "input_hash": "9b0502e5ef6ffe3f",
      "coverage": 0.1,
      "score_components": {
        "eps_surprise": 0,
        "revenue_surprise": 0,
        "estimate_revisions": 0,
        "guidance": 0,
        "event_recency": 80
      },
      "score_explanation": "Score 80 is a bounded 0-100 weighted blend led by event recency, with 10% input coverage. 4 components lacked enough data and contributed 0.",
      "components": [
        {
          "key": "eps_surprise",
          "label": "EPS surprise",
          "raw_value": null,
          "normalized_score": 0,
          "weight": 0.3,
          "contribution": 0,
          "reason_code": "EPS_SURPRISE_UNAVAILABLE"
        },
        {
          "key": "event_recency",
          "label": "Event recency",
          "raw_value": 6,
          "normalized_score": 80,
          "weight": 0.1,
          "contribution": 8,
          "reason_code": "EARNINGS_RECENCY"
        }
      ],
      "source_names": [
        "mock_market"
      ],
      "source_event_ids": [
        "raw_earnings_amd_1"
      ],
      "evidence_ids": [
        "ev_bed10e9ca24a8eda"
      ],
      "evidence_status": "available",
      "source_lineage": [
        {
          "evidence_id": "ev_bed10e9ca24a8eda",
          "provider": "mock_market",
          "source_type": "earnings",
          "source_url": null,
          "external_id": "raw_earnings_amd_1",
          "observed_at": "2026-06-25T16:35:16.301Z",
          "event_date": "2026-07-01",
          "ticker": "AMD",
          "company_name": null,
          "summary": "AMD earnings event for FY2026 Q2 expected 2026-07-01.",
          "confidence": 0.55,
          "source_quality": "mock"
        }
      ],
      "metadata": {
        "fiscal_period": "FY2026 Q2",
        "data_status": "scheduled"
      }
    }
  ],
  "meta": {
    "count": 1,
    "api_version": "v1",
    "request_id": "7e2f27ef-7848-47a4-8dd3-c6f5bcab0035",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}

Rankings

GET/api/v1/rankings/daily

List current daily ticker rankings

Production

Auth

API key

Scopes

signals:read

Surface

Public customer API

Returns derived intelligence and normalized summaries only; raw vendor payloads and secrets are not exposed.

Responses
StatusDescriptionSchema
200Daily rankings.object { data, meta }
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/rankings/daily
{
  "data": [
    {
      "id": "rank_20260627_msft",
      "ranking_date": "2026-06-27",
      "rank": 1,
      "ticker": "MSFT",
      "score": 82,
      "signal_count": 5,
      "primary_signal_types": [
        "price_momentum",
        "analyst_momentum"
      ],
      "reason_summary": "MSFT leads current rankings on price momentum and analyst revisions.",
      "generated_at": "2026-06-27T12:00:00.000Z"
    }
  ],
  "meta": {
    "count": 1,
    "generated_at": "2026-06-27T12:00:00.000Z",
    "api_version": "v1",
    "request_id": "7e2f27ef-7848-47a4-8dd3-c6f5bcab0035",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}

Research

GET/api/v1/evidence/{id}

Get normalized evidence for a signal input

Returns a safe, normalized evidence object with provider/source references and a human-readable summary. Raw vendor payloads remain server-side and are not redistributed.

Production

Auth

API key

Scopes

signals:read

Surface

Public customer API

Returns normalized evidence summaries and references, never raw vendor payloads.

Parameters
NameInRequiredSchema
idpathYesstring
Responses
StatusDescriptionSchema
200Normalized evidence details.object { data, meta }
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
404Evidence lookup miss. This route currently returns an API envelope with a 404 status.LookupNotFoundEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/evidence/{id}
{
  "data": {
    "id": "ev_bed10e9ca24a8eda",
    "provider": "mock_market",
    "source_type": "earnings",
    "source_url": null,
    "external_id": "raw_earnings_amd_1",
    "observed_at": "2026-06-25T16:35:16.301Z",
    "event_date": "2026-07-01",
    "ticker": "AMD",
    "company_name": null,
    "raw_payload_ref": {
      "source_record_id": "source_82bb7dff15edc7ad",
      "raw_event_id": "raw_earnings_amd_1",
      "content_hash": "c1c6a9f7254d9b4e"
    },
    "summary": "AMD earnings event for FY2026 Q2 expected 2026-07-01.",
    "confidence": 0.55,
    "source_quality": "mock",
    "metadata": {
      "event_type": "earnings_event",
      "source_record_type": "earnings",
      "is_mock": true
    }
  },
  "meta": {
    "api_version": "v1",
    "request_id": "9e89ce30-1ecf-4da6-867c-2f7475636c62",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}
GET/api/v1/signals/{id}/outcomes

List forward outcome windows for a signal

Returns 1, 5, 20, and 60 day signal outcome windows with pending, measured, or failed measurement status.

Beta

Auth

API key

Scopes

signals:read

Surface

Public customer API

Outcome windows are returned when measurement data exists; pending windows are explicit.

Parameters
NameInRequiredSchema
idpathYesstring
Responses
StatusDescriptionSchema
200Signal outcome status.object { data, meta }
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
404Resource not found.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/signals/{id}/outcomes
{
  "data": {
    "signal_id": "sig_429498d6dba2ffc6",
    "ticker": "AMD",
    "status": "pending",
    "supported_horizons_days": [
      1,
      5,
      20,
      60
    ],
    "outcomes": [
      {
        "id": "out_1d",
        "signal_id": "sig_429498d6dba2ffc6",
        "ticker": "AMD",
        "measured_at": null,
        "horizon_days": 1,
        "measurement_status": "pending",
        "baseline_price": null,
        "outcome_price": null,
        "return_pct": null,
        "benchmark_ticker": "SPY",
        "benchmark_return_pct": null,
        "excess_return_pct": null,
        "direction_correct": null,
        "error_message": null,
        "metadata": {}
      }
    ]
  },
  "meta": {
    "count": 4,
    "measured_count": 0,
    "pending_count": 4,
    "failed_count": 0,
    "api_version": "v1",
    "request_id": "7e2f27ef-7848-47a4-8dd3-c6f5bcab0035",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}
GET/api/v1/macro/context

Get the latest interpreted macro regime

Beta

Auth

API key

Scopes

signals:read

Surface

Public customer API

Returns derived intelligence and normalized summaries only; raw vendor payloads and secrets are not exposed.

Responses
StatusDescriptionSchema
200Derived macro context.object { data, meta }
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/macro/context
{
  "data": {
    "snapshot_date": "2026-06-27",
    "fed_funds_rate": 5.25,
    "treasury_2y": 4.7,
    "treasury_10y": 4.25,
    "yield_curve_10y_2y": -0.45,
    "inflation_rate": 3.1,
    "unemployment_rate": 4,
    "regime_label": "restrictive_policy",
    "summary": "Rates remain restrictive while labor data is stable.",
    "source_names": [
      "mock_macro"
    ]
  },
  "meta": {
    "api_version": "v1",
    "request_id": "7e2f27ef-7848-47a4-8dd3-c6f5bcab0035",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}
GET/api/v1/companies/{ticker}/agent-brief

Get an agent-ready structured company brief

Returns derived company intelligence for AI agents and developer workflows without redistributing raw vendor payloads.

Beta

Auth

API key

Scopes

signals:read

Surface

Public customer API

Agent Briefs are derived summaries for workflow automation and remain beta.

Parameters
NameInRequiredSchema
tickerpathYesstring
Responses
StatusDescriptionSchema
200Structured company agent brief.object { data, meta }
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/companies/{ticker}/agent-brief
{
  "data": {
    "ticker": "MSFT",
    "company": {
      "ticker": "MSFT",
      "company_name": "Microsoft Corporation",
      "company_id": "company_msft",
      "security_id": "security_msft",
      "exchange": "NASDAQ",
      "sector": "Technology",
      "industry": "Software Infrastructure"
    },
    "as_of": "2026-06-26T18:30:00.000Z",
    "machine_summary": {
      "ticker": "MSFT",
      "score": 36,
      "confidence": 0.76,
      "active_signal_count": 5,
      "primary_signal_types": [
        "price_momentum",
        "composite_signal",
        "analyst_momentum"
      ],
      "evidence_status": "available",
      "qa_status": "passed",
      "outcome_status": "pending_data"
    },
    "human_summary": "MSFT has 5 active derived signal(s), led by price_momentum, composite_signal, analyst_momentum.",
    "active_signals": [
      {
        "id": "sig_977db43b55ef57e1",
        "ticker": "MSFT",
        "signal_type": "price_momentum",
        "score": 74,
        "confidence": 0.76,
        "reason": "MSFT has 3.7% recent price momentum with 100% positive sessions.",
        "scoring_version": "2026-06-20.v1",
        "score_explanation": "Score 74 is a bounded 0-100 weighted blend led by trend consistency, drawdown control, return 20d, with 75% input coverage.",
        "evidence_ids": [
          "ev_d4db7f1d420ba224"
        ],
        "evidence_status": "available"
      }
    ],
    "why_now": [
      "MSFT has 3.7% recent price momentum with 100% positive sessions."
    ],
    "supporting_evidence": [
      {
        "evidence_id": "ev_d4db7f1d420ba224",
        "provider": "mock_market",
        "source_type": "price_bar",
        "source_url": null,
        "external_id": "price_8638f0279b38c5e1",
        "observed_at": "2026-06-25T16:35:16.301Z",
        "event_date": "2026-06-25",
        "ticker": "MSFT",
        "company_name": null,
        "summary": "MSFT price observation on 2026-06-25.",
        "confidence": 0.55,
        "source_quality": "mock"
      }
    ],
    "contradicting_evidence": [],
    "risk_flags": [
      "Market intelligence is informational only and not investment advice.",
      "Signals can decay quickly as new filings, prices, earnings, or news arrive."
    ],
    "source_lineage": [
      {
        "evidence_id": "ev_d4db7f1d420ba224",
        "provider": "mock_market",
        "source_type": "price_bar",
        "source_url": null,
        "external_id": "price_8638f0279b38c5e1",
        "observed_at": "2026-06-25T16:35:16.301Z",
        "event_date": "2026-06-25",
        "ticker": "MSFT",
        "company_name": null,
        "summary": "MSFT price observation on 2026-06-25.",
        "confidence": 0.55,
        "source_quality": "mock"
      }
    ],
    "confidence": 0.76,
    "freshness": {
      "generated_at": "2026-06-26T18:30:00.000Z",
      "as_of": "2026-06-26",
      "latest_signal_at": "2026-06-26T18:18:21.351Z",
      "latest_event_date": "2026-06-26",
      "signal_count": 5,
      "evidence_count": 5
    },
    "suggested_agent_tasks": [
      "Review source_lineage evidence summaries before using this brief downstream."
    ],
    "qa": {
      "qa_status": "passed",
      "qa_flags": [],
      "confidence_notes": "Deterministic QA found active signals with normalized supporting evidence; no AI review was run.",
      "reviewed_at": "2026-06-26T18:30:00.000Z"
    },
    "outcome_status": {
      "status": "pending_data",
      "measured_signal_count": 0,
      "pending_signal_count": 5,
      "summary": "Forward outcome measurement is pending until outcome jobs are enabled."
    },
    "generated_at": "2026-06-26T18:30:00.000Z"
  },
  "meta": {
    "ticker": "MSFT",
    "active_signal_count": 5,
    "evidence_count": 5,
    "api_version": "v1",
    "request_id": "d8d9dfba-e545-4d1f-a3f3-29dbf4eabddc",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}
GET/api/v1/tickers/{ticker}/thesis

Get an explainable ticker thesis

Beta

Auth

API key

Scopes

signals:read

Surface

Public customer API

Returns derived intelligence and normalized summaries only; raw vendor payloads and secrets are not exposed.

Parameters
NameInRequiredSchema
tickerpathYesstring
Responses
StatusDescriptionSchema
200Ticker thesis.object { data, meta }
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/tickers/{ticker}/thesis
{
  "data": {
    "ticker": "MSFT",
    "score": 36,
    "thesis": "MSFT is currently supported by 5 derived signal(s), led by price momentum, composite signal, analyst momentum. The strongest evidence is derived from supporting signals.",
    "supporting_signals": [
      {
        "id": "sig_977db43b55ef57e1",
        "ticker": "MSFT",
        "signal_type": "price_momentum",
        "score": 74,
        "confidence": 0.76,
        "reason": "MSFT has 3.7% recent price momentum with 100% positive sessions.",
        "event_date": "2026-06-25",
        "generated_at": "2026-06-25T16:35:16.303Z",
        "effective_at": "2026-06-25T23:59:59.999Z",
        "as_of": "2026-06-25",
        "scoring_version": "2026-06-20.v1",
        "input_hash": "24cb5e733feb8036",
        "coverage": 0.75,
        "score_components": {
          "return_20d": 15.67,
          "relative_strength_60d": 0,
          "trend_consistency": 26.67,
          "volume_confirmation": 15.3,
          "drawdown_control": 16
        },
        "score_explanation": "Score 74 is a bounded 0-100 weighted blend led by trend consistency, drawdown control, return 20d, with 75% input coverage. 1 component lacked enough data and contributed 0.",
        "components": [
          {
            "key": "return_20d",
            "label": "Recent return",
            "raw_value": 3.749600893997439,
            "normalized_score": 47,
            "weight": 0.25,
            "contribution": 11.75,
            "reason_code": "PRICE_RETURN"
          }
        ],
        "source_names": [
          "mock_market"
        ],
        "source_event_ids": [
          "price_8638f0279b38c5e1"
        ],
        "evidence_ids": [
          "ev_d4db7f1d420ba224"
        ],
        "evidence_status": "available",
        "source_lineage": [
          {
            "evidence_id": "ev_d4db7f1d420ba224",
            "provider": "mock_market",
            "source_type": "price_bar",
            "source_url": null,
            "external_id": "price_8638f0279b38c5e1",
            "observed_at": "2026-06-25T16:35:16.301Z",
            "event_date": "2026-06-25",
            "ticker": "MSFT",
            "company_name": null,
            "summary": "MSFT price observation on 2026-06-25.",
            "confidence": 0.55,
            "source_quality": "mock"
          }
        ],
        "metadata": {
          "observation_count": 10,
          "return_pct": 3.75
        }
      }
    ],
    "supporting_evidence": [
      {
        "evidence_id": "ev_d4db7f1d420ba224",
        "provider": "mock_market",
        "source_type": "price_bar",
        "source_url": null,
        "external_id": "price_8638f0279b38c5e1",
        "observed_at": "2026-06-25T16:35:16.301Z",
        "event_date": "2026-06-25",
        "ticker": "MSFT",
        "company_name": null,
        "summary": "MSFT price observation on 2026-06-25.",
        "confidence": 0.55,
        "source_quality": "mock"
      }
    ],
    "risks": [
      "Signals are derived from public event data and can decay quickly.",
      "Mock data is for local development only until live providers are connected.",
      "Backtest metrics are stubbed in this initial build."
    ],
    "generated_at": "2026-06-26T16:49:26.153Z"
  },
  "meta": {
    "api_version": "v1",
    "request_id": "d8d9dfba-e545-4d1f-a3f3-29dbf4eabddc",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}
GET/api/v1/backtests

Get backtest capabilities and runs

Placeholder

Auth

API key

Scopes

signals:read

Surface

Public customer API

Backtest execution is not enabled; this returns reserved capabilities and an empty run list.

Responses
StatusDescriptionSchema
200Placeholder capabilities and an empty run list.BacktestRunsEnvelope
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/backtests
{
  "data": {
    "capabilities": {
      "status": "stubbed",
      "can_submit": false,
      "message": "Forward outcome windows are recorded for signals when price bars exist. Full historical backtest execution is reserved for beta.",
      "supported_horizons_days": [
        1,
        5,
        20,
        60
      ],
      "outcome_fields": [
        "return_pct",
        "benchmark_return_pct",
        "excess_return_pct",
        "direction_correct"
      ]
    },
    "runs": []
  },
  "meta": {
    "count": 0,
    "api_version": "v1",
    "request_id": "7e2f27ef-7848-47a4-8dd3-c6f5bcab0035",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}
POST/api/v1/backtests

Submit a backtest

Reserved endpoint; execution is not enabled in the beta.

Placeholder

Auth

API key

Scopes

signals:read

Surface

Public customer API

Reserved endpoint. Current beta returns 501 until historical execution jobs are enabled.

Responses
StatusDescriptionSchema
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
501Endpoint contract is reserved but execution is unavailable.ErrorEnvelope
GET/api/v1/backtests/{id}

Get a backtest run

Placeholder

Auth

API key

Scopes

signals:read

Surface

Public customer API

Backtest run lookup is reserved and currently returns a not-found placeholder.

Parameters
NameInRequiredSchema
idpathYesstring
Responses
StatusDescriptionSchema
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
404Resource not found.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
GET/api/v1/backtests/signal-types

List signal definitions and outcome availability

Placeholder

Auth

API key

Scopes

signals:read

Surface

Public customer API

Signal type summaries expose readiness status, not performance claims.

Responses
StatusDescriptionSchema
200Backtest signal research status.BacktestSignalTypeSummaryEnvelope
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/backtests/signal-types
{
  "data": [
    {
      "signal_type": "price_momentum",
      "description": "Price momentum scored from recent return, trend consistency, volume confirmation, and drawdown control.",
      "sample_size": 0,
      "win_rate": null,
      "average_return": null,
      "status": "not_enough_data"
    }
  ],
  "meta": {
    "count": 1,
    "api_version": "v1",
    "request_id": "7e2f27ef-7848-47a4-8dd3-c6f5bcab0035",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}

Watchlists

GET/api/v1/watchlists

List organization watchlists

Requires the watchlists:read scope. Results are always scoped to the API key organization.

Beta

Auth

API key

Scopes

watchlists:read

Surface

Public customer API

Organization-scoped watchlist resources only.

Responses
StatusDescriptionSchema
200Organization watchlistsobject { data, meta }
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/watchlists
{
  "data": [
    {
      "id": "wl_core_research",
      "organization_id": "org_123",
      "name": "Core research",
      "description": "High-priority tickers for daily signal review.",
      "created_at": "2026-06-26T20:05:15.000Z",
      "updated_at": "2026-06-26T20:05:15.000Z",
      "tickers": [
        {
          "id": "wlt_msft",
          "watchlist_id": "wl_core_research",
          "organization_id": "org_123",
          "ticker": "MSFT",
          "added_at": "2026-06-26T20:05:15.000Z",
          "metadata": {}
        }
      ],
      "metadata": {}
    }
  ],
  "meta": {
    "count": 1,
    "api_version": "v1",
    "request_id": "7e2f27ef-7848-47a4-8dd3-c6f5bcab0035",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}
POST/api/v1/watchlists

Create an organization watchlist

Requires the watchlists:write scope. The created watchlist belongs to the API key organization.

Beta

Auth

API key

Scopes

watchlists:write

Surface

Public customer API

Organization-scoped watchlist resources only.

Request Body

Required · WatchlistCreateRequest

Responses
StatusDescriptionSchema
201Watchlist createdobject { data, meta }
400Malformed request, invalid JSON, or invalid query parameter.ErrorEnvelope
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
409Watchlist name already exists for the organizationNo JSON body
422Request body was valid JSON but failed domain validation.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
GET/api/v1/watchlists/{id}

Get an organization watchlist

Requires the watchlists:read scope.

Beta

Auth

API key

Scopes

watchlists:read

Surface

Public customer API

Organization-scoped watchlist resources only.

Parameters
NameInRequiredSchema
idpathYesstring
Responses
StatusDescriptionSchema
200Watchlist detailobject { data, meta }
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
404Resource not found.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
POST/api/v1/watchlists/{id}/tickers

Add a ticker to a watchlist

Requires the watchlists:write scope. Adding an existing ticker is idempotent.

Beta

Auth

API key

Scopes

watchlists:write

Surface

Public customer API

Organization-scoped watchlist resources only.

Parameters
NameInRequiredSchema
idpathYesstring

Request Body

Required · WatchlistTickerRequest

Responses
StatusDescriptionSchema
200Updated watchlistobject { data, meta }
400Malformed request, invalid JSON, or invalid query parameter.ErrorEnvelope
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
404Resource not found.ErrorEnvelope
422Request body was valid JSON but failed domain validation.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
DELETE/api/v1/watchlists/{id}/tickers/{ticker}

Remove a ticker from a watchlist

Requires the watchlists:write scope. Removing a ticker that is not present is idempotent.

Beta

Auth

API key

Scopes

watchlists:write

Surface

Public customer API

Organization-scoped watchlist resources only.

Parameters
NameInRequiredSchema
idpathYesstring
tickerpathYesstring
Responses
StatusDescriptionSchema
200Updated watchlistobject { data, meta }
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
404Resource not found.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope

Usage

GET/api/v1/usage

List recent usage for the API key organization

Requires the usage:read scope.

Production

Auth

API key

Scopes

usage:read

Surface

Public customer API

Organization-scoped usage metadata only.

Responses
StatusDescriptionSchema
200Recent usage log entries.object { data, meta }
401Missing, expired, revoked, or invalid API key.ErrorEnvelope
403API key lacks the required scope.ErrorEnvelope
429Plan rate limit exceeded.ErrorEnvelope
500Unexpected server-side failure. The x-request-id header can be used for support correlation.ErrorEnvelope
Example response
GET /api/v1/usage
{
  "data": [
    {
      "request_id": "16b263fb-0be4-4239-a732-0dfec5b3dd40",
      "path": "/api/v1/tickers/MSFT/thesis",
      "method": "GET",
      "status_code": 200,
      "duration_ms": 42,
      "plan_key": "beta",
      "occurred_at": "2026-06-27T19:30:00.000Z"
    }
  ],
  "meta": {
    "count": 1,
    "api_version": "v1",
    "request_id": "7e2f27ef-7848-47a4-8dd3-c6f5bcab0035",
    "disclaimer": "Market intelligence for informational purposes only; not financial advice."
  }
}

Separate API Surfaces

Dashboard control plane

Cookie-authenticated dashboard routes. These are not public v1 customer endpoints.

GET
/api/account/api-keys

Dashboard API key inventory for the signed-in organization.

Beta
POST
/api/account/api-keys

Creates an organization key and returns the one-time secret.

Beta
DELETE
/api/account/api-keys/{id}

Revokes an organization API key.

Beta
GET
/api/account/organization

Signed-in organization and plan context.

Beta
GET
/api/account/usage

Dashboard usage summary for the signed-in account.

Beta
GET/PUT
/api/account/signal-engine-settings

Owner/admin scoring configuration control plane.

Operator-only
POST
/api/account/signal-engine-settings/preview

Owner/admin score preview tooling.

Operator-only
POST
/api/account/signal-engine-settings/reset

Owner/admin reset of scoring configuration.

Operator-only

Operator and dev endpoints

Deployment operations and local tooling. These are excluded from customer API contracts.

GET
/api/cron/ingest

Scheduled ingestion. Requires the deployment cron bearer secret.

Operator-only
POST
/api/dev/ingest

Local development ingestion. Disabled in production unless dev tools are explicitly enabled.

Operator-only

Beta and Legal Boundary

API output is market intelligence for informational purposes only and is not financial advice. Backtest execution remains a placeholder, outcome windows depend on available price bars, and example keys such as sf_live_example_1234567890 are fake.