How to Build a Nigerian Stock Market App with the NGN Market API

A complete guide to building a live NGX market data dashboard using the NGN Market API — covering equity prices, forex rates, company profiles, corporate disclosures, and more. Free plan included.

NGN Market

Written by NGN Market

·24 min read
How to Build a Nigerian Stock Market App with the NGN Market API

TL;DR: The NGN Market API gives you live NGX equity prices, the All Share Index, forex rates, company financials, corporate disclosures, dividends, and financial news from one REST API — all returning clean JSON. The free plan includes 3,000 calls per month with no credit card required. This guide walks through the core endpoints with working JavaScript code so you can ship a Nigerian stock market app from scratch.

If you have tried to build anything with Nigerian stock market data, you already know that clean, reliable, developer-friendly access to NGX prices has been hard to come by. Most developers end up scraping unreliable sources or stitching together stale data from multiple places that were never meant to be used programmatically.

The NGN Market API is built to fix that. It covers the full Nigerian Exchange stack — equities, indices, forex rates, ETFs, bonds, company financials, corporate disclosures, dividends, and financial news — from a single REST API that returns consistent JSON and prices in Naira. The free plan gives you 3,000 calls per month with no credit card.

This guide builds a working Nigerian stock market dashboard step by step. Every section is a self-contained fetch call you can drop directly into your project.

What you can build with this API

A quick picture of what the NGN Market API gives you:

  • Live equity prices for all 150+ NGX-listed companies, updated every 20 minutes during trading hours (Monday–Friday, 09:00–16:00 WAT)
  • The daily NGX All Share Index — change, YTD return, volume, value traded, market cap, breadth (advancers, decliners, unchanged), and session open/close times
  • Full company profiles: sector, sub-sector, 52-week range, trailing EPS, market cap, P/B ratio, dividend yield, business description
  • OHLCV price history back to each company's listing date — open, high, low, close, volume, VWAP, and trade count per day
  • NGN exchange rates against USD, EUR, GBP, and other major currencies — live and historical
  • Corporate disclosures: official filings including earnings releases, AGM notices, dividend declarations, and board resolutions — sourced from the NGX and updated twice daily
  • A dividend calendar: upcoming ex-dates and recent payouts across all NGX companies
  • Sector-level performance: average price change per sector over 1 day, 7 days, and 52 weeks
  • Financial statements: income statement, balance sheet, cash flow, and computed ratios for every reporting period available
  • AI-powered financial news search that matches company names to their ticker symbols — searching "Dangote" also returns articles referencing DANGCEM

The API covers every asset class listed on the NGX: equities, ETFs, bonds, and indices. One key, one base URL, one consistent response format across all of it.

Before you start: get your API key

Sign up at ngnmarket.com, open your developer dashboard, and click Generate API key. Your key starts with ngm_live_ and is shown only once — copy it before leaving the page.

The free plan gives you 3,000 calls per month and access to the market snapshot, company list, current forex rates, all indices, corporate disclosures, and blog endpoints. No credit card, no expiry.

Every request needs your key in the Authorization header:

Authorization: Bearer ngm_live_YOUR_KEY

The base URL for all endpoints is:

https://api.ngnmarket.com/v1

Every response wraps the payload in a consistent JSON envelope:

{
  "success": true,
  "data": { },
  "meta": {
    "plan": "free",
    "calls_used": 42,
    "calls_remaining": 2958,
    "reset_at": "2026-07-13T00:00:00.000Z"
  }
}

The meta object is on every single response. It tells you exactly how many calls you have used, how many remain, and when your quota resets. Read it in your app and surface a warning before you hit zero — that is much better than a broken dashboard at the end of the month.

Get the daily market snapshot

The market snapshot is the right place to start. One call returns everything you need for a market overview widget: the ASI value and daily change, YTD return, total deals, volume, value traded, market cap breakdown across equities and bonds, and market breadth.

This endpoint is on the free plan — you can start calling it before you have written any other code.

