Stocks API

Stock prices delayed 15 minutes, historical charts, company fundamentals, short interest data, and AI-powered stock analysis.

Free (deep AI summaries PRO-gated)29 endpoints

Overview

The Stocks API provides comprehensive stock data including 15-minute-delayed prices, historical charts, company fundamentals, short interest metrics, and AI-powered analysis reports. Every endpoint requires an API key (free to generate in Settings > Developer Console); most are available in full on the Free tier.


Stock Lists & Metadata

GET /

Returns all available stock ticker symbols tracked by SentiSense.

Authentication: API key required | Parameters: None

curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks"

Response: string[] (e.g., ["AAPL", "MSFT", "GOOGL", ...])


GET /detailed

Returns all stocks with company name, KB entity ID, and URL slug.

Authentication: API key required | Parameters: None

curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/detailed"

Response object:

Field Type Description
ticker string Ticker symbol
name string Company name
kbEntityId string Ontology entity ID
urlSlug string URL-friendly slug
socialDominance object | null Precomputed share of voice. value is share as a 0-1 decimal, rank is 1-based across the coverage universe, percentile is 0-100. Null when no signal exists. Refreshed daily.

Returns popular stock tickers. Parameters: None

curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/popular"

Response: string[]


Returns popular stocks with company details. Same schema as /detailed.


GET /images

Returns company logo/icon URLs for a batch of tickers.

Parameters:

Parameter Type Required Default Description
tickers string Yes - Comma-separated tickers (max 600)
forced boolean No false Bypass cache
curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/images?tickers=AAPL,TSLA,NVDA"

Response: Map<ticker, { iconUrl, logoUrl }>: URLs for company icons and logos. GET a URL directly to receive the image bytes; no API key is required for the image fetch itself, so the URLs can be used straight in an <img src> tag.

Treat these URLs as refreshable rather than permanent. Brand assets are periodically refreshed, and a URL issued for a previous revision stops resolving once that happens. Re-read them from this endpoint instead of storing them long term.


GET /descriptions

Returns company profiles with branding, market cap, and sector information.

Parameters:

Parameter Type Required Default Description
tickers string Yes - Comma-separated tickers
forced boolean No false Bypass cache
curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/descriptions?tickers=AAPL,MSFT"

Per-Stock Data

GET /{ticker}/similar

Returns peer and similar stocks based on sector, industry, and SentiSense ontology relationships.

Parameters:

Parameter Type Required Default Description
ticker path Yes - Stock ticker symbol
limit integer No 5 Max results
curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/AAPL/similar?limit=10"

GET /{ticker}/profile

Returns a company profile including CEO, sector, industry, and market data.

Parameters:

Parameter Type Required Default Description
ticker path Yes - Stock ticker symbol
forced boolean No false Bypass cache
curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/AAPL/profile"

Listing status: the profile also carries listingStatus, delistedDate and delistingReason when the symbol is delisted or pending delisting. All three are absent for a normally listed symbol, and they carry the same values as on GET /price: listingStatus is "DELISTED" or "PENDING_DELISTING", delistedDate is the ISO date trading stopped, and delistingReason is one of acquired, take_private, bankruptcy, exchange_rule, merged.

ETF profiles: when ticker identifies a tracked ETF, the response may also carry imageUrl, a square presentation image for the fund. It is the issuer's mark rather than the individual fund's, so every fund in a family shares one image, and it is the same value returned by the /etfs endpoints. It is square like logoUrl and iconUrl and drops into the same avatar slot, but it is a first-party asset rather than a vendor branding mark, so it is returned as a direct URL. It is absent for issuers we hold no image for.


GET /{ticker}/entities

Returns SentiSense ontology entities related to a stock (e.g., CEO, key products, partner companies).

curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/AAPL/entities"

Response: array of related entities. Each entry:

Field Type Description
id string Deprecated: not a stable public identifier. Use urlSlug to refer to an entity.
displayName string Entity display name
type string PERSON, PRODUCT, ORGANIZATION, etc.
relatedStock string The ticker you queried
urlSlug string|null Handle for the Metrics API {entityId} parameter (e.g. Tim-Cook)
title string|null Person's role (e.g. CEO)
category string|null Product category
appId string|null Apple App Store id when the product has a tracked companion app

GET /{ticker}/graph

Returns the typed relationships around one stock, including leaders, products and product families, peers, owners and subsidiaries, publishers, and topics.

curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/AAPL/graph?depth=1&cap=75"

Parameters:

Parameter Type Required Default Description
depth integer No 1 Traversal depth, either 1 or 2
cap integer No 75 Maximum non-root nodes, from 1 to 200

Response: a bounded graph projection with the requested stock as its root.

Field Type Description
ticker string Uppercase ticker symbol
root string Slug of the root company; matches one entry in nodes
depth integer Applied traversal depth
cap integer Applied non-root node cap
truncated boolean true when more matching nodes exist beyond cap
omitted integer Nodes left out because they carry no slug, and so cannot be addressed
counts object Returned nodes, edges, and node totals in byType
groups object Slugs grouped as people, products, productFamilies, peers, organizations, publishers, and topics
nodes[] array Nodes with slug, displayName, and type; PRODUCT_OR_SERVICE nodes also carry a string category when non-null, matching the product category on /{ticker}/entities
edges[] array Relationships with source, target, type, direction, and properties
{
  "ticker": "AAPL",
  "root": "Apple-Inc",
  "depth": 1,
  "cap": 75,
  "truncated": false,
  "omitted": 0,
  "counts": {
    "nodes": 3,
    "edges": 2,
    "byType": { "COMPANY": 1, "PERSON": 1, "PRODUCT_OR_SERVICE": 1 }
  },
  "groups": {
    "people": ["Tim-Cook"],
    "products": ["iPhone"],
    "productFamilies": [],
    "peers": [],
    "organizations": [],
    "publishers": [],
    "topics": []
  },
  "nodes": [
    { "slug": "Apple-Inc", "displayName": "Apple Inc.", "type": "COMPANY" },
    { "slug": "Tim-Cook", "displayName": "Tim Cook", "type": "PERSON" },
    { "slug": "iPhone", "displayName": "iPhone", "type": "PRODUCT_OR_SERVICE", "category": "Smartphones" }
  ],
  "edges": [
    { "source": "Tim-Cook", "target": "Apple-Inc", "type": "LEADS", "direction": "DIRECTED", "properties": {} },
    { "source": "iPhone", "target": "Apple-Inc", "type": "PRODUCT_OF", "direction": "DIRECTED", "properties": { "sourceProperty": "associatedCompany" } }
  ]
}

Handles: slugs are the only identifier here. The same string does three jobs: it joins groups and edges to nodes inside one response, it addresses the entity on the Metrics API and Documents API, and it is the entity page path (/entities/Tim-Cook). A product family is { "family": "iPhone", "members": ["iPhone-15"] }, slugs on both sides.

Edge types: OWNS, PEER, BELONGS_TO, LEADS, FOUNDED, AFFILIATED_WITH, VARIANT_OF, SUBTOPIC_OF, and SUBSIDIARY_OF are curated relationships. PRODUCT_OF is derived from a product's associated company.

Direction: DIRECTED preserves the relationship from source to target. BIDIRECTIONAL combines matching relationships present in both directions.

