An investor relations page has three market data modules: a share price, a price chart, and a financials tab. Firms that build IR websites for small public companies rebuild those three things for every client, and the same questions come up every time. Does the price need to be real time? How much history does the chart need? Can the financials update themselves instead of being hand-edited every quarter? And what will the client's counsel ask about licensing? This post walks through each module with concrete endpoints, using SiftingIO's stocks and fundamentals API as the working example, and ends with a checklist you can paste into a proposal.
The share-price module: delayed or real time#
The first client question is usually 'can visitors see the live price?' Official real-time last-sale data is licensed by the listing venue, and redistributing it to anonymous website visitors is the expensive case: display agreements, per-user reporting, and monthly redistribution fees, all negotiated before the widget ships. That pricing exists because real-time redistribution is built for trading screens, and an IR page is not one.
A 15-minute delayed quote is the standard answer for IR pages, and it's usually the right one. Nobody executes a trade from an IR page. A visitor wants the level, the day's change, and confidence that the number is current enough to be honest. Delayed display carries far lighter terms, and the page should state plainly that the price is delayed and when it was last updated.
A third option is an aggregated reference price. SiftingIO publishes one consensus price per ticker, formed as a volume-and-reputation-weighted median across multiple independent venues rather than a pass-through from any single source. It is a reference value, not an official exchange-of-record print, and it should be labeled as one. For an IR widget that job description fits well: a clearly labeled indicative price with a timestamp.
The call itself is one endpoint (AAPL stands in for the client's ticker throughout):
curl -H "X-API-Key: $SIFTING_KEY" \
"https://api.sifting.io/v1/last/trade/stocks/AAPL"
The response carries the latest price, size, and a millisecond timestamp. Poll it from your server on the schedule you advertise, cache the result, and render the cached value to every visitor.
The price chart: five years of daily OHLCV#
A five-year daily chart needs roughly 1,260 trading days of bars, which is a one-time backfill plus one new bar per day. Daily bars are the correct interval for an IR chart; intraday granularity adds cost and noise without helping the visitor.
curl --compressed -H "X-API-Key: $SIFTING_KEY" \
"https://api.sifting.io/v1/hist/stocks/AAPL/bars?interval=1d&limit=2000"
Two mechanics matter here. The bars endpoint requires gzip, so send Accept-Encoding: gzip (curl's, compressed flag does this); without it the API returns 406 gzip_required instead of data. And the page size runs up to 2,000 bars per request, 1,000 by default, so a five-year daily pull of about 1,260 bars comes back in a single call at limit=2000. For longer or intraday ranges, paging is cursor-based: pass meta.next_cursor back as the cursor parameter until it returns null.
Check history depth against the plan before quoting the build. On SiftingIO the free tier reaches back one month and Builder one year; full history starts at the Pro tier. A five-year chart therefore sets the plan floor for the project, and that belongs in the proposal rather than in a surprise invoice later. Once the backfill is stored, a nightly job appends the newest bar and the chart maintains itself. Lightweight Charts or any candlestick library renders the array directly.
A financials tab that updates itself#
The financials tab is where IR sites rot. A hand-edited table of quarterly numbers is accurate on launch day and wrong two quarters later. The fix is to render the tab from filing data keyed by ticker, so a new 10-Q appears because it was filed, without anyone touching the page.
Three endpoint families cover it. The filings list returns recent SEC filings with form types and dates, ready to render as a documents table:
curl -H "X-API-Key: $SIFTING_KEY" \
"https://api.sifting.io/v1/fnd/stocks/AAPL/filings"
The endpoint accepts form and date filters, so the tab can separate 10-K and 10-Q reports from 8-K current reports; parameter details are in the docs. For earnings specifically, /v1/fnd/stocks/AAPL/earnings returns the 8-K item 2.02 earnings releases, which is exactly the press-release feed most IR pages want.
For headline numbers, /v1/fnd/stocks/AAPL/ratios returns standard fundamental ratios, and /v1/fnd/stocks/AAPL/financials/{concept} returns a single XBRL concept, revenue for example, across reporting periods. Values arrive as { value, unit } pairs tagged with SEC period codes like CY2024Q3, so building a revenue-by-quarter table means iterating periods rather than parsing raw XBRL. The XBRL financials calls, the full bundle and the single-concept endpoint, require gzip the same way the bars do; the filings, earnings, and ratios lists do not.
Licensing and attribution, answered honestly#
IR builders field the same compliance questions on every project, and vague answers erode trust. The honest ones:
Real-time official data needs a license. If the client insists on a true real-time exchange-of-record price, that is a direct agreement with the listing venue, with fees and audit terms to match. Most small-cap clients drop the requirement once the cost is on the table.
A reference price must be labeled. An aggregated consensus price is a synthetic reference value. That is a strength for an informational page, because it is filtered across venues rather than tied to one print, but the page should say 'indicative, delayed' or similar, show an as-of timestamp, and carry the standard information-only disclaimer. It is a price to display and inform with, never a feed to execute against, and the page should not imply otherwise.
Attribution depends on the contract. Some data agreements require a visible credit line, some restrict how the source may be named, some are silent. Read the redistribution language of whatever provider backs the widget before promising a white-label build, and put the answer in the proposal so counsel sees it early.
Common pitfalls#
Calling the API from the browser. A widget that fetches the quote per page view exposes the sft_ API key in the page source and spends quota on every visitor. Twenty thousand monthly page views is twenty thousand calls; a server-side poll every 15 minutes is under 3,000 calls a month and serves any number of visitors from cache. Always proxy through the server.
Missing gzip on heavy endpoints. Historical bars and the XBRL financials endpoints return 406 gzip_required when the request lacks Accept-Encoding: gzip. The error gets misread as a bad ticker or an auth problem; it is a missing header.
The weekend freeze. A price that hasn't moved since Friday's close looks broken on Sunday. Query /v1/fnd/markets/us_equities/status and render the market state next to the price. 'Market closed, last updated Friday 4:00 p.m. ET' reads as correct; a silent stale number reads as a bug. The same status endpoint covers holidays and half days.
The investor relations page build checklist#
A version to paste into the proposal:
- Share price: delayed or labeled reference price, polled server-side on the advertised schedule, cached, rendered with an as-of timestamp and market open/closed state. Real-time official quotes excluded unless the client licenses them directly.
- Chart: five years of daily OHLCV bars, backfilled once with cursor pagination and gzip, appended nightly. Plan tier chosen for full history depth.
- Financials tab: filings table (10-K, 10-Q, 8-K) and earnings releases pulled by ticker on a daily schedule; headline ratios and revenue-by-quarter from XBRL concepts. No hand-edited numbers.
- Compliance: indicative-price label, information-only disclaimer, attribution per the data agreement, API key kept server-side.
- Ops: rate-limit headers (X-RateLimit-Remaining, Retry-After) logged, refresh jobs alerting on failure, a monthly check that filings are still flowing.
Every line above maps to an endpoint shown in this post, which is the point: an IR page is a small, well-defined data product. Most of the build risk sits in the decisions above, and settling them in the proposal is cheaper than settling them in week three.
Read the docs for the full endpoint reference and response schemas.