const fetchMarketSnapshot = async (apiKey) => {
  const res = await fetch('https://api.ngnmarket.com/v1/market/snapshot', {
    headers: { 'Authorization': `Bearer ${apiKey}` }
  });

  const body = await res.json();

  if (!body.success) {
    throw new Error(body.error.message);
  }

  return body.data;
};

const snapshot = await fetchMarketSnapshot('ngm_live_YOUR_KEY');

console.log(`ASI: ${snapshot.asi.toLocaleString()}`);
console.log(`Change: ${snapshot.asi_change_percent}%`);
console.log(`YTD: +${snapshot.ytd_asi_change_percent}%`);
console.log(`Value traded: ₦${(snapshot.value_traded / 1e9).toFixed(1)}B`);
console.log(`Breadth: ${snapshot.breadth.advancers}A / ${snapshot.breadth.decliners}D`);

A real response looks like this:

{
  "date": "2026-06-13",
  "asi": 244739.18,
  "asi_change": -122.41,
  "asi_change_percent": -0.05,
  "ytd_asi_change_percent": 112.02,
  "deals": 9821,
  "volume": 512847291,
  "value_traded": 8213400000,
  "turnover_rate": 0.0052,
  "market_cap": {
    "equity": 131000000000000,
    "bonds": 22000000000000,
    "etfs": 2100000000,
    "total": 153102100000000
  },
  "breadth": {
    "advancers": 33,
    "decliners": 28,
    "unchanged": 18,
    "total": 79,
    "adv_dec_ratio": 1.18
  },
  "session": {
    "open_time": "09:00",
    "close_time": "16:00",
    "timezone": "Africa/Lagos"
  },
  "updated_at": "2026-06-13T16:00:00.000Z"
}

The breadth object saves you a separate request if you are building a market summary widget — advancers, decliners, unchanged, and the advance/decline ratio are all here. The ytd_asi_change_percent field is useful for context: the NGX is up over 112% year-on-year as of June 2026, which is worth surfacing to your users.

You can also pass a ?date=YYYY-MM-DD parameter to get the snapshot for any historical trading day.

Fetch the full list of NGX companies

The /companies endpoint returns a paginated list of all NGX-listed equities with live price data. You can filter by sector, search by name or ticker, sort by market cap, price, volume, or percentage change, and filter by market cap range. Like the snapshot, this endpoint is on the free plan.

const fetchCompanies = async (apiKey, options = {}) => {
  const params = new URLSearchParams({
    limit: options.limit || 50,
    page:  options.page  || 1,
    sort:  options.sort  || 'market_cap',
    order: options.order || 'desc',
    ...(options.sector && { sector: options.sector }),
    ...(options.search && { search: options.search }),
  });

  const res = await fetch(
    `https://api.ngnmarket.com/v1/companies?${params}`,
    { headers: { 'Authorization': `Bearer ${apiKey}` } }
  );

  const body = await res.json();
  if (!body.success) throw new Error(body.error.message);
  return body.data;
};

// Top 10 companies by market cap
const top10 = await fetchCompanies(apiKey, { limit: 10 });
top10.data.forEach(c => console.log(`${c.symbol}: ₦${c.price}`));

// All Financial Services stocks, sorted by today's volume
const banks = await fetchCompanies(apiKey, {
  sector: 'Financial Services',
  sort:   'volume',
  order:  'desc',
  limit:  20,
});

// Search for a company by name or partial ticker
const results = await fetchCompanies(apiKey, { search: 'Dangote' });

Each company object in the response includes current price, previous close, day high, day low, volume, market cap, 7-day and 52-week change percentages, and a last_updated timestamp.

If you only need ticker symbols, company names, and ISINs for a dropdown or autocomplete — without price data — use /companies/identifiers instead. It returns the full list in one call, no pagination, and costs a single API call regardless of how many companies are listed.

Get a single company's full profile

The /companies/:symbol endpoint returns everything needed for a company detail page: current OHLC price, value traded, market cap, 52-week range, trailing EPS, shareholders equity, P/B ratio, D/E ratio, dividend yield, sector classification, business description, website, and contact details.