Edge properties: properties maps string keys to string values and is {} when the relationship carries no detail. Keys include role (the person's title on a LEADS edge, e.g. "Chief Executive Officer"), since (the year a LEADS relationship began, e.g. "2011"), and year (the founding year on a FOUNDED edge). Other keys may appear, so treat the map as open.

Unknown ticker: returns 404 with error: "entity_not_found" and up to three suggestions from entity search, plus reason: "non_us_listing" when the symbol is a non-US listing.

Free with an API key; rate limits apply. One ticker per call; there is no enumeration endpoint.


GET /{ticker}/ai-summary

Returns an AI-generated stock analysis report. PRO feature with limited Free access: depth=basic returns a preheader summary (Free: unlimited). depth=deep returns a full multi-section report (Free: 10 views/month, PRO: unlimited). Returns 429 with {error: "quota_exceeded", message, ...} when Free quota is exhausted, matching the platform-wide quota contract. message says when the allowance resets (the start of next month) and links PRO, which has no monthly report limit. The response has no Retry-After header.

Authentication: API key required

Parameters:

Parameter Type Required Default Description
ticker path Yes - Stock ticker symbol
depth string No basic Analysis depth: basic or deep
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/AAPL/ai-summary?depth=deep"

Response Schema: flat object (no {isPreview, data} wrapper).

Field Type Description
ticker string Ticker symbol
companyName string Company name
status string READY, DRAFT, NOT_AVAILABLE, or ERROR. Only READY carries report content; treat any other value as no report. Without content, sections, sectionOrder, moatRating and aiDisruptionRisk are omitted from the response, and companyName and version can be omitted too
statusReason string | null Present on every status other than READY
reportType string SUMMARY for depth=basic, FULL for depth=deep
version integer Report date encoded as yymmdd (e.g. 260520)
lastUpdated long Epoch milliseconds
sections object Map of section name to {content, directives}. Present on both depths when status is READY. depth=basic returns a single Executive Summary section; depth=deep returns the full set.
sectionOrder string[] Ordered section keys for rendering. Present on both depths when status is READY. ["Executive Summary"] on depth=basic.
moatRating integer | null Proprietary moat quality score 0 to 10. Present on depth=deep only. null if not yet assessed for this ticker.
aiDisruptionRisk string | null Low, Medium, High, or Critical: AI revenue-displacement exposure. Present on depth=deep only. null if not yet assessed.

Check status == "READY" before reading any section. Do not branch on the presence of sections to decide whether you received a deep report: both depths return it. Read reportType (SUMMARY vs FULL), or check the length of sectionOrder.


GET /{ticker}/metrics/{metricType}/breakdown

Returns sentiment or mention metrics broken down by entity for a stock over a time range.

Parameters:

Parameter Type Required Default Description
ticker path Yes - Stock ticker
metricType path Yes - Metric type (e.g., sentiment, mentions)
startTime long Yes - Start time (epoch ms)
endTime long Yes - End time (epoch ms)
curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/AAPL/metrics/sentiment/breakdown?startTime=1745600000000&endTime=1746204800000"

Market Data & Prices

GET /price

Returns the latest price for a single stock ticker, delayed 15 minutes.

Parameters:

Parameter Type Required Default Description
ticker string Yes - Stock ticker symbol
curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/price?ticker=AAPL"

Response:

Field Type Description
ticker string Ticker symbol
currentPrice double Regular-session price, delayed 15 minutes. During RTH (09:30 to 16:00 ET): the most recent regular-session value. Otherwise: most recent regular-session close.
change double currentPrice change vs previousClose
changePercent double currentPrice change percentage
previousClose double Previous closing price
volume long Volume
timestamp long When this response was served (epoch milliseconds). Not the age of the price: it tracks the current clock regardless of how old the value is.
priceAsOf long | absent When the market data behind currentPrice is from (epoch milliseconds). This is the field to read for freshness. Omitted outside regular hours, and whenever the upstream data is not dated, so treat its absence as "unknown" rather than "fresh".
extendedHours object | null Extended-hours view (pre-market or after-hours). Absent during RTH, overnight, and weekends. See below.
listingStatus string | absent "DELISTED" or "PENDING_DELISTING". Present only when the symbol is delisted or pending delisting, absent otherwise.
delistedDate string | absent ISO date (YYYY-MM-DD) trading stopped. Present only alongside listingStatus: "DELISTED".
delistingReason string | absent One of acquired, take_private, bankruptcy, exchange_rule, merged. Present only alongside listingStatus: "DELISTED".

Delisted symbols return their last trade price rather than an error, and listingStatus is what marks that price as frozen. On a "DELISTED" symbol, currentPrice, change and changePercent are the final trading session's values and never advance again. priceAsOf is the close of that final session (it can fall a day or more before delistedDate), extendedHours is absent, and timestamp is still the serve time. Read listingStatus before rendering a price as current.

extendedHours object:

Field Type Description
session string "pre" (04:00 to 09:30 ET) or "post" (16:00 to 20:00 ET)
price double Live extended-hours price
change double Extended-hours price change vs currentPrice
changePercent double Extended-hours change percentage vs currentPrice

GET /prices

Returns the latest prices for multiple tickers in a single request, delayed 15 minutes (see /price above).

Parameters:

Parameter Type Required Default Description
tickers string Yes - Comma-separated tickers
curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/prices?tickers=AAPL,TSLA,NVDA"

Response: StockPrice[] (JSON array). Each element is the same price object as /price, including a ticker field identifying the symbol, an optional extendedHours object during pre/post sessions, and the optional listingStatus / delistedDate / delistingReason fields. Check each element for a frozen price rather than assuming a batch is uniformly live. Tickers that fail to resolve are silently omitted from the array.


GET /chart

Returns historical OHLCV (Open, High, Low, Close, Volume) chart data for a stock.

Parameters:

Parameter Type Required Default Description
ticker string Yes - Stock ticker symbol
timeframe string No 1M Chart timeframe: 1D, 5D, 1W, 1M, 3M, 6M, 1Y, 5Y, 10Y, MAX

Up to 26 years of split- and dividend-adjusted history. MAX returns a stock's full available
history, back to 1999 for names listed that long: 320 monthly bars for AAPL, versus the 5 years
most price APIs cap at. 10Y returns weekly bars over ten years.

Granularity is chosen per range so a long chart stays a sensible payload: intraday for 1D
through 1M (5-minute for 1D, 15-minute for 5D, 30-minute for 1W, hourly for 1M), daily
for 3M through 1Y, weekly for 5Y and 10Y, monthly for MAX.

Ranges of 10Y and MAX are adjusted for both splits and dividends, so a long series is
comparable end to end rather than showing a cliff at every corporate action. Shorter ranges,
including 5Y, are split-adjusted only. The two bases therefore differ on the same historical
date, by roughly the dividends paid since: negligible for a non-payer, around 14% over five years
for a 3% yielder. volume is restated to today's share count in every range, so a pre-split bar
reports shares on the current basis and the volume series has no cliff either. Only splits move
it: a dividend changes the price basis but not the number of shares that changed hands. Every
bar carries adjusted: true to mark that basis.

One consequence of the restatement surprises people, so it is worth stating plainly: on a stock
with a large cumulative split factor, an old bar can report a share count many times larger than a
recent one. AAPL has split 28-for-1 since 2013, so one share of 2008 is 28 shares now and its raw
turnover is counted 28 times over. Measured on the monthly series in September 2026, that puts a
2008 bar near 24 billion shares against roughly 1 billion for a recent month. That is the
restatement working, not a data error, and the series is continuous across every split.

202 Accepted on 10Y and MAX means that stock's deep history is still being assembled.
The body is an empty array and a Retry-After header gives the suggested wait in seconds; retry
and you will get the full series. We return this rather than silently substituting a shorter
range, so a 200 always means the range you asked for. It only happens on the first request for
a rarely-viewed stock.

A timeframe value outside the list above answers 400 Bad Request with an invalid_timeframe
error naming the valid values.

Response: array of bars. Each bar has:

Field Type Description
timestamp long Unix timestamp in milliseconds
date string Pre-formatted display string (format varies by timeframe)
open double Opening price
high double Highest price during the bar
low double Lowest price during the bar
close double Closing price
volume long Bar volume, on the same restated basis as the prices (see adjusted)
session string | null US-equity session: pre (04:00 to 09:30 ET), regular (09:30 to 16:00 ET), or post (16:00 to 20:00 ET). Populated for intraday timeframes (1D, 5D, 1W, 1M); null for daily, weekly, and monthly bars (3M and longer) that span whole sessions. The 1M timeframe returns regular-session bars only.
adjusted boolean Always true: the bar is restated to the stock's current share count rather than served as it printed at the time.
curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/chart?ticker=AAPL&timeframe=6M"

Migrating from an internal chart endpoint on another site? GET /chart is the documented
equivalent, with full OHLCV bars instead of close-only pairs. Field-by-field mapping:
the migration guide.


GET /market-status

Returns the current US market status: open while the regular trading session is open, closed otherwise. Pre-market and after-hours report as closed.

Parameters: None

curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/market-status"

Response:

Field Type Description
status string open or closed
timestamp long When the status was computed (epoch milliseconds)

Fundamentals

Two endpoints share one period object. /fundamentals returns a single fiscal period, the
latest by default, plus trailing-twelve-month, price-ratio and market fields where available.
/fundamentals/history returns up to 40 quarters or 20 years of the same object with the
statement fields and derived ratios filled in and the rest null. /fundamentals/periods lists which periods exist, and
/fundamentals/current is a compact price-and-TTM profile. The period object is documented once,
under GET /fundamentals/history.

Reporting currency. Statement figures are served as the filer reports them, in the filer's
own currency, and are never converted to US dollars. US filers report in USD; foreign filers
listed as ADRs report in their home currency (ASML in EUR, Toyota in JPY, SK hynix in KRW).
/fundamentals, /fundamentals/current and every /fundamentals/history period carry an
optional reportedCurrency field ("USD", "EUR", "KRW", ...) naming that currency. When the field
is absent, the currency is unknown, not implicitly USD.

Do not mix these figures with the share price. The listed price is the USD ADR price, so when
reportedCurrency is present and not USD the API serves peRatio, psRatio and pbRatio as
null rather than a cross-currency number. Margins, returns and liquidity ratios have the same currency on both
sides and are served for every filer.

GET /fundamentals

Returns one fiscal period. With no fiscalPeriod and fiscalYear, that is the most recent filed
period for the timeframe, enriched with live market data. With both, it is that period as filed,
without the market data (see the table below). Supplying only one of the two does not select a
period; you get the latest one.

Parameters:

Parameter Type Required Default Description
ticker string Yes - Stock ticker
timeframe string No quarterly quarterly or annual
fiscalPeriod string No - Specific period (e.g. Q4 or FY). Only honoured together with fiscalYear.
fiscalYear string No - Specific fiscal year (e.g. 2024). Only honoured together with fiscalPeriod.
curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/fundamentals?ticker=AAPL&timeframe=quarterly"

Response: one period object, the shape documented under
GET /fundamentals/history, plus the fields that history leaves null:

Field On /fundamentals
revenueTTM, netIncomeTTM, epsTTM The sum of the filed periods that end with this period and together cover twelve months: four rows for a quarterly filer, two for a filer that reports half-years. epsTTM is on the diluted basis where the provider reports one. Null on timeframe=annual, null for any line that one of those periods lacks, and null when the filed periods cannot be assembled into a twelve-month window. Across a stock split, epsTTM can be built from split-adjusted quarterly figures, so it will not always equal the sum of the history rows' epsDiluted.
quartersIncluded The number of filed periods in the trailing-twelve-month window: 4 for a quarterly filer, 2 for a half-year filer. The trailing sums are filled only when this is present. Null on timeframe=annual, and null when no twelve-month window could be assembled.
currentPrice A delayed USD price, cached here for up to 30 minutes; use the quote endpoints when you need the price itself. Latest-period requests only.
marketCap USD market capitalisation from the company profile. Latest-period requests only, and null when the profile carries no market cap or the period was served from the statement source (see below).
sharesOutstanding Deprecated. On a latest period that carries marketCap, it is an estimate marketCap / currentPrice rather than a reported count; see the note under /fundamentals/history.
peRatio currentPrice / epsTTM; on timeframe=annual, currentPrice / epsDiluted for the year (or epsBasic when there is no diluted figure). Latest-period requests only, null for non-USD filers and when the EPS input is zero or negative.
psRatio marketCap / revenueTTM; on timeframe=annual, price over the year's revenue per share. Null for non-USD filers and on responses without market data.
pbRatio currentPrice over book value per share (totalEquity / sharesOutstanding). Null for non-USD filers, when equity is not positive, and on responses without market data.
roe, roa netIncomeTTM / totalEquity and netIncomeTTM / totalAssets, in percent. On timeframe=annual, the year's netIncome is used instead.
companyName Filled only on latest periods that carry market data.

The latest period is served from one of two sources, chosen per ticker by which one has the
fresher filing, so a ticker can move between them. Responses from the market-data source carry
the full set above. Responses from the statement source carry the trailing sums, currentPrice
and peRatio but no marketCap, psRatio, pbRatio or companyName, and their
sharesOutstanding is the weighted-average form used on history rows. A null marketCap on a
latest period tells you which one you got.


GET /fundamentals/periods

Lists the fiscal periods available for a ticker, quarterly and annual together:
{ ticker, periods: [{ fiscalPeriod, fiscalYear, filingDate, periodEndDate, timeframe }] }. Order
is not guaranteed; sort on periodEndDate yourself.

curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/fundamentals/periods?ticker=AAPL"

GET /fundamentals/current

Returns a compact trailing profile, not a statement: ticker, currentPrice, epsTTM, revenueTTM,
peTTM, psTTM, quartersIncluded, reportedCurrency, fetchedAt, plus available and
reason. Use it when you only need trailing P/E and P/S; for statement lines use /fundamentals.

curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/fundamentals/current?ticker=AAPL"

GET /fundamentals/history

Returns a multi-period history of full financial statements (income statement, balance sheet and
cash flow), one entry per statement period the provider publishes, plus any pre-IPO quarter
described under Reading the rows, newest first. This is the
endpoint behind the statement tables on the Financials tab: use it for margin trends, multi-year
comparisons, or as the input data for a valuation model. Not the same as /fundamentals (a single
period) or /fundamentals/historical/revenue (income-statement lines only, recent periods only).

Parameters:

Parameter Type Required Default Description
ticker string Yes - Stock ticker
timeframe string No quarterly quarterly or annual
limit integer No 12 quarterly / 10 annual Periods to return. Values above 40 quarterly / 20 annual are clamped to the cap.
curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/fundamentals/history?ticker=AAPL&timeframe=annual&limit=10"

Response: { ticker, timeframe, count, dataSource, reason, periods[] }. count is the number
of periods returned, below limit when the provider has fewer. Periods are sorted by
periodEndDate, newest first. A ticker with no statements (an unknown symbol, an ETF or fund, a
very recent listing) returns 200 with count: 0, an empty periods and a fixed explanatory
reason; it is not a 404. dataSource is deprecated and carries no information: "" on every
period and on a non-empty envelope, null on an empty one.

The period object

Every field below is present on every period, except reportedCurrency, which is omitted when
unknown. ticker, fetchedAt and dataSource are never null. Every other field is null when the value is unavailable for that period: the provider did
not publish the line, a consistency check rejected it, or a calculation lacked an input. Null is
never zero, and never a reason to fill in a neighbouring field; the one substitution we recommend
is spelled out in the sharesOutstanding note below. On /fundamentals/history the last group is
null on every row; those fields are filled only by /fundamentals.

Identity

Field Type Description
ticker string The requested symbol.
fiscalPeriod string Q1 to Q4 on quarterly rows, FY on annual rows, on the filer's fiscal calendar (Apple's Q1 ends in December).
fiscalYear string The filer's own fiscal-year label. It can differ from the calendar year of periodEndDate: Lululemon's year ending 2025-02-02 is fiscal "2024".
periodEndDate string Last day of the period as an ISO date (2025-09-27). The field to sort and join on.
periodMonths integer Months the period covers: 3 for a quarter, 6 for a filer that reports half-years, 12 for a year. fiscalPeriod names the quarter a period ends in, so a half-year period is labelled Q2 or Q4; this field is what distinguishes the two. Null when the span cannot be established: the oldest row of a response, which has nothing behind it to measure against, and a row after a missing period whose own figures do not settle its length.
filingDate string Date the statement was filed, ISO date.
companyName string Null on history rows.

