API Reference

BASE URL: HTTPS://API.SENTIMENTFX.ORG

API Key No key yet? Get a free one — 1,000 calls every 30 days, no card.

Authentication

All API endpoints require an API key passed as the X-API-Key request header. Get one below — no card, no account, 1,000 free calls every 30 days.

PlanIncluded CallsPast the allowance
Free1,000 per 30-day windowRequests stop until the window ends
Pro15,000 / monthRequests stop until the 1st
Data200,000 / monthRequests stop until the 1st

Already subscribed? Keys generated from the dashboard are linked to your account and pick up your plan's monthly allowance automatically.

Nothing is ever billed per call. When a key's allowance is used up it stops serving until it refills — a free key's 30-day window starts at its first call, and paid plans refill on the 1st. Requests past the allowance return 402 with "type": "insufficient_quota". GET /v1/usage keeps working when you're out, so you can always check where you stand. Need more than your plan includes? Request a higher allowance.
Example Request
# Curl
curl https://api.sentimentfx.org/v1/sentiment/BTC \
  -H "X-API-Key: sfx_your_api_key_here"

# Python
import requests
res = requests.get(
    "https://api.sentimentfx.org/v1/sentiment/BTC",
    headers={"X-API-Key": "sfx_your_api_key_here"}
)

# JavaScript
const res = await fetch(
    "https://api.sentimentfx.org/v1/sentiment/BTC",
    { headers: { "X-API-Key": "sfx_your_api_key_here" } }
)

Sentiment

GET /v1/sentiment/{ticker}

Returns sentiment-scored headlines for the specified ticker. Default 25 headlines = 1 call. Every additional 25 = 1 more call.

ParameterTypeDefaultDescription
tickerstring—42 supported across crypto, FX, stocks, ETFs, commodities
limitinteger25Headlines to return, 1–100. Costs 1 credit per 25 returned.
sourcesstringnewsnews returns editorial news. social returns Reddit, StockTwits and X posts only. all returns both.

Social posts are kept separate from news and never count towards a sentiment average. Each headline's source_kind is news, reddit, stocktwits, x or youtube.

Response
{
  "ticker": "BTC",
  "limit": 25,
  "sources": "news",
  "calls_used": 1,
  "data": [
    {
      "date": "2026-04-27T12:00:00",
      "title": "Bitcoin hits new yearly high amid ETF inflows",
      "source": "CoinDesk",
      "source_kind": "news",
      "sentiment_score": 0.6821,
      "sentiment_label": "positive"
    }
  ]
}
▶ Try it
Ticker Limit

                                    

Summary

GET /v1/summary/{ticker}

Returns daily averaged sentiment scores. Costs 1 credit per day actually returned — a window with no coverage costs nothing.

ParameterTypeDefaultDescription
tickerstring—42 supported across crypto, FX, stocks, ETFs, commodities
daysinteger30Days of history, 1–365. Costs 1 credit per day returned.
sourcesstringnewsnews averages editorial news. social gives a separate daily average of Reddit, StockTwits and X posts.
Response
{
  "ticker": "BTC",
  "days": 30,
  "sources": "news",
  "calls_used": 30,
  "data": [
    {
      "date": "2026-04-27",
      "avg_sentiment": 0.2341,
      "article_count": 12,
      "label": "positive"
    }
  ]
}
▶ Try it
Ticker Days

                                    

Prices

GET /v1/prices/{ticker}

Returns daily closing prices in the asset's native currency: GBP for crypto, exchange rates for FX pairs, USD for stocks, ETFs and commodity futures. Costs 1 credit per day actually returned — a window with no coverage costs nothing.

ParameterTypeDefaultDescription
tickerstring—42 supported across crypto, FX, stocks, ETFs, commodities
daysinteger30Days of history, 1–365. Costs 1 credit per day returned.
Response
{
  "ticker": "BTC",
  "days": 30,
  "calls_used": 30,
  "currency": "GBP",
  "data": [
    {
      "date": "2026-04-27T00:00:00",
      "close_price": 72841.50,
      "volume": 18294830293.0
    }
  ]
}
▶ Try it
Ticker Days

                                    

Correlation

GET /v1/correlation/{ticker}

Returns the Pearson correlation between sentiment shifts and next-day price returns, with a 95% confidence interval and signal strength rating. Always 1 call.