This endpoint requires the Hobby plan.

const fetchCompanyProfile = async (apiKey, symbol) => {
  const res = await fetch(
    `https://api.ngnmarket.com/v1/companies/${symbol}`,
    { headers: { 'Authorization': `Bearer ${apiKey}` } }
  );

  const body = await res.json();

  if (!body.success) {
    if (body.error.code === 'PLAN_REQUIRED') {
      console.error(`Upgrade to ${body.error.required_plan} to use this endpoint`);
    }
    throw new Error(body.error.message);
  }

  return body.data;
};

const dangcem = await fetchCompanyProfile(apiKey, 'DANGCEM');

console.log(dangcem.about);
console.log(`TTM EPS: ₦${dangcem.ttm_eps}`);
console.log(`52w high: ₦${dangcem.high52wk} on ${dangcem.high_52wk_date}`);
console.log(`52w low: ₦${dangcem.low52wk} on ${dangcem.low_52wk_date}`);

The symbol lookup is case-insensitive. DANGCEM, dangcem, and Dangcem all return the same result.

Historical price data (OHLCV)

The chart endpoint returns the full OHLCV history for any NGX-listed company — open, high, low, close, volume, VWAP, and trade count per day. It supports preset windows (7d, 30d, 90d, 1y, 5y, all) or a custom range with ?from= and ?to=. This endpoint is also on the Hobby plan.

Advertisement

const fetchPriceHistory = async (apiKey, symbol, period = '90d', format = 'chart') => {
  const res = await fetch(
    `https://api.ngnmarket.com/v1/companies/${symbol}/chart?period=${period}&format=${format}`,
    { headers: { 'Authorization': `Bearer ${apiKey}` } }
  );

  const body = await res.json();
  if (!body.success) throw new Error(body.error.message);
  return body.data;
};

// Compact [timestamp, price] pairs — ready for Chart.js or Recharts
const lineData = await fetchPriceHistory(apiKey, 'ZENITHBANK', '90d', 'chart');
console.log(`${lineData.count} data points`);
console.log(`Change over period: ${lineData.statistics.price_change_percent}%`);
// lineData.data = [[1741449600000, 54.3], [1741536000000, 55.1], ...]

// Full OHLCV arrays — ready for candlestick charts
const candleData = await fetchPriceHistory(apiKey, 'GTCO', '1y', 'ohlcv');
// candleData.data = [[timestamp, open, high, low, close, volume], ...]

Three response formats are available:

  • format=detailed — full objects with timestamp, date, open, high, low, close, volume, vwap, trade_count, change, change_percent
  • format=chart — compact [timestamp, close] pairs, the lightest option for line charts
  • format=ohlcv[timestamp, open, high, low, close, volume] arrays for candlestick charts, compatible with ApexCharts, Highcharts, ECharts, and Plotly

The statistics block in every response computes first price, last price, min, max, absolute change, and percentage change for the requested period. You do not need to calculate these client-side.

Live NGN exchange rates

The forex endpoint returns the current NGN exchange rate against all supported currencies — USD, EUR, GBP, and others. This endpoint is on the free plan. Each rate entry includes the rate, the inverse rate, and the daily change.

const fetchForexRates = async (apiKey) => {
  const res = await fetch(
    'https://api.ngnmarket.com/v1/forex/current',
    { headers: { 'Authorization': `Bearer ${apiKey}` } }
  );

  const body = await res.json();
  if (!body.success) throw new Error(body.error.message);
  return body.data.rates;
};

const rates = await fetchForexRates(apiKey);
const usd = rates.find(r => r.currency === 'USD');

// rate = NGN per 1 USD (e.g. 1603.5 means $1 = ₦1,603.50)
console.log(`$1 = ₦${usd.rate}`);

// inverse_rate = USD per 1 NGN
console.log(`₦1 = $${usd.inverse_rate}`);
console.log(`Daily change: ${usd.daily_change_percent}%`);