Income statement (amounts in reportedCurrency)

Field Type Description
revenue number Total revenue.
costOfRevenue number Cost of revenue. Served null, together with grossProfit and grossMargin, when the provider's line fails our consistency check: operating expenses folded into cost of revenue or the reverse, a cost of revenue below zero, or a cost of revenue larger than the period's total operating costs while its gross margin falls far below the neighbouring periods'.
grossProfit number Gross profit.
operatingIncome number Operating income. Null for a period in which the filer's own filings carry no operating-income line (common for banks, insurers and some industrial and pharmaceutical filers, which report income before taxes directly). When the filer's filings cannot be checked, the provider's figure is served.
netIncome number The provider's consolidated net income line. Not the EPS numerator.
bottomLineNetIncome number The provider's bottom-line income line, which can differ from netIncome in size and in sign; see the worked example below. Always null on rows from our fallback source.
eps number Compatibility field with a mixed basis: basic EPS, except on fallback-source history rows where it is the diluted figure when one exists. Prefer epsBasic or epsDiluted, which name their basis.
epsBasic number Basic earnings per share, as reported.
epsDiluted number Diluted earnings per share, as reported. Null when the provider reports no diluted figure.

Share counts (a number of shares)

Field Type Description
weightedAverageSharesBasic integer Basic weighted-average shares for the period. Null when the provider reports none.
weightedAverageSharesDiluted integer Diluted weighted-average shares for the period. Null when the provider reports none.
sharesOutstanding integer Deprecated, see the note below. On history rows it equals weightedAverageSharesDiluted, or the basic figure when there is no diluted one. Always null on rows from our fallback source.

