Back to the notebook

Stock Screener API: Filter the Universe on the SentiSense Score, Analyst Consensus, and Technicals

A stock screener API takes a structured filter and returns the matching rows in one call. Today we are opening ours: four deterministic endpoints over roughly a thousand tracked US names, free with an API key, so your agent or your script can run the same screens the app runs.

SentiSense Team
SentiSense Team
August 15, 2026 · 4 min read

A stock screener API takes a structured set of filters and returns every matching ticker in a single call, with the full field set on each row. No pagination through a chain, no scraping a table, no client-side reimplementation of the filter logic.

Today we are opening ours: four deterministic endpoints, free with an API key. It is the same screener that powers the app, now callable from a script or an AI agent.

What you can filter on

The universe is roughly a thousand of the most-watched US stocks, plus a separate ETF universe. The interesting part is not the count, it is that our own signals sit in the same WHERE clause as everything else:

  • SentiSense Score: SENTI_SCORE_7D, SENTI_SCORE_1M, SCORE_CHANGE_7D, plus 30-day trend and rising-streak fields.
  • Attention: MENTION_SHARE, MENTION_VELOCITY, SOCIAL_DOMINANCE, DOMINANCE_CHANGE.
  • Analyst consensus: ANALYST_BUY_RATIO_PCT, ANALYST_TARGET_UPSIDE_PCT, ANALYST_COUNT, ANALYST_RATING_MOMENTUM_30D.
  • Technicals and returns: PCT_OFF_52W_HIGH, PCT_OFF_200D_MA, PCT_OFF_50D_MA, MA_CROSS_STATE, RETURN_1M through RETURN_1Y, VOLATILITY_30D.

A screen on analyst ratings alone is something a dozen free tools already do. A screen on analyst ratings crossed with whether anyone is actually talking about the name is not.

The street likes it, nobody is talking about it

That cross, as one request:

curl -X POST https://app.sentisense.ai/api/v1/screener/execute \
  -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "plan": {
      "filters": [
        { "fieldName": "ANALYST_BUY_RATIO_PCT", "op": "GTE", "value": 90 },
        { "fieldName": "ANALYST_COUNT", "op": "GTE", "value": 5 },
        { "fieldName": "SOCIAL_DOMINANCE", "op": "LTE", "value": 0.001 }
      ],
      "sort": { "fieldName": "ANALYST_TARGET_UPSIDE_PCT", "dir": "DESC" }
    },
    "limit": 25
  }'

Keep the ANALYST_COUNT leg. Coverage bottoms out at a single analyst, and a 100% buy ratio from one analyst is noise, not consensus.

The mirror image, Score climbing while the price has not moved:

curl -X POST https://app.sentisense.ai/api/v1/screener/execute \
  -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "plan": {
      "filters": [
        { "fieldName": "SENTI_SCORE_TREND_30D", "op": "GT", "value": 0 },
        { "fieldName": "PRICE_TREND_30D", "op": "LTE", "value": 0 }
      ],
      "sort": { "fieldName": "SENTI_SCORE_TREND_30D", "dir": "DESC" }
    }
  }'

limit sits on the request body next to plan, not inside it. It defaults to 100 and caps at 500.

Four endpoints

POST /api/v1/screener/execute runs a plan against the stock universe and POST /api/v1/screener/etfs/execute runs the same shape against ETFs. GET /api/v1/screener/fields returns the full catalog: every field, its group, its unit, the operators it accepts, and a description. Build your filter UI from that and you inherit new fields as we ship them. GET /api/v1/screener/screens returns the 28 curated screens we ship in the product, each with an executable plan you can run directly or fork.

Two response details worth coding against. matched comes back alongside results, so truncation is visible: a capped list with no count is how a caller quietly concludes the universe is smaller than it is. And every row carries the full field set, not just the fields you filtered on, so you can sort or post-process client side without a second call.

Field semantics, stated outright

Guess these three wrong and the screen still runs, still returns rows, and means nothing:

  • ANALYST_RATING_MEAN is inverted. It is the vendor's 1-to-5 scale where 1.0 is strong buy. Bullish is LTE 2.5, not GTE.
  • MA_CROSS_STATE is ordinal, not a percentage: 1 golden cross, -1 death cross, 0 neither. Use EQ.
  • Nulls never match. A row missing the field you filtered on is excluded in both directions, so RETURN_1Y >= 0 and RETURN_1Y < 0 do not partition the universe.

And one about scale: every SENTI_SCORE_* field is the SentiSense Score, an unbounded conviction measure banded at 5, 13, and 23. It is not sentiment polarity. Filter on the band edges, not on polarity-scale values like 0.5, which behave as "any positive score".

SDKs and agents

The Python and Node SDKs ship the screener as of sentisense 0.39.0 (PyPI) and 0.38.0 (npm). The curated screens round-trip: list them, pick one, execute its plan as-is.

from sentisense import SentiSenseClient

client = SentiSenseClient(api_key="ss_live_...")

screens = client.list_screens()
screen = next(s for s in screens if s.id == "oversold-with-positive-sentiment")
result = client.run_screen(plan=screen.plan, limit=10)

print(f"{screen.name}: {result.matched} matches")

The screener is also in the MCP connector as screen_stocks, and the agent skill installs with npx skills add SentiSenseApp/skills. Either way an agent can ask for the names where analyst conviction and public attention disagree, and get structured rows back instead of a scraped table.

Screens read a snapshot that refreshes every 20 minutes, so this is a research surface, not a quote feed. Rate limits: 30 requests per minute on Free, 300 on PRO, with no monthly cap on PRO.

The full field catalog and response contract are in the Screener API docs. Every endpoint above works on a free key: get an API key and the calls run as written.


SentiSense provides market information, sentiment analysis, and data intelligence for informational and educational purposes only. We do not provide investment advice, recommendations, or financial guidance. Screener results are a filter over data, not a suggestion to buy or sell any security. Users are solely responsible for their own investment decisions.