ParameterTypeDefaultDescription
tickerstring—42 supported across crypto, FX, stocks, ETFs, commodities
Response
{
  "ticker": "BTC",
  "calls_used": 1,
  "window_days": 180,
  "sample_size": 87,
  "primary_signal": {
    "type": "sentiment_shift_vs_next_day_return",
    "correlation": 0.241,
    "p_value": 0.0241,
    "ci_95": [0.033, 0.431],
    "strength": "weak",
    "direction": "positive (momentum)"
  },
  "interpretation": "Sentiment shifts show a weak positive (momentum) signal (r=0.241, p=0.0241, n=87)"
}
Methodology: Correlates daily sentiment shifts (deviation from 7-day rolling average) against next-day price returns over a 180-day window. Strength is classified on |r| magnitude: strong (|r|≥0.25), weak (|r|≥0.10), or inconclusive (|r|<0.10). CI uses Fisher z-transform.
▶ Try it
Ticker

                                    

MCP — Claude, Cursor & other AI clients

SentimentFX also speaks the Model Context Protocol, so Claude Code, Claude.ai desktop, Cursor, Cline and any other MCP-compatible client can call the sentiment tools natively without you writing HTTP-plumbing code. Same X-API-Key, same billing, same rate limits — you just point the client at a URL.

Endpoint: https://api.sentimentfx.org/mcp

Auth: X-API-Key: sfx_... header, or Authorization: Bearer sfx_... for clients that can only send a bearer token (get a free key).

Tools exposed

ToolArgsCost
list_tickers—free
get_usage—free — plan, calls used, allowance, reset date
get_sentimentticker, limit (≤100)1 credit / 25 headlines returned
get_summaryticker, days (≤365)1 credit / day returned
get_pricesticker, days (≤365)1 credit / day returned
get_correlationticker1 credit

Claude Code

Run once in a terminal. --scope user makes the tools available in every project; leave it out to add them to the current project only:

claude mcp add --transport http --scope user sentimentfx https://api.sentimentfx.org/mcp --header "X-API-Key: sfx_your_key_here"

Check it with claude mcp list, or /mcp inside a session. Start a new session and Claude will discover the six tools. Try "What's Bitcoin sentiment looking like this week?".

Cursor / Windsurf

Add this to ~/.cursor/mcp.json (or .cursor/mcp.json in a project) for Cursor, or to Windsurf's mcp_config.json:

{
  "mcpServers": {
    "sentimentfx": {
      "url": "https://api.sentimentfx.org/mcp",
      "headers": { "X-API-Key": "sfx_your_key_here" }
    }
  }
}

Cline

In the MCP Servers panel, open the Configure tab and click Configure MCP Servers. Cline needs "type": "streamableHttp": without it, Cline falls back to the older SSE transport, which this server doesn't offer.

{
  "mcpServers": {
    "sentimentfx": {
      "type": "streamableHttp",
      "url": "https://api.sentimentfx.org/mcp",
      "headers": { "X-API-Key": "sfx_your_key_here" }
    }
  }
}

Claude API (custom apps)

Use the Messages API's MCP connector. It needs the server in mcp_servers and a matching mcp_toolset in tools. The connector can't send custom headers, so your key goes in authorization_token, which arrives as Authorization: Bearer:

from anthropic import Anthropic
client = Anthropic()
resp = client.beta.messages.create(
    model="claude-opus-5-5",
    max_tokens=16000,
    betas=["mcp-client-2025-11-20", "server-side-fallback-2026-07-01"],
    fallbacks="default",
    mcp_servers=[{
        "type": "url",
        "url": "https://api.sentimentfx.org/mcp",
        "name": "sentimentfx",
        "authorization_token": "sfx_your_key_here",
    }],
    tools=[{"type": "mcp_toolset", "mcp_server_name": "sentimentfx"}],
    messages=[{"role": "user", "content": "Rank the top 5 tickers by 7-day sentiment shift."}],
)
print("".join(b.text for b in resp.content if b.type == "text"))