Balance sheet (amounts in reportedCurrency)

Field Type Description
totalAssets number Total assets.
totalLiabilities number Total liabilities.
totalEquity number Total shareholders' equity.
currentAssets number Current assets. Null for a period in which the filer's balance sheet reports no current-assets total, as with the unclassified balance sheets of banks, insurers and most REITs. When the filer's filings cannot be checked, the provider's figure is served.
currentLiabilities number Current liabilities. Null for a period in which the filer's balance sheet reports no current-liabilities total, on the same terms as currentAssets.
cash number Cash and cash equivalents. Does not include short-term investments.
debt number Total debt as the provider reports it. On rows from our fallback source: long-term debt, or non-current liabilities when that line is absent, or total minus current liabilities.
longTermDebt number Long-term debt.

Cash flow (amounts in reportedCurrency)

Field Type Description
operatingCashFlow number Cash from operations.
investingCashFlow number Cash from investing.
financingCashFlow number Cash from financing.
capitalExpenditure number Capital expenditure, negative as an outflow. A positive provider value is treated as corrupt and served null, along with freeCashFlow. Always null on rows from our fallback source.
freeCashFlow number operatingCashFlow - abs(capitalExpenditure) when both exist, otherwise the provider's own reported free cash flow, otherwise null. Always null on rows from our fallback source.

Derived ratios (computed by us from the fields above; null when an input is null)

Field Type Description
grossMargin number grossProfit / revenue, in percent.
operatingMargin number operatingIncome / revenue, in percent.
netMargin number netIncome / revenue, in percent.
currentRatio number currentAssets / currentLiabilities.
debtToEquity number debt / totalEquity.
roe number netIncome / totalEquity in percent on annual rows. Null on quarterly history rows: it needs a twelve-month figure, which only /fundamentals carries.
roa number netIncome / totalAssets in percent, same availability as roe.

Metadata

Field Type Description
reportedCurrency string Currency of the statement amounts ("USD", "EUR", "KRW", ...). Absent when unknown.
fetchedAt integer When we fetched the row from the provider, epoch seconds.
dataSource string Deprecated. Always "".
preIpoFiling object The SEC filing a pre-IPO quarter was read from; see Pre-IPO quarters under Reading the rows. Null on every other row.

Always null on history, filled only by /fundamentals

Fields Group
revenueTTM, netIncomeTTM, epsTTM, quartersIncluded Trailing twelve months
peRatio, pbRatio, psRatio Price ratios (USD price over home-currency figures, so USD filers only)
marketCap, currentPrice USD market data

Reading the rows

  • Two sources. History rows come from our primary statement source, which fills every field
    above when the filing carries it. For tickers it does not cover, a fallback source fills the rows
    instead, and its rows are marked in the tables: bottomLineNetIncome, sharesOutstanding,
    capitalExpenditure and freeCashFlow are null on every row, debt is selected as described,
    and eps is the diluted figure where one exists. The row does not say which source served it.

  • Corrections from the filing. When the provider's figure for a period contradicts the
    company's own SEC filing for that period, and the filing settles which is right, the filing's
    figure is served instead:

    • revenue, costOfRevenue, grossProfit and operatingIncome, when the filer's own lines
      for the period are consistent with each other (gross profit plus cost of revenue equals
      revenue, and gross profit less operating expenses equals operating income) and disagree with
      the provider's. The derived margins follow.
    • weightedAverageSharesBasic, weightedAverageSharesDiluted and the EPS fields of a quarter,
      when the provider carried an earlier period's share counts forward into it and divided by them.
      On a second or third fiscal quarter the corrected counts can be the filing's year-to-date
      averages; the EPS is the quarter's.
    • The EPS fields and share counts of a fiscal year, when the provider's EPS for the year is
      explained by neither its own share count nor the filing's.
    • The EPS fields and both weighted-average share counts of a first, second or third fiscal
      quarter or a fiscal year from roughly the last three (quarters) or five (years) years, when the
      company's SEC filing states all four, in US dollars, for that exact period and they agree with each other and
      with the period's net income. Fourth quarters keep the provider's figures, because an annual
      report states no three-month EPS. A new filing's figures apply once SEC publishes them, usually
      within days; until then the provider's stand.

    A short reviewed list covers periods whose correction the provider's data cannot settle on its
    own; each entry is checked against the filing and stops applying when the provider changes the
    period. Corrected rows are not marked. The trailing sums on /fundamentals add the corrected
    figures.

  • Rows are the provider's, not deduplicated. A provider that republishes a period yields two
    rows with the same periodEndDate, and a row whose source date could not be parsed carries null
    there and sorts last. Both are rare; tolerate both.

  • Pre-IPO quarters. For a small list of recently listed companies, quarterly history includes
    a quarter from before the listing that the company filed only as the prior-year comparison column
    of a later filing, usually its first 10-Q. That row carries preIpoFiling naming the filing, and
    holds the income-statement lines the filing reports for the quarter. Its balance-sheet and
    cash-flow fields are null, because such a filing carries no quarter-end balance sheet or
    three-month cash flow for it. When the provider publishes a row for the same period, that row is
    served instead. preIpoFiling is null on every other row, including every annual row.

    Field Type Description
    preIpoFiling.form string SEC form type of the filing, for example 10-Q.
    preIpoFiling.accession string SEC accession number of the filing, 0000000000-00-000000.
    preIpoFiling.filedDate string Date the filing was filed, YYYY-MM-DD.
    preIpoFiling.note string Where in the filing the figures appear.
  • Share basis. Per-period EPS is served as the provider reports it, apart from the corrections
    from the filing above. SentiSense restates it onto a split-adjusted basis for a small list of
    named issuers and nowhere else.

    A provider that restates a company's share counts for a split can leave some older rows' EPS on
    the pre-split basis, so those rows contradict themselves. Where that has been checked against the
    company's own filing, SentiSense divides the EPS on the affected rows by the split ratio and
    marks each one with epsBasisRepair. Share counts and net income are never changed, and no row
    of any other issuer is changed.

    epsBasisRepair is null on almost every row. Null means SentiSense applied no EPS repair to that
    row. It is not a statement that the row's EPS and share count are on the same basis: a row whose
    issuer is not on the list, or whose figures did not qualify, or for which the split history could
    not be read, carries a null marker and is served exactly as the provider reports its EPS.

    Field Type Description
    epsBasisRepair.fields string[] Which EPS fields on the row were restated, in the order epsBasic, epsDiluted, eps.
    epsBasisRepair.multiplier number Restated value divided by the value the provider reported. Divide by it to recover the provider's figure.
    epsBasisRepair.splitExecutionDates string[] Execution dates of the splits the provider had not applied to this row's EPS, newest first, YYYY-MM-DD.

    The Cooper Companies (COO) is the worked example. Its share counts are restated for the
    four-for-one split of 2024-02-20 back to fiscal 2006 while the provider's EPS is restated only
    back to fiscal 2021, so the annual rows through fiscal 2020 carry epsBasisRepair with a
    multiplier of 0.25: fiscal 2020 basic EPS is served as 1.215 rather than 4.86, against the
    196.4M share count beside it. Fiscal 2021 and fiscal 2022 both carry a null marker. The 7.6x
    drop between them is a real earnings move, not a change of basis.

    epsBasisRepair describes per-period EPS only. This repair never changes epsTTM or the other
    trailing-twelve-month figures, and the marker never describes a trailing adjustment. Trailing
    figures are assembled separately from the per-period rows, and whether they carry a split
    adjustment of their own depends on which source served them, so the marker says nothing about a
    trailing window that spans one of these seams.

