Skip to main content
This guide shows how to build a price ticker that stays current throughout the NGX trading day. Because equity prices refresh every 20 minutes on our end, polling every 5 minutes gives you fresh data without wasting quota. Endpoints used:
  • GET /companies (Free plan) — fetch prices for all or filtered stocks
  • GET /companies/:symbol (Starter plan) — fetch a single stock’s full quote

How it works

  1. Fetch current prices on page load
  2. Re-fetch on a fixed interval (5 minutes recommended)
  3. Display the updated values — highlight the change direction if you like
  4. Stop polling when the user leaves or the page unmounts
The last_updated field in every response tells you exactly when the price was last written, so you can show users how fresh the data is.

Fetch prices for a watchlist

Use GET /companies with a search or sector filter, or just fetch the full list and filter client-side.
const API_KEY = 'ngm_live_YOUR_KEY';

async function fetchPrices(symbols) {
  // Fetch all companies, then filter to your watchlist
  const res = await fetch(
    'https://api.ngnmarket.com/v1/companies?limit=200',
    { headers: { Authorization: `Bearer ${API_KEY}` } }
  );
  const { data } = await res.json();
  return data.companies.filter(c => symbols.includes(c.symbol));
}

const watchlist = ['DANGCEM', 'GTCO', 'AIRTELAFRI', 'MTNN', 'ZENITHBANK'];
const prices = await fetchPrices(watchlist);

Sample response (trimmed)

{
  "success": true,
  "data": {
    "companies": [
      {
        "symbol": "DANGCEM",
        "company_name": "Dangote Cement Plc",
        "sector": "Industrial Goods",
        "current_price": 302.50,
        "price_change": 4.00,
        "price_change_percent": 1.34,
        "volume": 812400,
        "market_cap": 5150820750000,
        "last_updated": "2026-04-21T11:40:00.000Z"
      },
      {
        "symbol": "GTCO",
        "company_name": "Guaranty Trust Holding Co",
        "sector": "Financial Services",
        "current_price": 62.10,
        "price_change": -0.40,
        "price_change_percent": -0.64,
        "volume": 3201000,
        "market_cap": 1831545000000,
        "last_updated": "2026-04-21T11:40:00.000Z"
      }
    ]
  }
}

Poll on an interval (vanilla JavaScript)

JavaScript
const API_KEY  = 'ngm_live_YOUR_KEY';
const SYMBOLS  = ['DANGCEM', 'GTCO', 'AIRTELAFRI', 'MTNN', 'ZENITHBANK'];
const INTERVAL = 5 * 60 * 1000; // 5 minutes in ms

async function fetchPrices() {
  const res = await fetch(
    'https://api.ngnmarket.com/v1/companies?limit=200',
    { headers: { Authorization: `Bearer ${API_KEY}` } }
  );
  const { data } = await res.json();
  return data.companies.filter(c => SYMBOLS.includes(c.symbol));
}

function renderTicker(prices) {
  prices.forEach(({ symbol, current_price, price_change_percent, last_updated }) => {
    const el = document.getElementById(`ticker-${symbol}`);
    if (!el) return;
    el.querySelector('.price').textContent = `₦${current_price.toFixed(2)}`;
    el.querySelector('.change').textContent =
      `${price_change_percent >= 0 ? '+' : ''}${price_change_percent.toFixed(2)}%`;
    el.querySelector('.change').className =
      `change ${price_change_percent >= 0 ? 'up' : 'down'}`;
    el.querySelector('.updated').textContent =
      `Updated ${new Date(last_updated).toLocaleTimeString('en-NG')}`;
  });
}

// Initial load
fetchPrices().then(renderTicker);

// Refresh every 5 minutes
const timer = setInterval(() => fetchPrices().then(renderTicker), INTERVAL);

// Clean up when the page is closed
window.addEventListener('beforeunload', () => clearInterval(timer));

React component

React
import { useEffect, useState, useRef } from 'react';

const API_KEY  = 'ngm_live_YOUR_KEY';
const SYMBOLS  = ['DANGCEM', 'GTCO', 'AIRTELAFRI', 'MTNN', 'ZENITHBANK'];
const INTERVAL = 5 * 60 * 1000; // 5 minutes

async function fetchPrices() {
  const res = await fetch(
    'https://api.ngnmarket.com/v1/companies?limit=200',
    { headers: { Authorization: `Bearer ${API_KEY}` } }
  );
  const { data } = await res.json();
  return data.companies.filter(c => SYMBOLS.includes(c.symbol));
}

export function PriceTicker() {
  const [prices, setPrices]   = useState([]);
  const [loading, setLoading] = useState(true);
  const timerRef              = useRef(null);

  useEffect(() => {
    // Load on mount
    fetchPrices().then(p => { setPrices(p); setLoading(false); });

    // Poll every 5 minutes
    timerRef.current = setInterval(
      () => fetchPrices().then(setPrices),
      INTERVAL
    );

    return () => clearInterval(timerRef.current); // clean up on unmount
  }, []);

  if (loading) return <p>Loading prices…</p>;

  return (
    <table>
      <thead>
        <tr>
          <th>Symbol</th>
          <th>Price (₦)</th>
          <th>Change</th>
          <th>Last updated</th>
        </tr>
      </thead>
      <tbody>
        {prices.map(({ symbol, current_price, price_change_percent, last_updated }) => (
          <tr key={symbol}>
            <td>{symbol}</td>
            <td>{current_price.toFixed(2)}</td>
            <td style={{ color: price_change_percent >= 0 ? 'green' : 'red' }}>
              {price_change_percent >= 0 ? '+' : ''}{price_change_percent.toFixed(2)}%
            </td>
            <td>{new Date(last_updated).toLocaleTimeString('en-NG')}</td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}

Tips

Choose the right polling interval. Data refreshes every 20 minutes during trading hours, so polling more frequently than every 5 minutes won’t give you fresher prices — it just uses quota. Outside trading hours you can stop polling entirely. Check last_updated before re-rendering. If the timestamp hasn’t changed since your last poll, the price hasn’t moved and you can skip the DOM/state update. Only poll during trading hours. NGX trades Monday–Friday, 09:00–16:00 WAT. You can detect this client-side and pause the interval outside those windows:
JavaScript
function isMarketOpen() {
  const now = new Date();
  const day = now.getUTCDay(); // 0 = Sun, 6 = Sat
  if (day === 0 || day === 6) return false;

  // WAT = UTC+1
  const watHour   = now.getUTCHours() + 1;
  const watMinute = now.getUTCMinutes();
  const watTime   = watHour * 100 + watMinute;

  return watTime >= 900 && watTime < 1600; // 09:00–16:00
}

// Only start polling if the market is open
if (isMarketOpen()) {
  fetchPrices().then(renderTicker);
  const timer = setInterval(() => {
    if (!isMarketOpen()) { clearInterval(timer); return; }
    fetchPrices().then(renderTicker);
  }, INTERVAL);
}

Companies list reference

All parameters for GET /companies

Company detail reference

Full quote fields from GET /companies/:symbol