Every MCP tool call counts against the same allowance as the equivalent /v1/* HTTP call — check usage on the dashboard's API Access panel.

Error Codes

CodeMeaning
401Missing or invalid API key
402Allowance used up — insufficient_quota. Wait for the refill or request more
403Plan does not include API access
404No data found for ticker
429Rate limit exceeded
500Server error

Request more calls

Every plan stops at its allowance rather than billing per call. If your application needs more than your plan includes, tell us roughly how many calls and what for, and we'll raise your key's allowance. The extra calls apply every period: each 30-day window on a free key, each month on Pro or Data.

Bulk dataset licence

The API is sold as a monthly call allowance, which suits an application reading current sentiment. If you need the whole corpus at once — to backtest against, to train on, or to join to your own data — that's a licence rather than a subscription, delivered as CSV or JSONL.

ContentsDetail
Headlines180,000+ FinBERT-scored
Price rows120,000+ daily OHLCV
Tickers42 — crypto, FX, US equities, ETFs, commodity futures
Per headlineticker, title, source, URL, FinBERT score (-1 to +1), label, published timestamp
FormatsCSV or JSONL, one-off snapshot or refreshed periodically

Scores come from the same FinBERT pipeline behind the live API, so a backtest on the archive and a signal read from /v1/sentiment are directly comparable. Methodology is documented in full under Sentiment Scoring.

Methodology

HOW SENTIMENTFX SCORES, ANALYSES, AND SIGNALS

Sentiment Scoring

Every headline is scored using FinBERT, a BERT-based transformer model fine-tuned on financial news. The model outputs three probabilities: positive, negative, and neutral.

We compute the score as:

score = positive_probability − negative_probability

This gives a value in the range −1.0 to +1.0, where +1 is maximally positive, −1 is maximally negative, and 0 is neutral. We deliberately exclude the neutral label from the score — only the relative weight of positive vs negative drives it.

The daily sentiment figure shown on the dashboard is the mean score across all headlines published for that ticker on that day.

Score RangeLabel
> +0.3Strongly Bullish
+0.1 to +0.3Bullish
−0.1 to +0.1Neutral
−0.3 to −0.1Bearish
< −0.3Strongly Bearish

Sentiment Shift

Raw sentiment level is a lagging, noisy signal — markets tend to price in known information quickly. What is more useful is the change in sentiment relative to recent baseline.

We define the daily sentiment shift as:

shift = today's sentiment − 7-day rolling average

A positive shift means today's news is meaningfully more positive than the recent norm. A negative shift means the tone has deteriorated relative to baseline. This is the primary input to the correlation and signal models.

The 7-Day Trend shown on the dashboard compares the average sentiment of the last 7 days to the 7 days before that — a broader directional indicator separate from the daily shift.

Correlation Analysis

We compute a Pearson correlation between daily sentiment shifts and the next-day price return (close-to-close, in the ticker's native currency) over a rolling 180-day window. A minimum of 30 overlapping data points is required to return a result.

r = corr(sentiment_shift[d], price_return[d+1])

The result includes:

FieldDescription
correlation (r)Pearson r. Range −1 to +1. Closer to ±1 = stronger relationship.
p_valueProbability the result is due to chance. <0.05 = statistically significant.
ci_9595% confidence interval via Fisher z-transform. Narrower = more reliable.
sample_size (n)Number of overlapping trading days used in the calculation.

We also compute a momentum baseline (autocorrelation of price returns) to test whether the sentiment signal adds value beyond simple price momentum. primary_beats_momentum: true means it does.

Signal Strength

Signal strength reflects the statistical reliability of the historical sentiment-price correlation model for a given ticker — not the size of today's specific shift.

LabelCriteriaMeaning
Strong|r| ≥ 0.25Consistent relationship across the analysis window
Weak|r| ≥ 0.10Detectable relationship but modest in magnitude
Inconclusive|r| < 0.10No meaningful directional relationship found

Strength is based on correlation magnitude (|r|), consistent with how practitioners use rolling correlations in quantitative finance. The p-value is included in the response for reference. Tickers with fewer headlines (SOL, XRP, DOGE) tend to have noisier correlations and are more likely to be inconclusive.

Correlation is not causation. Signal strength tells you how consistent the historical relationship has been — it does not guarantee future price moves.

Shift Percentile

The shift percentile ranks today's sentiment shift against all historical daily shifts for that ticker over the last 180 days.

PercentileLabelMeaning
≥ 90thExtremeLarger than 90% of all recorded shifts — rare
75th – 89thSignificantTop quartile of historical shifts
50th – 74thModerateAbove-median shift
< 50thMinorBelow-median — normal day-to-day noise

A high shift percentile means today's sentiment move is unusually large relative to history — which, combined with a reliable signal model, increases confidence in the direction. A minor shift in isolation has limited predictive value even if the historical correlation is strong.

Momentum vs Contrarian

The direction label describes how sentiment shifts have historically related to price moves for a given ticker.

Labelr signMeaning
MomentumPositive (+)Positive sentiment shifts tend to be followed by price rises. Negative shifts tend to be followed by drops.
ContrarianNegative (−)Positive sentiment shifts tend to be followed by price drops — the market may already have priced in the optimism. Negative shifts may precede rebounds.

Neither direction is inherently better — both can be traded if the correlation is strong enough. The direction is determined purely by the sign of the Pearson r value over the analysis window.