Earnings and share-count fields

epsBasic, epsDiluted, netIncome, bottomLineNetIncome, weightedAverageSharesBasic and
weightedAverageSharesDiluted are each the provider's own line, or the filing's where the
corrections described under Reading the rows apply. None is computed from another,
so they are not expected to reconcile arithmetically: netIncome / weightedAverageSharesDiluted
will not generally reproduce any EPS field, because the provider computes EPS from its own numerator
on its own share basis.

netIncome and the EPS fields are consolidated figures that include discontinued operations, while
revenue and operatingIncome cover continuing operations only, as GAAP presents them. For a company
that has sold or spun off a business, EPS from continuing operations is not served.

bottomLineNetIncome can differ from netIncome in both size and sign. HPE's fiscal 2025 is the
clear case: netIncome is +57,000,000 while bottomLineNetIncome is -59,000,000, alongside a
reported EPS of -0.0446. We publish both as the provider states them and make no claim about how
either reconciles with the EPS fields.

A weighted average is an average over the reporting period, not a count at period end. Neither
share field is a period-end share count, so neither is a correct input to a market capitalisation
or a book value per share.

Deprecated: sharesOutstanding

This field stops being populated on 2026-12-15. It is not a shares-outstanding count despite
its name, and it means different things on different responses: the diluted weighted average
(or the basic one where no diluted figure exists) on history rows and on latest periods served
from the statement source, a marketCap / currentPrice estimate on latest periods that carry
market data, and null on fallback-source history rows and on some explicit-period requests.
That ambiguity is why it is being retired rather than redefined.

Migrate to weightedAverageSharesDiluted, falling back to weightedAverageSharesBasic when it
is null. On every row where the old field was a share count, that gives the same number. It does
not reproduce the marketCap / currentPrice estimate: if your code depends on that one, use
marketCap and currentPrice directly.


GET /fundamentals/historical/revenue

Returns a lightweight income-statement series (revenue, gross profit, operating income, net
income, EPS) per fiscal quarter or year, wrapped in dataPoints with count and reason
(dataSource is deprecated and always empty). Covers recent periods only (roughly the last three
to four years). For longer history or the balance sheet and cash flow, use /fundamentals/history.
grossProfit is null for a period whose cost of revenue fails the consistency check described
under costOfRevenue on /fundamentals/history. Where /fundamentals/history serves a figure
corrected from the company's filing (see Corrections from the filing under
Reading the rows), this series serves the same figure for that period.

curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/fundamentals/historical/revenue?ticker=AAPL"

Short Interest & Float

GET /short-interest

Returns twice-monthly short interest data from FINRA for a stock, newest settlement date first.

curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/short-interest?ticker=AAPL&limit=24"

Parameters:

Parameter Type Required Default Description
ticker string Yes - Stock ticker symbol
limit integer No 24 Maximum number of settlement dates to return

Response:

Field Type Description
ticker string Uppercase ticker symbol
count integer Number of entries in dataPoints
dataPoints[] array One entry per settlement date, newest first
dataPoints[].shortInterest number Shares sold short and not yet covered, in shares
dataPoints[].daysToCover number shortInterest divided by avgDailyVolume
dataPoints[].avgDailyVolume number Average daily trading volume over the period, in shares
dataPoints[].settlementDate string Settlement date (ISO YYYY-MM-DD)
{
  "ticker": "AAPL",
  "dataPoints": [
    { "shortInterest": 120000000, "daysToCover": 2.5, "avgDailyVolume": 48000000, "settlementDate": "2026-01-15" }
  ],
  "count": 1
}

A ticker with no short interest data returns 200 with an empty dataPoints array and count: 0.


GET /float

Returns the free float: shares available for public trading.

curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/float?ticker=AAPL"

Parameters:

Parameter Type Required Default Description
ticker string Yes - Stock ticker symbol

Response:

Field Type Description
ticker string Uppercase ticker symbol
freeFloat number | null Free float, in shares. 0 means the symbol has no free float, as for funds such as SPY and QQQ
freeFloatPercent number | null Free float as a percentage of total shares, in percentage points (92.1 means 92.1%)
effectiveDate string | null Date the float figure applies to, as YYYY-MM-DD or YYYY-MM-DD HH:mm:ss depending on the data source
{ "ticker": "AAPL", "freeFloat": 14000000000, "freeFloatPercent": 92.5, "effectiveDate": "2026-01-15" }

A ticker with no float data returns 200 with freeFloat, freeFloatPercent and effectiveDate all null. For share counts, use weightedAverageSharesDiluted and weightedAverageSharesBasic on GET /fundamentals/history.


GET /short-volume

Returns daily short sale volume for a stock, newest date first.

curl -H "X-SentiSense-API-Key: $SENTISENSE_API_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/short-volume?ticker=AAPL&limit=90"

Parameters:

Parameter Type Required Default Description
ticker string Yes - Stock ticker symbol
limit integer No 90 Maximum number of trading days to return

Response:

Field Type Description
ticker string Uppercase ticker symbol
count integer Number of entries in dataPoints
dataPoints[] array One entry per trading day, newest first
dataPoints[].shortVolume number Shares sold short that day, in shares
dataPoints[].totalVolume number Total shares traded that day on the reporting venues, in shares; not consolidated market volume
dataPoints[].shortVolumeRatio number shortVolume as a share of totalVolume, in percentage points (45.2 means 45.2%)
dataPoints[].date string Trading day (ISO YYYY-MM-DD)
{
  "ticker": "AAPL",
  "dataPoints": [
    { "shortVolume": 7000000, "totalVolume": 15500000, "shortVolumeRatio": 45.16, "date": "2026-01-15" }
  ],
  "count": 1
}

A ticker with no short volume data returns 200 with an empty dataPoints array and count: 0.


Quote Snapshot

GET /{ticker}/quote

Returns a single-call aggregate snapshot combining the latest price (delayed 15 minutes), today's OHLC, 52-week range, market cap, and key fundamentals. Designed for detail pages that need all key stats in one request.

Authentication: API key required | Rate limit: standard quota

curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/AAPL/quote"

Response object:

Field Type Description
ticker string Ticker symbol
currentPrice number|null Regular-session price, delayed 15 minutes. During RTH (09:30 to 16:00 ET): the most recent regular-session value. Otherwise: most recent regular-session close.
change number|null currentPrice change vs previousClose
changePercent number|null currentPrice change percentage vs previousClose
volume number|null Volume for the current session
open number|null Opening price for the current session
dayHigh number|null Intraday high
dayLow number|null Intraday low
previousClose number|null Previous session close
week52High number|null 52-week high
week52Low number|null 52-week low
marketCap number|null Market capitalization (USD)
peRatio number|null Trailing P/E ratio
epsTTM number|null Earnings per share (TTM)
dividendYield number|null Annual dividend yield (decimal, e.g. 0.005)
movingAverage200Day number|null 200-day simple moving average of daily closes. null when fewer than 200 trading days of history exist (e.g. a recent IPO).
reportedCurrency string|null Currency epsTTM is reported in ("USD", "EUR", "KRW", ...), as filed. Same field and same meaning as on the fundamentals endpoints. Absent when no fundamentals are available for the ticker.
timestamp number|null When this response was served (epoch milliseconds). Not the age of the price: it tracks the current clock regardless of how old the value is.
priceAsOf number | absent When the market data behind currentPrice is from (epoch milliseconds). This is the field to read for freshness. Omitted outside regular hours, and whenever the upstream data is not dated, so treat its absence as "unknown" rather than "fresh".
extendedHours object | null Extended-hours view (pre-market or after-hours). Absent during RTH, overnight, and weekends. Same shape as on /price: { session, price, change, changePercent }.
listingStatus string | absent "DELISTED" or "PENDING_DELISTING". Present only when the symbol is delisted or pending delisting, absent otherwise.
delistedDate string | absent ISO date (YYYY-MM-DD) trading stopped. Present only alongside listingStatus: "DELISTED".
delistingReason string | absent One of acquired, take_private, bankruptcy, exchange_rule, merged. Present only alongside listingStatus: "DELISTED".