The rate convention: rate is always how many Naira one unit of foreign currency costs. A USD rate of 1603.5 means one dollar is ₦1,603.50. The inverse_rate flips it — how much foreign currency one Naira buys. Get this the right way around in your UI before users notice.

For historical rates, use /forex/history with ?currency=USD&from=2026-01-01. That endpoint requires the Hobby plan — useful once you need to chart the Naira's exchange rate movement over time.

Corporate disclosures

One of the most underused data points in Nigerian investment apps. The disclosures endpoint returns a paginated feed of official corporate filings from NGX-listed companies — earnings releases, AGM notices, dividend declarations, board resolutions, director dealings. It is available on the free plan.

const fetchDisclosures = async (apiKey, options = {}) => {
  const params = new URLSearchParams({
    limit: options.limit || 25,
    ...(options.symbol && { symbol: options.symbol }),
    ...(options.type   && { type:   options.type }),
    ...(options.from   && { from:   options.from }),
  });

  const res = await fetch(
    `https://api.ngnmarket.com/v1/disclosures?${params}`,
    { headers: { 'Authorization': `Bearer ${apiKey}` } }
  );

  const body = await res.json();
  if (!body.success) throw new Error(body.error.message);
  return body.data;
};

// All recent disclosures
const latest = await fetchDisclosures(apiKey);

// MTNN filings only
const mtnn = await fetchDisclosures(apiKey, { symbol: 'MTNN' });

// Financial statements filed in 2026
const statements = await fetchDisclosures(apiKey, {
  type: 'Financial Statements',
  from: '2026-01-01',
});

Each disclosure includes the document title, company name and symbol, ISIN, submission type, a direct link to the PDF on the NGX document library, and filing and modification timestamps.

Call /disclosures/types first if you want to see all valid type values with document counts — this is useful for building a filter UI.

Earnings releases and dividend declarations move NGX stock prices quickly. Surfacing this data in your app as a feed or notification is a feature most investment apps in Nigeria do not have.

Top gainers and losers

The market movers endpoint returns the biggest gaining and losing NGX stocks for any trading session — previous close, today's close, absolute and percentage change, volume, value traded, and trade count per entry. This endpoint requires the Starter plan. Omit date for the current or most recent session.

const fetchMarketMovers = async (apiKey, options = {}) => {
  const params = new URLSearchParams({
    limit: options.limit || 10,
    ...(options.date && { date: options.date }),
    ...(options.type && { type: options.type }),
  });

  const res = await fetch(
    `https://api.ngnmarket.com/v1/market/movers?${params}`,
    { headers: { 'Authorization': `Bearer ${apiKey}` } }
  );

  const body = await res.json();
  if (!body.success) throw new Error(body.error.message);
  return body.data;
};

const movers = await fetchMarketMovers(apiKey, { limit: 5 });

console.log('Top gainers:');
movers.top_gainers.forEach(s => {
  console.log(`  ${s.symbol}: +${s.change_percent}% (₦${s.todays_close})`);
});

console.log('Top losers:');
movers.top_losers.forEach(s => {
  console.log(`  ${s.symbol}: ${s.change_percent}% (₦${s.todays_close})`);
});

// Historical session
const friday = await fetchMarketMovers(apiKey, { date: '2026-06-10' });

Pass ?type=gainers or ?type=losers to get only one side. Each entry also includes logo_url and market_cap — useful for building a polished movers card.


Putting it together: a full React dashboard

Here is a complete React component that pulls the market snapshot, company list, and market status in parallel and renders a live NGX dashboard. It polls every 20 minutes, but only during NGX trading hours.

import { useState, useEffect, useCallback } from 'react';

const API_KEY  = process.env.NEXT_PUBLIC_NGN_MARKET_API_KEY;
const BASE_URL = 'https://api.ngnmarket.com/v1';

const get = (path) =>
  fetch(`${BASE_URL}${path}`, {
    headers: { 'Authorization': `Bearer ${API_KEY}` }
  }).then(r => r.json());

