API Reference
BASE URL: HTTPS://API.SENTIMENTFX.ORG
Authentication
All API endpoints require an API key passed as the X-API-Key request header. Get one below — no card, no account, 100 free calls to try it with.
| Plan | Included Calls/mo | Overage |
|---|---|---|
| Free | 100 (one-off, not monthly) | None — requests stop at 100 |
| Pro | 1,000 | £0.01 / call via Stripe |
| Data | 5,000 | £0.01 / call via Stripe |
Full history on all 42 tickers, every endpoint, REST and MCP. If you've already made a free key above, enter the same email and we'll raise that key's allowance rather than issuing a second one.
Already subscribed? Keys generated from the dashboard are linked to your account and pick up your plan's monthly allowance automatically.
402 with "type": "insufficient_quota" rather than
silently billing you. There is no card on a free key and no overage can accrue.
GET /v1/usage keeps working when you're out, so you can always
check where you stand.
# 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
Returns sentiment-scored headlines for the specified ticker. Default 25 headlines = 1 call. Every additional 25 = 1 more call.
| Parameter | Type | Default | Description |
|---|---|---|---|
| ticker | string | — | 42 supported across crypto, FX, stocks, ETFs, commodities |
| limit | integer | 25 | Headlines to return, 1–100. Costs 1 credit per 25 returned. |
{
"ticker": "BTC",
"limit": 25,
"calls_used": 1,
"data": [
{
"date": "2026-04-27T12:00:00",
"title": "Bitcoin hits new yearly high amid ETF inflows",
"source": "CoinDesk",
"sentiment_score": 0.6821,
"sentiment_label": "positive"
}
]
}
Summary
Returns daily averaged sentiment scores. Costs 1 credit per day actually returned — a window with no coverage costs nothing.
| Parameter | Type | Default | Description |
|---|---|---|---|
| ticker | string | — | 42 supported across crypto, FX, stocks, ETFs, commodities |
| days | integer | 30 | Days of history, 1–365. Costs 1 credit per day returned. |
{
"ticker": "BTC",
"days": 30,
"calls_used": 30,
"data": [
{
"date": "2026-04-27",
"avg_sentiment": 0.2341,
"article_count": 12,
"label": "positive"
}
]
}
Prices
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.
| Parameter | Type | Default | Description |
|---|---|---|---|
| ticker | string | — | 42 supported across crypto, FX, stocks, ETFs, commodities |
| days | integer | 30 | Days of history, 1–365. Costs 1 credit per day returned. |
{
"ticker": "BTC",
"days": 30,
"calls_used": 30,
"currency": "GBP",
"data": [
{
"date": "2026-04-27T00:00:00",
"close_price": 72841.50,
"volume": 18294830293.0
}
]
}
Correlation
Returns the Pearson correlation between sentiment shifts and next-day price returns, with a 95% confidence interval and signal strength rating. Always 1 call.
| Parameter | Type | Default | Description |
|---|---|---|---|
| ticker | string | — | 42 supported across crypto, FX, stocks, ETFs, commodities |
{
"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)"
}
strong (|r|≥0.25), weak (|r|≥0.10), or inconclusive (|r|<0.10). CI uses Fisher z-transform.
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 (get a free key).
Tools exposed
| Tool | Args | Cost |
|---|---|---|
list_tickers | — | free |
get_sentiment | ticker, limit (≤100) | 1 credit / 25 headlines returned |
get_summary | ticker, days (≤365) | 1 credit / day returned |
get_prices | ticker, days (≤365) | 1 credit / day returned |
get_correlation | ticker | 1 credit |
Claude Code
Add to ~/.claude/settings.json (or your project's .claude/settings.json):
{
"mcpServers": {
"sentimentfx": {
"type": "http",
"url": "https://api.sentimentfx.org/mcp",
"headers": { "X-API-Key": "sfx_your_key_here" }
}
}
}
Restart Claude Code and Claude will discover the six tools. Try "What's Bitcoin sentiment looking like this week?".
Cursor / Cline / Windsurf
Same JSON block under whatever MCP config panel the editor exposes — Cursor is Settings → MCP → Add new server, Cline lives in its side panel. The only field that ever changes is the URL/auth combo above.
Claude API (custom apps)
Use the Anthropic SDK's MCP client to attach the server to your messages.create call:
from anthropic import Anthropic
client = Anthropic()
resp = client.beta.messages.create(
model="claude-opus-4-7",
max_tokens=1024,
mcp_servers=[{
"type": "url",
"url": "https://api.sentimentfx.org/mcp",
"name": "sentimentfx",
"authorization_token": "sfx_your_key_here",
}],
messages=[{"role": "user", "content": "Rank the top 5 tickers by 7-day sentiment shift."}],
)
Every MCP tool call bills the same meter as the equivalent /v1/* HTTP call — check usage on the dashboard's API Access panel.
Error Codes
| Code | Meaning |
|---|---|
| 401 | Missing or invalid API key |
| 403 | Plan does not include API access |
| 404 | No data found for ticker |
| 429 | Rate limit exceeded |
| 500 | Server error |
Bulk dataset licence
The API is metered per call, 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.
| Contents | Detail |
|---|---|
| Headlines | 180,000+ FinBERT-scored |
| Price rows | 120,000+ daily OHLCV |
| Tickers | 42 — crypto, FX, US equities, ETFs, commodity futures |
| Per headline | ticker, title, source, URL, FinBERT score (-1 to +1), label, published timestamp |
| Formats | CSV 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.
Pricing depends on scope and whether you're redistributing, so this starts a conversation rather than a checkout. Tell us what you need and we'll come back with terms.
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 Range | Label |
|---|---|
| > +0.3 | Strongly Bullish |
| +0.1 to +0.3 | Bullish |
| −0.1 to +0.1 | Neutral |
| −0.3 to −0.1 | Bearish |
| < −0.3 | Strongly 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:
| Field | Description |
|---|---|
| correlation (r) | Pearson r. Range −1 to +1. Closer to ±1 = stronger relationship. |
| p_value | Probability the result is due to chance. <0.05 = statistically significant. |
| ci_95 | 95% 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.
| Label | Criteria | Meaning |
|---|---|---|
| Strong | |r| ≥ 0.25 | Consistent relationship across the analysis window |
| Weak | |r| ≥ 0.10 | Detectable relationship but modest in magnitude |
| Inconclusive | |r| < 0.10 | No 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.
Shift Percentile
The shift percentile ranks today's sentiment shift against all historical daily shifts for that ticker over the last 180 days.
| Percentile | Label | Meaning |
|---|---|---|
| ≥ 90th | Extreme | Larger than 90% of all recorded shifts — rare |
| 75th – 89th | Significant | Top quartile of historical shifts |
| 50th – 74th | Moderate | Above-median shift |
| < 50th | Minor | Below-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.
| Label | r sign | Meaning |
|---|---|---|
| Momentum | Positive (+) | Positive sentiment shifts tend to be followed by price rises. Negative shifts tend to be followed by drops. |
| Contrarian | Negative (−) | 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.