All fields except ticker are nullable. Render "--" or hide the row when a field is absent.

Null fields are omitted from the JSON. A null field is left out of the response body entirely rather than serialized as null, so the key count varies by ticker. Read defensively rather than assuming a key is present.

Foreign filers omit reportedCurrency, epsTTM and peRatio. On foreign ADR filers such as ASML and TM those three fields are absent, while price fields, marketCap and dividendYield are served normally. This is the same cross-currency rule the fundamentals endpoints follow: currentPrice is the USD ADR price and the filer's earnings are in home currency, so a trailing P/E would mix two currencies. We withhold it rather than publish a wrong number. Do not fill the gap by dividing currentPrice by a non-USD epsTTM.

Delisted symbols keep quoting their last trade. When listingStatus reads "DELISTED", every price field above (including open, dayHigh, dayLow, previousClose and volume) describes the final trading session. priceAsOf is the close of that session, which can fall a day or more before delistedDate, and extendedHours is absent. timestamp remains the serve time, so do not read it as the age of the price. The same three listing fields appear on GET /price and GET /{ticker}/profile.

Example response (after-hours):

{
  "ticker": "AAPL",
  "currentPrice": 213.45,
  "change": 1.23,
  "changePercent": 0.58,
  "volume": 48203100,
  "open": 212.10,
  "dayHigh": 214.20,
  "dayLow": 211.80,
  "previousClose": 212.22,
  "week52High": 237.23,
  "week52Low": 164.08,
  "marketCap": 3280000000000,
  "peRatio": 32.1,
  "epsTTM": 6.65,
  "dividendYield": 0.0044,
  "movingAverage200Day": 198.42,
  "reportedCurrency": "USD",
  "timestamp": 1745600000000,
  "extendedHours": {
    "session": "post",
    "price": 214.10,
    "change": 0.65,
    "changePercent": 0.30
  }
}

ETF tickers: This endpoint is stock-only. Calling it with an ETF ticker (e.g. VTI, SPY) returns 400 ticker_is_etf with a pointer to GET /etfs/{ticker}/quote which returns AUM, expense ratio, NAV, and inception date instead of market cap / P/E / EPS. The error body also carries a seeInstead array holding that exact path, so a client can follow it without string-matching the message:

{
  "error": "ticker_is_etf",
  "message": "SPY is an ETF; use /api/v1/etfs/SPY/quote",
  "seeInstead": ["/api/v1/etfs/SPY/quote"]
}

Rate-limit note: Cached for 15 seconds server-side. Each call still counts toward your monthly quota.


Company KPIs

A KPI is a per-company key performance indicator series: the operating numbers a company reports about itself, quarter after quarter, in a chartable shape. Financial statements describe what every company reports; KPIs describe what a specific company reports. The set covers GAAP line items and the company-specific non-GAAP metrics that move a stock, such as iPhone unit sales, Tesla deliveries, AWS revenue, and Netflix paid net adds. Every series is curated per company from earnings filings and press releases, and carries a citation to the filing it came from.

The endpoints below cover the whole surface: GET /with-kpis enumerates coverage, GET /{ticker}/kpis/types lists one company's metrics, and GET /{ticker}/kpis returns the series. The reference for each follows this section.

Worked examples: the Company KPI API guide.

The three-step KPI workflow

Discovery first, then metadata, then data. Steps 1 and 2 are Discovery tier: an API key is required for identity, but neither call consumes monthly quota, so a client can refresh the shape of its universe far more often than it fetches series payloads. Only step 3 is quota-gated and PRO-gated.

Step 1: discover which companies have coverage. Call once at startup and cache it. Enumerating coverage is the supported alternative to probing tickers one at a time and collecting 404s.

curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/with-kpis"
{
  "count": 947,
  "tickers": [
    { "ticker": "AAPL", "companyName": "Apple Inc.", "lastUpdated": "2026-01-30", "kpiCount": 8 },
    { "ticker": "ABBV", "companyName": "AbbVie Inc.", "lastUpdated": "2026-01-25", "kpiCount": 6 }
  ]
}

Step 2: list one company's KPI types. Metadata tuples only, with no series payload attached. Use it to decide what is worth rendering, or to let an agent choose, before committing to the heavy call.

curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/AAPL/kpis/types"
[
  { "id": "iphone_revenue", "name": "iPhone Revenue", "category": "product_revenue", "chartType": "bar" },
  { "id": "services_revenue", "name": "Services Revenue", "category": "segment_revenue", "chartType": "line" }
]

Step 3: fetch the series. The endpoint takes only the ticker and returns every curated series for it; select the ones you need by id from Step 2. Points are ordered newest to oldest: the first element is the most recently reported period.

curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/AAPL/kpis"
{
  "isPreview": false,
  "previewReason": null,
  "data": {
    "ticker": "AAPL",
    "companyName": "Apple Inc.",
    "cik": "0000320193",
    "lastUpdated": "2026-01-30",
    "kpis": [
      {
        "id": "iphone_revenue",
        "name": "iPhone Revenue",
        "category": "product_revenue",
        "unit": "USD",
        "displayFormat": "currency_abbreviated",
        "chartType": "bar",
        "values": [
          { "period": "Q4 FY2025", "date": "2025-09-27", "value": 50000000000, "isEstimate": null },
          { "period": "Q1 FY2026", "date": "2025-12-27", "value": 85000000000, "isEstimate": null }
        ],
        "sourceRef": "Apple 8-K Q1 FY2026 press release",
        "discontinued": false,
        "discontinuedNote": null
      }
    ]
  }
}

Example values throughout this section are illustrative, not live readings.


GET /{ticker}/kpis

Returns company-specific KPI time-series for a ticker. KPIs are curated GAAP and non-GAAP metrics extracted from earnings filings and press releases (e.g. iPhone unit sales, Tesla deliveries, AWS revenue, Netflix paid net adds).

Authentication: API key required on every call; PRO for the series data. A free key receives isPreview: true with the company metadata and an empty kpis list, which is enough to detect coverage and gate the UI. Calls without a key return 401 api_key_required.

Parameters:

Parameter Type Required Default Description
ticker path Yes - Stock ticker symbol

Coverage today: near-complete for the S&P 500 plus an extended universe of 900+ tickers, and growing. Entries can briefly show kpiCount: 0 while curation for a newly added company is in flight; skip those when enumerating. Roadmap: coverage extending to the long-tail of US tickers; some tickers may return 404 Not Found until curated. Use GET /with-kpis to enumerate the current set.

Example Request:

curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/AAPL/kpis"

Response Schema (envelope):

Field Type Description
isPreview boolean true when the caller is on the FREE tier
previewReason string "PRO_REQUIRED" or null
upgrade object Present only when isPreview is true. Carries plan, message, price, url and relay: surface message and url to your user in one line, then continue with the preview data
data.ticker string Stock ticker
data.companyName string Company name
data.cik string SEC Central Index Key (when available)
data.lastUpdated string ISO date of the last KPI refresh
data.kpis array of KpiSeries Time-series objects (PRO only; empty in preview)

KpiSeries object:

Field Type Description
id string Stable per-ticker identifier, e.g. "iphone_revenue"
name string Human-readable name, e.g. "iPhone Revenue"
category string Logical category: "product_revenue", "segment_revenue", "unit_economics", etc.
unit string Unit of measurement: "USD", "units", "subscribers", "%", etc.
displayFormat string Display hint: "currency_abbreviated", "number_abbreviated", "percent", etc.
chartType string Default chart type: "bar" or "line"
values array of KpiDataPoint Time-series data points, newest to oldest (first element is most recent)
sourceRef string Citation for the source filing
discontinued boolean or null true when the company has stopped reporting this metric; null or false otherwise
discontinuedNote string Optional human-readable note about discontinuation

KpiDataPoint object:

Field Type Description
period string Fiscal period label, e.g. "Q2 FY2026"
date string ISO date of the period close, e.g. "2025-12-27"
value number Numeric value for the period
isEstimate boolean|null true for preliminary or estimated values; usually null

Example Response (truncated):

{
  "isPreview": false,
  "previewReason": null,
  "data": {
    "ticker": "AAPL",
    "companyName": "Apple Inc.",
    "cik": "0000320193",
    "lastUpdated": "2026-04-30",
    "kpis": [
      {
        "id": "iphone_revenue",
        "name": "iPhone Revenue",
        "category": "product_revenue",
        "unit": "USD",
        "displayFormat": "currency_abbreviated",
        "chartType": "bar",
        "values": [
          { "period": "Q1 FY2025", "date": "2024-12-28", "value": 69702000000, "isEstimate": null },
          { "period": "Q2 FY2025", "date": "2025-03-29", "value": 46841000000, "isEstimate": null },
          { "period": "Q3 FY2025", "date": "2025-06-28", "value": 39286000000, "isEstimate": null },
          { "period": "Q4 FY2025", "date": "2025-09-27", "value": 49025000000, "isEstimate": null },
          { "period": "Q1 FY2026", "date": "2025-12-27", "value": 85269000000, "isEstimate": null }
        ],
        "sourceRef": "Apple 8-K Q1 FY2026 press release",
        "discontinued": false,
        "discontinuedNote": null
      }
    ]
  }
}

GET /with-kpis

Lists every ticker with curated KPI coverage, sorted alphabetically. Builder discovery use case: render a supported-tickers page or seed a watchlist without 404-probing one ticker at a time.

Authentication: API key required. No monthly quota cost (Discovery tier: the call registers identity for abuse tracking but does not burn the per-month quota; rate-limit-per-minute still applies).

Parameters: None.

Example Request:

curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/with-kpis"

Response Schema:

Field Type Description
count int Total number of tickers with curated KPI coverage
tickers array of KpiCoverageEntry Listing sorted alphabetically by ticker

KpiCoverageEntry object:

Field Type Description
ticker string Stock ticker
companyName string Company name
lastUpdated string ISO date of the last KPI refresh for this ticker
kpiCount int Number of distinct KPI series available for this ticker

Example Response (truncated):

{
  "count": 947,
  "tickers": [
    { "ticker": "A",    "companyName": "Agilent Technologies, Inc.", "lastUpdated": "2026-04-12", "kpiCount": 5 },
    { "ticker": "AAPL", "companyName": "Apple Inc.",                 "lastUpdated": "2026-04-30", "kpiCount": 8 },
    { "ticker": "ABBV", "companyName": "AbbVie Inc.",                "lastUpdated": "2026-04-22", "kpiCount": 6 }
  ]
}

GET /{ticker}/kpis/types

Lists the KPI metadata tuples available for a ticker without paying the cost of the full series payload. Mirrors the /api/v1/insights/stock/{ticker}/types precedent. Useful for letting an agent or UI decide which KPIs to render before fetching the data.

Authentication: API key required. No monthly quota cost (Discovery tier).

Parameters:

Parameter Type Required Default Description
ticker path Yes - Stock ticker symbol

Example Request:

curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/AAPL/kpis/types"

Response Schema (bare array):

Field Type Description
id string Stable per-ticker identifier
name string Human-readable name
category string Logical category
chartType string Default chart type: "bar" or "line"

Example Response:

[
  { "id": "iphone_revenue",   "name": "iPhone Revenue",   "category": "product_revenue", "chartType": "bar"  },
  { "id": "services_revenue", "name": "Services Revenue", "category": "segment_revenue", "chartType": "line" },
  { "id": "mac_revenue",      "name": "Mac Revenue",      "category": "product_revenue", "chartType": "bar"  }
]

Returns 404 Not Found when the ticker has no curated KPIs.


Reading a KPI point

Periods are fiscal, not calendar. period is a display label such as "Q1 FY2026"; date is the ISO date on which that period closed. The two routinely disagree with the calendar: a fiscal Q1 can close in December. Sort and align on date, label with period, and do not assume a fiscal quarter maps to a calendar quarter when comparing two companies.

Units live on the series, not on the point. value is a raw number. Its meaning comes from unit on the parent series ("USD", "units", "subscribers", "%"), and displayFormat is the matching rendering hint (currency_abbreviated, number_abbreviated, percent). Read the two together rather than inferring a unit from the series name. chartType carries the intended default rendering, bar or line.

Points run newest to oldest. The first element is the most recently reported period, so a sequential delta is the first two elements, and a year-over-year delta is the first element against the one four positions later (index 0 against index 4) when the series has no gaps. Series lengths vary by company and metric; check the length before indexing.

Two flags change how a series should be displayed. isEstimate is true for a preliminary or estimated value and is usually null otherwise. discontinued is true once a company stops reporting a metric, with an optional discontinuedNote; a discontinued series remains valid history but should not sit on a live dashboard as though a new print is coming.

Every series carries sourceRef, a citation for the filing the numbers came from. Surface it wherever a user might ask where a number originated.

Dual-class tickers resolve server-side. KPI endpoints accept the secondary share class and resolve it to the curated primary, so GOOG reaches Alphabet's series and BRK-B reaches Berkshire's. See Ticker symbols for the aliasing rules, including the pairs that are tracked separately rather than aliased.

Patterns for builders

Quarter-over-quarter and year-over-year deltas. The series arrives ordered newest first, so deltas are arithmetic rather than an extra request: the first two points for the sequential move, the first against the point four positions later for the annual move. Ranking a watchlist by acceleration in a company-specific metric surfaces moves that a price screen does not.

Earnings-eve reads. Combine GET /api/v1/calendar/earnings with a watchlist to find which companies report next, then load their KPI series to show which operating numbers matter and how they have trended into the print. Because coverage discovery and KPI types cost no monthly quota, the watchlist intersection can refresh far more often than the series fetch.

Pairing KPIs with sentiment. Fetch the reported operating number from the KPI endpoints and the market's reading from GET /api/v2/metrics/entity/{entityId}/metric/{metricType}, where metricType is mentions, sentiment, sentisense, or social_dominance. Metric points are time-ascending with a flat value scalar, so they plot directly against a KPI series. A core metric accelerating while sentiment fades, or the reverse, is a divergence a price chart does not show.

Cache by reporting cadence. Most KPI series change only when a company files, which for the majority of metrics means once a quarter. Cache the coverage list and the type list on a daily cadence, and refresh a company's series around its reporting date rather than on every page view. lastUpdated on both the coverage entry and the series payload tells you when a refresh actually landed.


Sentiment

GET /{ticker}/sentiment

Returns the stock's headline sentiment picture in one call: the proprietary SentiSense Score, its
30-day regime and direction, a daily sparkline, where the conversation is happening by source, the
stories driving it, and curated peer tickers.

This is the endpoint the Developer Console hands you as your first call.

Authentication: API key required. Available in full on the Free tier.

Parameters:

Parameter Type Required Default Description
ticker path Yes - Stock ticker symbol

Example Request:

curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \
  "https://app.sentisense.ai/api/v1/stocks/AAPL/sentiment"

When there is nothing to return: a 404 whose error is either entity_not_found (no stock is tracked under that symbol; the body carries up to three suggestions, so resolve with GET /api/v1/kb/entities/search?q= and retry) or no_coverage (the symbol is tracked, we hold no sentiment record for it, and a different spelling will not help). See Two kinds of 404.

Response: { isPreview, previewReason, data }. Every field below lives under data. The endpoint is available in full on every tier and still uses the wrapper, so an API-key caller always gets isPreview: false and previewReason: null. Unwrap first: the Score is at data.sentisenseScore, and reading sentisenseScore off the root returns nothing.

Response Schema:

Field (under data) Type Description
ticker string Ticker symbol
companyName string Company name
asOf string ISO date (YYYY-MM-DD) the data is current as of
sentisenseScore number or null Today's SentiSense Score (sentiment x mentions composite, unbounded). Null until today's reading lands, see the note below
sentisenseScoreAvg30d number 30-day average Score, the stable regime figure
sentisenseScoreDelta30d number Change in the Score over 30 days
scoreLabel string Seven-band label of the 30-day average: "Strong Bearish", "Bearish", "Slightly Bearish", "Neutral", "Slightly Bullish", "Bullish" or "Strong Bullish"
direction string "Bullish", "Neutral" or "Bearish", from the 30-day average
latestDirection string or null Same three bands, from today's read. Null in lockstep with sentisenseScore
trend string "UP", "DOWN" or "FLAT"
scoreSparkline number[] Daily Score series
mentions number or null Mention volume of the latest New York daily bucket with data: today's once it lands, otherwise an earlier day, which narrative and faq name; null when there is none
mentionsAvg30d number 30-day average mentions per day
socialDominance number Latest share of voice, as a fraction (0.021 = 2.1%)
bySource[] array Per-source tone, loudest source first: source, direction, mentionShare (whole-number percent; each share is rounded independently, so the array can sum to 99 or 101), value (exact polarity, -1 to 1)
relatedTickers[] array Curated peer tickers: ticker, name
drivers[] array Top story drivers: title, tone (-1 to 1)
narrative string Short plain-language summary of why the Score sits where it does
faq[] array Question and answer pairs covering the common asks for this ticker

sentisenseScore and latestDirection are today's reading, and are null until the day's first analytics run lands (mid-morning ET, later at weekends). Poll before that and every ticker returns null for these two, which is a timing state and not an outage. The rest of the response is unaffected: scoreLabel, direction and sentisenseScoreAvg30d are all computed from the 30-day average, so prefer those when you need a headline that is always present. A null here means "no reading yet", never a Score of zero. A measured 0.0 is served as 0.0, so do not coerce null to 0, and do not infer absence by thresholding the 30-day average, which would suppress genuine neutrals.

Example Response:

{
  "isPreview": false,
  "previewReason": null,
  "data": {
    "ticker": "AAPL",
    "companyName": "Apple Inc.",
    "asOf": "2026-08-02",
    "sentisenseScore": 41.2,
    "sentisenseScoreAvg30d": 33.8,
    "sentisenseScoreDelta30d": 7.4,
    "scoreLabel": "Bullish",
    "direction": "Bullish",
    "latestDirection": "Bullish",
    "trend": "UP",
    "scoreSparkline": [28.1, 30.4, 31.9, 35.2, 41.2],
    "mentions": 1840,
    "mentionsAvg30d": 1512,
    "socialDominance": 0.081,
    "bySource": [
      { "source": "News",   "direction": "Bullish", "mentionShare": 58, "value": 0.1889 },
      { "source": "Reddit", "direction": "Neutral", "mentionShare": 21, "value": 0.0428 },
      { "source": "X",      "direction": "Bullish", "mentionShare": 10, "value": 0.1809 }
    ],
    "relatedTickers": [ { "ticker": "MSFT", "name": "Microsoft Corporation" } ],
    "drivers": [ { "title": "Apple raises services guidance", "tone": 0.44 } ],
    "narrative": "Sentiment has strengthened over the past month, led by news coverage.",
    "faq": [ { "question": "Is AAPL bullish or bearish?", "answer": "..." } ]
  }
}

Returns 404 Not Found when the ticker has no sentiment coverage.

This is the single-stock read. Two market-wide counterparts live in the Market Mood API: /api/v1/sentiment/sectors ranks the 11 GICS sectors against the market's own tone, and /api/v1/sentiment/breadth gives the bullish/neutral/bearish share of the roughly 1,000 covered stocks, the sentiment analogue of an advance/decline line.

Note on the response envelope: search-engine crawlers receive the same envelope with
isPreview: true and each per-source value set to null; direction and mention share are always
present. API-key callers on any tier receive the full payload with isPreview: false.

Try It

Test endpoints directly from your browser. Paste your API key once: it's saved locally and shared across all widgets. Get a free key

GET/api/v1/stocks/

List all available stock tickers

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks"
Enter your API key to send requests

GET/api/v1/stocks/detailed

All stocks with company details

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/detailed"
Enter your API key to send requests

GET/api/v1/stocks/popular

Popular stock tickers

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/popular"
Enter your API key to send requests

GET/api/v1/stocks/popular/detailed

Popular stocks with details

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/popular/detailed"
Enter your API key to send requests

GET/api/v1/stocks/images

Batch company logo URLs

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/images?tickers=AAPL%2CTSLA"
Enter your API key to send requests

GET/api/v1/stocks/descriptions

Company profiles with branding

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/descriptions?tickers=AAPL%2CTSLA"
Enter your API key to send requests

GET/api/v1/stocks/{ticker}/similar

Peer/similar stocks

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/AAPL/similar"
Enter your API key to send requests

GET/api/v1/stocks/{ticker}/profile

Company profile (CEO, sector, etc.)

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/AAPL/profile"
Enter your API key to send requests

GET/api/v1/stocks/{ticker}/entities

Related ontology entities

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/AAPL/entities"
Enter your API key to send requests

GET/api/v1/stocks/{ticker}/graph

Knowledge graph around a stock

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/AAPL/graph"
Enter your API key to send requests

GET/api/v1/stocks/{ticker}/ai-summary

AI-generated stock analysis report

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/AAPL/ai-summary"
Enter your API key to send requests

GET/api/v1/stocks/{ticker}/metrics/{metricType}/breakdown

Sentiment/mention metrics breakdown

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/AAPL/metrics/sentiment/breakdown"
Enter your API key to send requests

GET/api/v1/stocks/price

Latest price for a single stock, delayed 15 minutes

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/price?ticker=AAPL"
Enter your API key to send requests

GET/api/v1/stocks/prices

Latest prices for multiple stocks, delayed 15 minutes

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/prices?tickers=AAPL%2CTSLA%2CNVDA"
Enter your API key to send requests

GET/api/v1/stocks/chart

Historical OHLCV chart data

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/chart?ticker=AAPL&timeframe=1M"
Enter your API key to send requests

GET/api/v1/stocks/market-status

Current market open/closed status

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/market-status"
Enter your API key to send requests

GET/api/v1/stocks/fundamentals

Financial statement data

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/fundamentals?ticker=AAPL"
Enter your API key to send requests

GET/api/v1/stocks/fundamentals/periods

Available fiscal periods

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/fundamentals/periods?ticker=AAPL"
Enter your API key to send requests

GET/api/v1/stocks/fundamentals/current

Trailing P/E, P/S and EPS profile

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/fundamentals/current?ticker=AAPL"
Enter your API key to send requests

GET/api/v1/stocks/fundamentals/history

Multi-period statement history (up to 40 quarters or 20 years)

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/fundamentals/history?ticker=AAPL"
Enter your API key to send requests

GET/api/v1/stocks/fundamentals/historical/revenue

Historical revenue data

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/fundamentals/historical/revenue?ticker=AAPL"
Enter your API key to send requests

GET/api/v1/stocks/short-interest

Short interest metrics

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/short-interest?ticker=AAPL"
Enter your API key to send requests

GET/api/v1/stocks/float

Float information

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/float?ticker=AAPL"
Enter your API key to send requests

GET/api/v1/stocks/short-volume

Short volume data

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/short-volume?ticker=AAPL"
Enter your API key to send requests

GET/api/v1/stocks/{ticker}/quote

Aggregate quote snapshot (price, OHLC, 52W, fundamentals)

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/AAPL/quote"
Enter your API key to send requests

GET/api/v1/stocks/{ticker}/kpis

Company-specific KPI time-series (PRO)

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/AAPL/kpis"
Enter your API key to send requests

GET/api/v1/stocks/with-kpis

List every ticker with curated KPI coverage (key required, no quota cost)

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/with-kpis"
Enter your API key to send requests

GET/api/v1/stocks/{ticker}/kpis/types

Lightweight KPI metadata tuples for a ticker (key required, no quota cost)

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/AAPL/kpis/types"
Enter your API key to send requests

GET/api/v1/stocks/{ticker}/sentiment

SentiSense Score, 30-day direction, per-source tone, and story drivers

Try It
curl -H "X-SentiSense-API-Key: ss_live_YOUR_KEY" \ "https://app.sentisense.ai/api/v1/stocks/AAPL/sentiment"
Enter your API key to send requests