// NGX trades Monday–Friday, 09:00–16:00 WAT (UTC+1)
// So that is 08:00–15:00 UTC
const isMarketHours = () => {
  const now   = new Date();
  const day   = now.getUTCDay();     // 0 = Sun, 6 = Sat
  const hour  = now.getUTCHours();
  return day >= 1 && day <= 5 && hour >= 8 && hour < 15;
};

export default function NGXDashboard() {
  const [snapshot,  setSnapshot]  = useState(null);
  const [companies, setCompanies] = useState([]);
  const [isOpen,    setIsOpen]    = useState(false);
  const [loading,   setLoading]   = useState(true);
  const [error,     setError]     = useState(null);
  const [callsLeft, setCallsLeft] = useState(null);

  const load = useCallback(async () => {
    try {
      const [snapRes, compRes, statusRes] = await Promise.all([
        get('/market/snapshot'),
        get('/companies?limit=50&sort=market_cap&order=desc'),
        get('/market/status'),
      ]);

      if (!snapRes.success)   throw new Error(snapRes.error.message);
      if (!compRes.success)   throw new Error(compRes.error.message);
      if (!statusRes.success) throw new Error(statusRes.error.message);

      setSnapshot(snapRes.data);
      setCompanies(compRes.data.data);
      setIsOpen(statusRes.data.is_open);

      // Track quota from meta — all three responses share the same pool
      setCallsLeft(snapRes.meta.calls_remaining);

    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    load();

    // Poll every 20 minutes, but only during market hours
    // Outside market hours the data does not change
    const TWENTY_MINUTES = 20 * 60 * 1000;

    const interval = setInterval(() => {
      if (isMarketHours()) load();
    }, TWENTY_MINUTES);

    return () => clearInterval(interval);
  }, [load]);

  if (loading) return <p>Loading NGX market data...</p>;
  if (error)   return <p>Error: {error}</p>;

  // Compute movers client-side from the company list
  // On Starter plan, replace this with a direct call to /market/movers
  const gainers = [...companies]
    .filter(c => c.price_change_percent > 0)
    .sort((a, b) => b.price_change_percent - a.price_change_percent)
    .slice(0, 5);

  const losers = [...companies]
    .filter(c => c.price_change_percent < 0)
    .sort((a, b) => a.price_change_percent - b.price_change_percent)
    .slice(0, 5);

  return (
    <div className="ngx-dashboard">

      {/* Low-quota warning — read from meta on every response */}
      {callsLeft !== null && callsLeft < 300 && (
        <div className="quota-warning">
          {callsLeft} API calls remaining this month.
        </div>
      )}

      {/* Market open/closed indicator */}
      <div className={`market-badge ${isOpen ? 'open' : 'closed'}`}>
        {isOpen ? '● Market open' : '○ Market closed'}
      </div>

      {/* ASI snapshot */}
      {snapshot && (
        <div className="snapshot-grid">
          <div className="metric">
            <span className="label">All Share Index</span>
            <span className="value">{snapshot.asi.toLocaleString()}</span>
            <span className={snapshot.asi_change_percent >= 0 ? 'up' : 'down'}>
              {snapshot.asi_change_percent >= 0 ? '▲' : '▼'}
              {Math.abs(snapshot.asi_change_percent).toFixed(2)}%
            </span>
          </div>
          <div className="metric">
            <span className="label">YTD return</span>
            <span className="value up">
              +{snapshot.ytd_asi_change_percent?.toFixed(1)}%
            </span>
          </div>
          <div className="metric">
            <span className="label">Market cap</span>
            <span className="value">
              ₦{(snapshot.market_cap.equity / 1e12).toFixed(1)}T
            </span>
          </div>
          <div className="metric">
            <span className="label">Value traded</span>
            <span className="value">
              ₦{(snapshot.value_traded / 1e9).toFixed(1)}B
            </span>
          </div>
          <div className="metric">
            <span className="label">Breadth</span>
            <span className="value">
              {snapshot.breadth.advancers}A &nbsp;/&nbsp; {snapshot.breadth.decliners}D
            </span>
          </div>
          <div className="metric">
            <span className="label">Deals</span>
            <span className="value">{snapshot.deals.toLocaleString()}</span>
          </div>
        </div>
      )}

      {/* Top movers */}
      <div className="movers-grid">
        <div className="movers-col">
          <h3>Top gainers</h3>
          {gainers.map(c => (
            <div key={c.symbol} className="mover-row">
              <span className="sym">{c.symbol}</span>
              <span className="price">₦{c.price.toLocaleString()}</span>
              <span className="chg up">+{c.price_change_percent.toFixed(2)}%</span>
            </div>
          ))}
        </div>
        <div className="movers-col">
          <h3>Top losers</h3>
          {losers.map(c => (
            <div key={c.symbol} className="mover-row">
              <span className="sym">{c.symbol}</span>
              <span className="price">₦{c.price.toLocaleString()}</span>
              <span className="chg down">{c.price_change_percent.toFixed(2)}%</span>
            </div>
          ))}
        </div>
      </div>

      {/* Full stock board */}
      <table className="stock-board">
        <thead>
          <tr>
            <th>Symbol</th>
            <th>Company</th>
            <th>Sector</th>
            <th>Price (₦)</th>
            <th>Change</th>
            <th>Volume</th>
            <th>Market cap</th>
          </tr>
        </thead>
        <tbody>
          {companies.map(c => (
            <tr key={c.symbol}>
              <td><strong>{c.symbol}</strong></td>
              <td>{c.name}</td>
              <td>{c.sector}</td>
              <td>{c.price?.toLocaleString()}</td>
              <td className={c.price_change_percent >= 0 ? 'up' : 'down'}>
                {c.price_change_percent >= 0 ? '+' : ''}
                {c.price_change_percent?.toFixed(2)}%
              </td>
              <td>{c.volume?.toLocaleString()}</td>
              <td>₦{(c.market_cap / 1e9).toFixed(0)}B</td>
            </tr>
          ))}
        </tbody>
      </table>

    </div>
  );
}

A few things worth explaining in that component:

  • The quota check. The meta.calls_remaining field comes back on every single response. Reading it costs nothing. Showing a warning when it drops below 300 gives users of your app time to react before things break.
  • The polling guard. NGX market data updates every 20 minutes during trading hours, then stays frozen until the next session. Polling at midnight on Sunday burns real monthly quota for zero new data. The isMarketHours() function checks the UTC hour and day before each poll.
  • Top movers from the company list. On the free and Hobby plan, the dedicated /market/movers endpoint is not available. Computing gainers and losers client-side from the company list is a reasonable substitute. Once you are on the Starter plan, swap this for a direct call to /market/movers — you will get official NGX-ranked movers with full per-trade detail.

Quota management

The NGN Market API uses a monthly call quota rather than a per-second rate limit. That means you can make short bursts of requests without hitting a wall, as long as your monthly total stays within your plan.

Plan Monthly calls Per-minute burst Price
Free 3,000 30/min Free
Hobby 10,000 60/min ₦15,000/month
Starter 100,000 120/min ₦50,000/month
Growth 500,000 200/min ₦200,000/month
Business 2,000,000 300/min ₦700,000/month

The quota resets on your billing renewal date — the same day of the month you first subscribed — not necessarily the 1st. Check meta.reset_at in any response to see your exact reset timestamp.

All keys on your account share one quota pool. Having multiple API keys does not increase your available calls.

Three habits that keep you well within quota on any plan:

  • Cache on your server. If 100 users load your dashboard simultaneously, fetch the data once on your backend, cache it for 20 minutes, and serve all 100 users from that one response. Your users get the same fresh data and you use one API call instead of 100.
  • Stop polling after close. The NGX closes at 16:00 WAT every weekday. After close, the snapshot and company prices do not change until the next session opens at 09:00 WAT. Poll during market hours; skip outside them.
  • Use /companies/identifiers for lookups. If you need ticker symbols and company names for an autocomplete or dropdown, this endpoint returns the complete list in one lightweight call — no pagination, no price data, no unnecessary overhead.

What to build next

Once the core dashboard is running, these are the features that add the most value for Nigerian investors:

Price history charts. Call /companies/:symbol/chart?format=ohlcv to get full OHLCV data per day, then render it with ApexCharts or Highcharts as a candlestick chart. The NGN Market API returns VWAP and trade count alongside OHLCV — data most charting libraries will happily plot. This endpoint is on the Hobby plan, the same tier as the company profile, so both unlock together.

Company detail pages. Pair the full profile from /companies/:symbol with a 90-day price chart and recent disclosures from /companies/:symbol/disclosures. This is the standard investment research page format and everything you need is in three calls — company profile and chart on the Hobby plan, disclosures on the free plan.

Dividend calendar. The /dividends/upcoming endpoint returns all NGX companies with an upcoming ex-dividend date, sorted by how soon the date is. Nigerian investors are dividend-focused — a "stocks paying dividends soon" view drives real engagement. This endpoint is on the Starter plan.

Corporate disclosure feed. Push notifications when a company a user follows files a new earnings release or dividend declaration. The /disclosures endpoint is on the free plan and updated twice daily — it is one of the few high-value features you can ship before upgrading. This turns your app from a price board into something that actually helps investors act.

Sector performance. The /market/sectors endpoint returns average 1-day, 7-day, and 52-week price change per sector alongside aggregate market cap, value traded, volume, and breadth per sector. Good for heatmaps and rotation dashboards. This endpoint is on the Growth plan.

Financial statements. The /companies/:symbol/financials endpoint returns income statement, balance sheet, cash flow, and computed ratios — ROE, ROA, D/E ratio, current ratio, free cash flow margin, BVPS — for every reporting period available. For any app that goes beyond price data into fundamental analysis, this is the endpoint that makes NGN Market stand out. It requires the Business plan, which is aimed at apps building serious research and screening tools.

Frequently asked questions

Does the free plan really require no credit card?

Correct. Sign up, generate your key, and start making requests. 3,000 calls per month, no expiry, no card until you choose to upgrade.

What plan should I start with to build a real app?

The free plan is enough to build and test a full dashboard. The Hobby plan at ₦15,000/month unlocks company profiles and price charts — the two endpoints most investment apps need in production. Most apps stay on Hobby until their user base grows or they need the movers and dividends endpoints, at which point Starter makes sense.

How do I avoid running out of calls on the free plan?

Cache API responses on your server and serve multiple users from one request. Stop polling after 16:00 WAT. Use /companies/identifiers for search autocomplete instead of the paginated /companies endpoint. The meta.calls_remaining field in every response tells you exactly where you stand at all times.

What happens when I exceed my monthly quota?

Every request returns a 429 QUOTA_EXCEEDED error until your quota resets on your billing date. The error response still includes the meta object so you can read meta.reset_at and surface a meaningful message to your users.

Can I query historical trading sessions?

Yes. Most endpoints accept a ?date=YYYY-MM-DD parameter. The /market/snapshot endpoint returns the snapshot for any historical trading day. The /companies/:symbol/chart endpoint supports custom date ranges with ?from= and ?to=. The /market/movers and /market/top-trades endpoints also accept a date parameter.

Is there a way to search financial news about a specific company?

Yes. The /blog/search?q=Dangote endpoint does AI-powered full-text search across published financial news. It uses query expansion, so searching "Dangote" also matches articles that reference DANGCEM.

Get started

Sign up at ngnmarket.com and generate your free API key in the developer dashboard. Full documentation with response schemas, code examples in JavaScript, Python, and cURL, and an OpenAPI spec are at docs.ngnmarket.com.

The free plan is enough to build, test, and show something real. Upgrade when you need more calls or need to unlock deeper data.

Advertisement

Advertisement