Read StockTipRatings research from your own code, or hand it to an AI agent. Ten read-only endpoints and five MCP tools over the same data the site runs on.
A read-only HTTP API over StockTipRatings research: stocks and their analyst consensus, individual broker calls, analyst track records scored against what the stock actually did, semantic search over research commentary, and ranked lists.
It is versioned and frozen. Everything lives under https://stocktipratings.com/api/v1, answers JSON in snake_case, and never exposes your account data — a leaked key costs you quota, not your watchlist.
The OpenAPI 3.1 spec is the authoritative contract and needs no key to read.
Create a key on your account page. It is shown once, at creation. Keys are part of the Ultra plan — see pricing.
Send it as a bearer token. Revoking a key stops it working within a minute.
Authorization: Bearer str_live_9fK2mQ7xR4tL8vB1nD6sW3zA5cE0gH2jCheck the key and see what your plan allows:
curl -H "Authorization: Bearer $STR_API_KEY" \
https://stocktipratings.com/api/v1/meFind a stock. Search takes a name, a ticker symbol or a Bursa number, and gives you back the code the rest of the API is addressed by:
curl -G -H "Authorization: Bearer $STR_API_KEY" \
--data-urlencode "q=maybank" \
https://stocktipratings.com/api/v1/stocks
# -> "code": "1155.KL", "symbol": "MAYBANK", "name": "MALAYAN BANKING BERHAD"Then that stock in full — consensus, distribution and recent calls:
curl -H "Authorization: Bearer $STR_API_KEY" \
https://stocktipratings.com/api/v1/stocks/1155.KLSearch the research semantically:
curl -G -H "Authorization: Bearer $STR_API_KEY" \
--data-urlencode "q=banks with improving net interest margin" \
https://stocktipratings.com/api/v1/newsThe day's top-rated analyst calls:
curl -H "Authorization: Bearer $STR_API_KEY" \
"https://stocktipratings.com/api/v1/rankings?type=top_calls&limit=10"| Endpoint | Returns | Parameters |
|---|---|---|
| GET /me | The key's plan and its rate limit | — |
| GET /stocks | List or search stocks | q, sector, sort, order, page, limit |
| GET /stocks/{code} | One stock: consensus, distribution, recent calls | period |
| GET /stocks/{code}/calls | Calls on one stock | period, page, limit |
| GET /calls | Calls across the market | analyst_id, broker, date, period, rated, page, limit |
| GET /analysts | List or search analysts | q, broker, sector, sort, order, page, limit |
| GET /analysts/{id} | One analyst: profile and track record | period |
| GET /news | Semantic search over broker research | q, stock, analyst_id, published_from, published_to, limit |
| GET /rankings | Seven ranked lists of calls and stocks | type, limit, sector |
| GET /sectors/{name} | One sector and its AI summary | — |
List endpoints take page and limit and answer {data, page: {size, number, total_results, total_pages, has_next}}. Stocks are addressed by code — the Bursa number plus .KL, as in 1155.KL — which is not the ticker symbol; that is the symbol field. Codes are case-sensitive and the suffix is required. Analysts are addressed by an opaque id from /analysts.
Invalid parameters are rejected, never quietly adjusted: a limit over the cap is a 400, not a clamp, so a request for 1000 results never looks like a complete answer of 100.
An MCP server exposes five tools over the same API: search_stocks, get_stock_analysis, get_analyst_track_record, search_news and get_rankings. It holds no key of its own — your key travels on the request and is verified by the API, exactly as with curl.
Streamable HTTP, for clients that support remote MCP servers:
https://mcp.stocktipratings.comClaude Desktop, using the remote server:
{
"mcpServers": {
"stocktipratings": {
"url": "https://mcp.stocktipratings.com",
"headers": {
"Authorization": "Bearer str_live_…"
}
}
}
}Or run the binary locally over stdio, with the key in STR_API_KEY:
{
"mcpServers": {
"stocktipratings": {
"command": "/usr/local/bin/str-mcp",
"env": { "STR_API_KEY": "str_live_…" }
}
}
}Listing the tools needs no key, so an agent can always see what is available and tell you a subscription would answer your question.
Every error is the same envelope. The hint is written for an agent to act on.
{
"error": {
"code": "subscription_required",
"message": "This API key belongs to an account without an active subscription.",
"hint": "Subscribe at https://stocktipratings.com/pricing, then retry."
}
}| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | A parameter is missing, malformed, over a cap, or combined with one it excludes. |
| 401 | invalid_key | The key is missing, malformed, revoked or expired. |
| 402 | subscription_required | The key is valid but the account is not on the Ultra plan. |
| 404 | not_found | No resource with that identifier. |
| 429 | rate_limited | Over the plan quota. Retry-After says how long to wait. |
| 500 | internal_error | Something failed on our side. Retry with backoff. |
A lapsed subscription is 402, not 401, so you never go hunting for a bad key when the problem is billing.
A key is capped at 300 requests per minute. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; a 429 adds Retry-After. Read them and back off.
One MCP tool call is not one API request. get_analyst_track_record costs up to three and get_stock_analysis up to two, so a key is roughly 100 track-record lookups a minute rather than 300.
/news is metered by a second, tighter limit of its own, because each search embeds your query. That limit is not reflected in the X-RateLimit-* headers.
Field-level detail for every response lives in the spec, and it is tested against the router so it cannot rot.