Skip to content
← All recipes

Embed a Market Data Widget

≈ 2 hours

Embed a live stock ticker, price charts, or a top-movers board directly in your app — no sub-accounts required. Use a read-only pk_data_ key for low-stakes public widgets; production apps should proxy market data through their backend.

The flow

StepEndpoint / EventWhat it does
1POST /api-keys/data-keyCreate a read-only pk_data_ key for widget use (no trading, funds, or PII access).
2GET /market/quotes?symbols=A,B,CLive prices for up to 50 symbols in one call. Poll every 15–30 s.
3GET /stocks/{symbol}/chart?period=1MPre-shaped chart data (labels, prices, volumes) per period.
4GET /stocks/{symbol}/history?period=1MRaw OHLCV candles for custom chart rendering.
5GET /market/movers?direction=gainersTop gainers/losers by exchange. Refresh once per minute.
6GET /market/statusShow open/closed state (and a countdown via nextOpen) before displaying prices.
7GET /companies/{symbol}Company profile, fundamentals, logo URL, recent corporate actions.

Implementation

javascript
// pk_data_ keys are read-only — fine for a public widget.
// Production apps: proxy via your backend instead (embedded keys share your rate-limit bucket).
const DATA_KEY = 'pk_data_xxxxxxxxxxxxxxxx'; // from POST /api-keys/data-key
const BASE     = 'https://mystocks.africa/api/v1/partner';
const h        = { 'x-api-key': DATA_KEY };

// Ticker widget — poll every 15–30 s during market hours
async function refreshTicker(symbols) {
  const { data } = await fetch(
    `${BASE}/market/quotes?symbols=${symbols.join(',')}`, { headers: h }
  ).then(r => r.json());
  return data.map(q => ({ symbol: q.symbol, price: q.usdPrice, changePct: q.changePct }));
}

// Movers board — refresh once per minute
async function topMovers(exchange) {
  const { data, meta } = await fetch(
    `${BASE}/market/movers?exchange=${exchange}&direction=gainers&limit=10`, { headers: h }
  ).then(r => r.json());
  return { rows: data, total: meta.totalCount };
}

Common mistakes

  • Embedding a pk_data_ key in a production mobile app. The key is extractable, shares your full key’s rate-limit bucket, and rotating it breaks every shipped install — proxy through your backend or mint short-lived /oauth/token tokens.
  • Polling faster than the data refreshes. Prices update roughly every 15 minutes during market hours — sub-30-second polling burns rate limit for nothing.
  • Ignoring market status. Show CLOSED (with nextOpen countdown) instead of a frozen price that looks broken.
  • Calling a write endpoint with the data key — it returns 403 FORBIDDEN; data keys are market-data GETs only.

Prove it in sandbox first

  • 1.Data keys exist in production only; for sandbox experiments just use your sk_sandbox_ key against the same market-data endpoints.
  • 2.Prices are live read-through from production in sandbox — what you render is what production users would see.