# PakDataHub - full documentation > Every PakDataHub docs page as raw Markdown, in reading order. Index: https://pakdatahub.com/docs/llms.txt - Site overview: https://pakdatahub.com/llms.txt # Getting started PakDataHub is one REST API for Pakistan's official economic and financial data: exchange rates, inflation, interest rates, the balance of payments, money and banking, GDP, trade, commodity prices, digital payments, mutual funds, debt securities and more. It holds 16,964 series from 1947 to today, sourced from the State Bank of Pakistan (SBP), the Pakistan Bureau of Statistics (PBS), the PTA and MUFAP. Every series is a clean time series. You can pull it as JSON or CSV from `https://api.pakdatahub.com`. ## 1. Get a key Create an account at [pakdatahub.com/signup](https://pakdatahub.com/signup), using email and password or Google. Your first API key appears straight away, and it is also emailed to you. Every account gets **500 free API calls a month** (resetting on the 1st), no card. See [Plans & credits](https://pakdatahub.com/docs/plans-credits.md). ## 2. Find a series The catalog is public, so you can search it without a key: ```bash curl "https://api.pakdatahub.com/v1/search?q=kibor" ``` ```json { "success": true, "count": 3, "data": [ { "id": "rates.kibor.1y", "module": "fixed-income", "name": "KIBOR 1-Year", "unit": "percent", "frequency": "daily", "source": "SBP", "tier": "basic" }, { "id": "rates.kibor.3m", "module": "fixed-income", "name": "KIBOR 3-Month", "unit": "percent", "frequency": "daily", "source": "SBP", "tier": "basic" }, { "id": "rates.kibor.6m", "module": "fixed-income", "name": "KIBOR 6-Month", "unit": "percent", "frequency": "daily", "source": "SBP", "tier": "basic" } ] } ``` Every result has an `id`. That's the stable, lowercase identifier you use everywhere else, such as `fx.rate.avg.usd`, `rates.kibor.3m` or `inflation.cpi.national.yoy`. ## 3. Make your first call Send your key in the `X-API-Key` header: ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/fx.rate.avg.usd/latest" ``` ```json { "success": true, "series": "fx.rate.avg.usd", "meta": { "name": "Average Exchange rate of Pak Rupees per U.S. Dollar", "unit": "pkr", "frequency": "monthly", "source": "SBP", "last_updated": "2026-08-31", "transform": null }, "data": [ { "date": "2026-08-31", "value": 277.9187406, "dims": {} } ], "pagination": { "next_cursor": null, "count": 1 } } ``` That's it. Every one of the 16,964 series comes back in this same shape, whether you ask for the 1953 exchange rate or last week's flour price. ## 4. In Python ```python import httpx r = httpx.get( "https://api.pakdatahub.com/v1/series/inflation.cpi.national.yoy", params={"from": "2020-01-01", "sort": "asc"}, headers={"X-API-Key": "pk_live_xxx"}, timeout=30, ) for point in r.json()["data"]: print(point["date"], point["value"]) ``` Or load straight into pandas with CSV: ```python import pandas as pd url = ("https://api.pakdatahub.com/v1/series/fx.rate.avg.usd" "?from=1947-01-01&sort=asc&format=csv&api_key=pk_live_xxx") df = pd.read_csv(url, parse_dates=["date"]) ``` ## Next - [Authentication](https://pakdatahub.com/docs/authentication.md): keys, headers and sessions. - [Series & the catalog](https://pakdatahub.com/docs/series-and-catalog.md): how ids, modules and dimensions work. - [API reference](https://pakdatahub.com/docs/api-reference.md): every endpoint, with parameters and response schemas. - [Data dictionary](https://pakdatahub.com/docs/data-dictionary.md): what data exists, with real, callable ids. # Authentication Every data endpoint needs an API key. Discovery endpoints are public and need none: `/v1/catalog`, `/v1/search`, `/v1/status`, `/v1/calendar`, `/v1/plans`, `/v1/commodities/items` and `/v1/commodities/cities`. ## Sending your key The preferred way is the `X-API-Key` header: ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/rates.kibor.3m" ``` For quick tests, pandas `read_csv` or a spreadsheet import, you can pass it as a query parameter instead: ``` https://api.pakdatahub.com/v1/series/rates.kibor.3m?api_key=pk_live_xxx ``` Avoid the query-parameter form in production, because URLs end up in logs and browser history. ## Key format and storage - Keys start with `pk_live_`. - A key is shown **once**, when it is created. We store only a hash, so a lost key can't be recovered; revoke it and create a new one. - Each account can hold up to **3 active keys**, for example one per environment. See [`/v1/keys`](https://pakdatahub.com/docs/api-account-keys.md). - Each key's `last_used_at` is recorded, updated at most once a minute, so you can spot unused keys. ## Session tokens (dashboard) The web dashboard signs you in with email and password or Google, and holds a **session token**. The account-management endpoints accept either credential: | Endpoint | API key | Session token (`X-Session-Token`) | |---|---|---| | `/v1/series`, `/v1/funds`, all data endpoints | yes | no | | `/v1/account`, `/v1/keys`, `/v1/usage`, `/v1/webhooks`, `/v1/billing/portal` | yes | yes | See [Auth endpoints](https://pakdatahub.com/docs/api-auth.md) for signup, login and logout. ## What happens when a key is wrong ```json { "success": false, "error": { "code": "unauthorized", "message": "missing API key" } } ``` A missing or invalid key returns `401 unauthorized`. The other auth-related errors are: - `402`: this month's free calls are used up, or the subscription is inactive. - `403`: the feature needs a higher plan (e.g. revision vintages need Pro). See [Errors & rate limits](https://pakdatahub.com/docs/errors-rate-limits.md). ## Rotating a key 1. Create a new key (`POST /v1/keys` or the dashboard). 2. Deploy it. 3. Revoke the old one (`DELETE /v1/keys/{id}`). Revocation takes effect immediately. # Series & the catalog Almost everything in PakDataHub is a **time series**: rows of `(date, value, dims)` under one stable id. The **catalog** describes every series, and **`GET /v1/series/{id}`** returns its data. The exceptions are the richer, entity-shaped datasets, which have their own endpoints: - mutual funds - debt securities - auctions - external trade by commodity ## Series ids Ids are lowercase, dot-separated and human-readable, in the form `topic.group.item`: | Id | What it is | |---|---| | `fx.rate.avg.usd` | PKR per US dollar, monthly average, from 1947 | | `rates.kibor.3m` | KIBOR 3-month, daily, with `side` = bid/offer | | `inflation.cpi.national.yoy` | Headline CPI inflation, year-on-year % | | `payments.raast.p2p.value` | Raast person-to-person transfer value, quarterly | | `commodities.wheat_flour` | Wheat flour (20 kg bag), weekly, with `city` | Ids are **case-sensitive and stable**. Use them verbatim; don't re-slug them or swap the dots for hyphens. Series auto-discovered from the SBP open-data portal sometimes carry a numeric suffix (`_2`, `_3`) that tells apart series whose names collide. ## Modules Every series belongs to one module. You can filter the catalog and search by module: | Module | Covers | |---|---| | `forex` | PKR exchange rates, REER/NEER | | `fixed-income` | KIBOR, policy rate, PKRV/PKISRV curves, auction cut-offs | | `economic` | Curated flagships: CPI and groups, WPI, LSM, remittances, telecom | | `prices` | Inflation measures, cost-of-living index by city | | `commodities` | Weekly SPI retail prices | | `external` | Balance of payments, trade by country, FDI, reserves, remittances by country | | `monetary` | Money supply, banking aggregates, deep KIBOR/KIBID history, NPLs, branchless banking | | `real` | GDP, auto, power, fuel, fertilizer, cement, corporate sector | | `public-finance` | Federal and provincial revenue and expenditure, FBR taxes | | `debt` | External debt, government securities holdings, national savings | | `social` | Population, labour, literacy, education, health, confidence surveys | | `alternate` | Digital payments (Raast, cards, POS, PRISM), SME finance | See the [data dictionary](https://pakdatahub.com/docs/data-dictionary.md) for every module, with real ids. ## The catalog record `GET /v1/catalog/{id}` (public) describes one series: ```json { "id": "rates.kibor.3m", "module": "fixed-income", "name": "KIBOR 3-Month", "description": "Karachi Interbank Offered Rate, 3-month tenor (bid/offer)", "unit": "percent", "frequency": "daily", "source": "SBP", "source_url": "https://www.sbp.org.pk/ecodata/kibor/kibor.asp", "dimensions": { "side": ["bid", "offer"] }, "first_date": "2005-06-09", "last_date": "2026-10-02", "tier": "basic", "canonical_id": null } ``` | Field | Meaning | |---|---| | `unit` | e.g. `percent`, `pkr`, `index`, `count`, `usd_mn` (US$ millions), `usd_th` (thousands), `pkr_mn`, `pkr_bn`, `pkr_per_kg` | | `frequency` | `daily`, `weekly`, `monthly`, `quarterly`, `half_yearly`, `annual` or `irregular` (e.g. auctions) | | `dimensions` | the dimension keys and values the series carries (see below) | | `tier` | Informational: every plan reaches every series. Plans differ by history depth, revision vintages and webhooks (see [plans](https://pakdatahub.com/docs/plans-credits.md)). | | `canonical_id` | set when this series is a near-duplicate of another; prefer the canonical one | ## Dimensions Some series carry more than one value per date, labelled by **dimensions**: - **KIBOR**: `side` = `bid` or `offer`. - **SPI commodity prices**: `city` = `karachi`, `lahore`, ... or `national`. Filter with `dims=key:value`, and comma-separate several filters: ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/rates.kibor.3m?dims=side:offer&from=2026-01-01" ``` Without `dims` you get every dimension's rows, each tagged in `data[].dims`. ## Discovering series - **Search:** `GET /v1/search?q=remittances` gives ranked matches ([Search](https://pakdatahub.com/docs/api-search.md)). - **Browse a module:** `GET /v1/catalog?module=forex` ([Catalog](https://pakdatahub.com/docs/api-catalog.md)). - **Web:** the [coverage page](https://pakdatahub.com/coverage) and a page per series at `https://pakdatahub.com/series/{id}`. ## Getting data Once you have an id: ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/inflation.cpi.national.yoy?from=2020-01-01&sort=asc&format=csv" ``` See [Series endpoint](https://pakdatahub.com/docs/api-series.md) for every parameter, and [Transforms](https://pakdatahub.com/docs/api-transforms.md) for server-side YoY, MoM, % change, moving average and rebasing. # Errors & rate limits ## The error envelope Every error uses the same shape and a correct HTTP status: ```json { "success": false, "error": { "code": "not_found", "message": "unknown series" } } ``` `message` is written to be shown to a person. `code` is stable and meant for your code to branch on. ## Status codes | HTTP | `code` | When | What to do | |---|---|---|---| | 401 | `unauthorized` | Missing or invalid API key or session | Check the `X-API-Key` header; create a new key if it was revoked | | 402 | `credits_exhausted` | The free plan has used this month's 500 calls | Wait for the reset on the 1st, or upgrade | | 402 | `subscription_inactive` | Subscription cancelled, expired or `past_due` beyond the 3-day grace | Update billing in the dashboard | | 403 | `tier_forbidden` | The feature needs a higher plan: `vintage=` needs Pro or Business, webhooks need a paid plan, or you're at the 3-active-key or per-plan webhook cap | Upgrade, or free up a slot | | 404 | `not_found` | Unknown series id, fund, security, AMC or commodity | Check the id with `/v1/search` | | 409 | - | Signup with an email that already has an account | Sign in instead | | 422 | `invalid_params` | Bad parameter: malformed date, bad `dims` token, unknown `transform`, or a transform that doesn't fit the frequency | Fix the request; `message` says what's wrong | | 429 | `rate_limited` | Per-minute or per-day limit hit | Wait the `Retry-After` seconds | Examples: ```json { "success": false, "error": { "code": "invalid_params", "message": "unknown transform 'bogus'; choose one of 3ma, index, mom, pct_change, yoy" } } ``` ```json { "success": false, "error": { "code": "unauthorized", "message": "missing API key" } } ``` ## Rate limits Limits apply **per account**, across all its keys. Every keyed response carries: - `X-RateLimit-Limit`: your per-minute ceiling. - `X-RateLimit-Remaining`: requests left right now (the lower of your minute and day budgets). The per-minute limit is a true sliding 60-second window. The daily limit resets at midnight. | Plan | Per minute | Per day | |---|---|---| | Free | 10 | 500 calls a month (resets on the 1st) | | Developer | 60 | 10,000 | | Pro | 300 | 100,000 | | Business | 600 | 500,000 | Check your live usage with [`GET /v1/usage`](https://pakdatahub.com/docs/api-usage.md). ## Handling 429 ```python import time, httpx def get(url, key): while True: r = httpx.get(url, headers={"X-API-Key": key}, timeout=30) if r.status_code != 429: return r time.sleep(int(r.headers.get("Retry-After", "5"))) ``` ## Tips to use fewer requests - Use `/v1/series/{id}/latest` for tickers instead of pulling full history. - Pull a long history in one call (`limit` up to 10,000) rather than many small windows. - Use [`/v1/funds/screener`](https://pakdatahub.com/docs/api-funds.md) for every fund in **one** request instead of one call per fund. - Subscribe to [webhooks](https://pakdatahub.com/docs/api-webhooks.md) instead of polling for updates (paid plans). - Cache responses: most series update daily, weekly or monthly, never intraday. # Plans & credits Pricing is public and self-serve. The live numbers come from [`GET /v1/plans`](https://pakdatahub.com/docs/api-billing.md) and appear on the [pricing page](https://pakdatahub.com/pricing). Plans are priced on what the data is worth to you, not on request volume. They differ by how far back history goes, whether you get revision vintages and webhooks, and whether you may show the data to your own users. Request limits on paid plans are generous fair-use ceilings. | | Free | Developer | Pro | Business | |---|---|---|---|---| | Price | $0 | $19/mo | $49/mo | $199/mo | | Best for | evaluating, students, journalists | one analyst or developer | risk, treasury and research teams | apps that show the data to their users | | History depth | last 1 year | last 10 years | full (to 1947) | full | | Revision vintages (`?vintage=`) | - | - | yes | yes | | Webhooks | - | 3 | 50 | unlimited | | Show the data in your product | internal use | internal use | internal use | yes | | Uptime SLA | - | - | - | yes | | Requests | 500 a month | 10,000/day (fair use) | 100,000/day (fair use) | 500,000/day (fair use) | | Per minute | 10 | 60 | 300 | 600 | | Every dataset: all 12 modules, mutual funds, AMCs, debt securities, auctions, trade | yes | yes | yes | yes | | Server-side transforms, CSV | yes | yes | yes | yes | Teams that need annual billing in PKR against a purchase order, a display or redistribution licence, or custom series can email [hello@pakdatahub.com](mailto:hello@pakdatahub.com). ## How the free plan works - Every account gets **500 API calls a month**. The allowance resets on the 1st of each month; unused calls don't carry over. - **One call per request**, whatever the endpoint or response size. - When this month's calls are used up, requests return `402 credits_exhausted` until the 1st, or until you upgrade. - Check your balance with `GET /v1/usage`: `usage.credits_remaining`, and `usage.credits_reset` for the date it refills. - Paid plans aren't metered this way. They use the fair-use limits above. ## Using the data On every plan you may use the data internally - in your own analysis, models, dashboards and research, including commercial work - and quote individual figures in reports and articles. Showing the data to your own users or customers inside a product (fund NAVs in an app, KIBOR on a website) needs the Business plan or a written licence. See the [terms](https://pakdatahub.com/terms). ## History depth On Free and Developer, the `from` date is **clamped** to your window: the last 1 or 10 years. The request still succeeds; older points are simply left out. Pro and Business get every observation back to the start of each series (USD/PKR from 1947, fund NAVs from 1996). ## Billing - **Payments:** paid plans are billed monthly through LemonSqueezy, our merchant of record. Upgrade from the dashboard, or with [`POST /v1/checkout`](https://pakdatahub.com/docs/api-billing.md). - **Managing your subscription:** update your card, see invoices or cancel from the customer portal (`GET /v1/billing/portal`). - **Failed payments:** a `past_due` subscription keeps working for a 3-day grace period. # Google Sheets & Excel functions Put any of PakDataHub's 16,964 series into a spreadsheet with one formula. No code to maintain: the numbers update when you recalculate. ``` =PAKDATA("fx.rate.avg.usd", "2020-01-01") a Date | Value table, oldest first =PAKDATA_LATEST("rates.kibor.3m", "side:offer") the latest value, as a number ``` You need an API key; the free plan's 500 calls a month is plenty for a workbook ([get one](https://pakdatahub.com/signup)). Each `PAKDATA` or `PAKDATA_LATEST` formula is one API call when it recalculates. Find series ids in the [catalog](https://pakdatahub.com/coverage) or with `=PAKDATA_SEARCH("...")` in Google Sheets. ## Google Sheets **Install** (once per spreadsheet, about a minute): 1. In the spreadsheet: **Extensions -> Apps Script**. 2. Delete the sample code, paste the script below (or [download it](https://pakdatahub.com/integrations/PakDataHub.gs)), and click **Save**. 3. Reload the spreadsheet. A **PakDataHub** menu appears. Choose **Set API key** and paste your key. It's stored in your Google account, not in a cell. **Functions** | Formula | Returns | |---|---| | `=PAKDATA(series_id, [from], [to], [dims], [transform])` | A table: Date, any dimension columns (e.g. `side`, `city`), Value. Oldest first. | | `=PAKDATA_LATEST(series_id, [dims])` | The most recent value as a number | | `=PAKDATA_SEARCH(query, [limit])` | Matching series ids, names, units and frequencies (free) | | `=PAKDATA_INFO(series_id)` | Name, unit, frequency, source and date range (free) | Examples: ``` =PAKDATA("inflation.cpi.national.yoy", "2018-01-01") =PAKDATA("rates.kibor.3m", "2025-01-01", , "side:offer") =PAKDATA("commodities.wheat_flour", "2025-06-01", , "city:karachi") =PAKDATA("inflation.cpi.national", "2015-01-01", , , "yoy") =PAKDATA_LATEST("fx.rate.interbank.usd", "side:bid") =PAKDATA_SEARCH("kibor") ``` Dates can be typed as `"2024-01-31"` or point at a date cell. Results are cached (6 hours for tables, 1 hour for latest values), so recalculating doesn't spend calls; use **PakDataHub -> Refresh data** to force a refetch. Errors explain themselves in the cell, e.g. an unknown id or a used-up monthly allowance. The script: ```javascript /** * PakDataHub for Google Sheets - Pakistan's official economic and financial data in a cell. * https://pakdatahub.com/docs/spreadsheets * * Install (once per spreadsheet, about a minute): * 1. Extensions -> Apps Script. Delete what's there, paste this whole file, click Save. * 2. Reload the spreadsheet. A "PakDataHub" menu appears -> "Set API key" -> paste your key * (free at https://pakdatahub.com/signup). It is stored in your own Google account * (UserProperties), never in a cell. * * Functions: * =PAKDATA("fx.rate.avg.usd") full table: Date | Value (oldest first) * =PAKDATA("inflation.cpi.national.yoy", "2020-01-01") from a date * =PAKDATA("rates.kibor.3m", "2025-01-01", , "side:offer") with a dimension filter * =PAKDATA("inflation.cpi.national", "2015-01-01", , , "yoy") server-side transform * =PAKDATA_LATEST("rates.policy") the latest value, as a number * =PAKDATA_LATEST("rates.kibor.3m", "side:offer") * =PAKDATA_SEARCH("remittances") find series ids * =PAKDATA_INFO("fx.rate.avg.usd") name, unit, frequency, source, dates * * Every PAKDATA / PAKDATA_LATEST call is one API request. Results are cached (6 hours for * tables, 1 hour for latest values) so recalculating a sheet doesn't spend your free * plan's 500 monthly calls. PAKDATA_SEARCH and PAKDATA_INFO use public endpoints and * cost nothing. */ var PAKDATA_BASE = "https://api.pakdatahub.com"; var PAKDATA_KEY_PROP = "PAKDATA_API_KEY"; var PAKDATA_VERSION = "1.0.0"; // ---- menu ------------------------------------------------------------------- function onOpen() { SpreadsheetApp.getUi() .createMenu("PakDataHub") .addItem("Set API key", "pakdataSetKey") .addItem("Refresh data (clear cache)", "pakdataClearCache") .addItem("Help", "pakdataHelp") .addToUi(); } function pakdataSetKey() { var ui = SpreadsheetApp.getUi(); var res = ui.prompt( "PakDataHub API key", "Paste your API key (starts with pk_live_). Get one free at pakdatahub.com/signup.", ui.ButtonSet.OK_CANCEL ); if (res.getSelectedButton() !== ui.Button.OK) return; var key = String(res.getResponseText() || "").trim(); if (!/^pk_(live|test)_/.test(key)) { ui.alert("That doesn't look like a PakDataHub key (it should start with pk_live_)."); return; } PropertiesService.getUserProperties().setProperty(PAKDATA_KEY_PROP, key); pakdataClearCache(); ui.alert("Saved. =PAKDATA(...) formulas will now use this key."); } function pakdataClearCache() { // Bump a generation counter: every cache key includes it, so old entries are ignored. var props = PropertiesService.getUserProperties(); props.setProperty("PAKDATA_CACHE_GEN", String(Date.now())); SpreadsheetApp.getActive().toast("PakDataHub: cache cleared. Edit or reload a formula to refetch."); } function pakdataHelp() { SpreadsheetApp.getUi().alert( "PakDataHub functions", '=PAKDATA("fx.rate.avg.usd", "2020-01-01")\n' + '=PAKDATA_LATEST("rates.kibor.3m", "side:offer")\n' + '=PAKDATA_SEARCH("remittances")\n' + '=PAKDATA_INFO("fx.rate.avg.usd")\n\nDocs: https://pakdatahub.com/docs/spreadsheets', SpreadsheetApp.getUi().ButtonSet.OK ); } // ---- custom functions ------------------------------------------------------------ /** * Observations for a PakDataHub series as a table (Date, [dimensions], Value), oldest first. * * @param {string} seriesId Series id, e.g. "fx.rate.avg.usd" (find ids with PAKDATA_SEARCH). * @param {string} from Optional start date, "YYYY-MM-DD" (or a date cell). * @param {string} to Optional end date, "YYYY-MM-DD" (or a date cell). * @param {string} dims Optional dimension filter, e.g. "side:offer" or "city:karachi". * @param {string} transform Optional: yoy, mom, pct_change, 3ma or index. * @return Table of observations. * @customfunction */ function PAKDATA(seriesId, from, to, dims, transform) { var id = pakdataId_(seriesId); var q = { sort: "asc", limit: "5000" }; if (from) q.from = pakdataDate_(from); if (to) q.to = pakdataDate_(to); if (dims) q.dims = String(dims).trim(); if (transform) q.transform = String(transform).trim().toLowerCase(); var body = pakdataGet_("/v1/series/" + encodeURIComponent(id), q, true, 21600); var rows = body.data || []; if (!rows.length) return [["No data for " + id + " in this range"]]; // Dimension columns (e.g. side, city) when the series carries more than one value per date. var dimKeys = []; rows.forEach(function (r) { Object.keys(r.dims || {}).forEach(function (k) { if (dimKeys.indexOf(k) < 0) dimKeys.push(k); }); }); var header = ["Date"].concat(dimKeys).concat([pakdataValueLabel_(body.meta)]); var out = [header]; rows.forEach(function (r) { var line = [pakdataToDate_(r.date)]; dimKeys.forEach(function (k) { line.push((r.dims || {})[k] == null ? "" : String(r.dims[k])); }); line.push(r.value == null ? "" : Number(r.value)); out.push(line); }); return out; } /** * The most recent value of a PakDataHub series, as a number. * * @param {string} seriesId Series id, e.g. "rates.policy". * @param {string} dims Optional dimension filter, e.g. "side:offer". * @return The latest value. * @customfunction */ function PAKDATA_LATEST(seriesId, dims) { var id = pakdataId_(seriesId); var q = {}; if (dims) q.dims = String(dims).trim(); var body = pakdataGet_("/v1/series/" + encodeURIComponent(id) + "/latest", q, true, 3600); var rows = (body.data || []).filter(function (r) { return r.value != null; }); if (!rows.length) throw new Error("No latest value for " + id); if (rows.length > 1 && !dims) { var keys = Object.keys(rows[0].dims || {}); if (keys.length) { throw new Error(id + " has several values per date - add a filter, e.g. \"" + keys[0] + ":" + rows[0].dims[keys[0]] + "\""); } } return Number(rows[0].value); } /** * Search the PakDataHub catalog. Free - uses the public search endpoint. * * @param {string} query Words to search for, e.g. "remittances saudi". * @param {number} limit Optional max results (default 20, max 50). * @return Table of id, name, unit, frequency, module. * @customfunction */ function PAKDATA_SEARCH(query, limit) { if (!query) throw new Error("Give a search term, e.g. =PAKDATA_SEARCH(\"kibor\")"); var n = Math.min(Math.max(Number(limit) || 20, 1), 50); var body = pakdataGet_("/v1/search", { q: String(query), limit: String(n) }, false, 21600); var rows = body.data || []; if (!rows.length) return [["No series match \"" + query + "\""]]; var out = [["Series id", "Name", "Unit", "Frequency", "Module"]]; rows.forEach(function (r) { out.push([r.id, r.name, r.unit || "", r.frequency || "", r.module || ""]); }); return out; } /** * Catalog metadata for a series: name, unit, frequency, source and date range. Free. * * @param {string} seriesId Series id, e.g. "fx.rate.avg.usd". * @return Two-column table of fields and values. * @customfunction */ function PAKDATA_INFO(seriesId) { var id = pakdataId_(seriesId); var r = pakdataGet_("/v1/catalog/" + encodeURIComponent(id), {}, false, 21600); return [ ["Series id", r.id], ["Name", r.name], ["Description", r.description || ""], ["Unit", r.unit || ""], ["Frequency", r.frequency || ""], ["Source", r.source || ""], ["First observation", r.first_date ? pakdataToDate_(r.first_date) : ""], ["Last observation", r.last_date ? pakdataToDate_(r.last_date) : ""], ["Page", "https://pakdatahub.com/series/" + r.id], ]; } // ---- internals ----------------------------------------------------------------- function pakdataId_(seriesId) { var id = String(seriesId == null ? "" : seriesId).trim(); if (!id) throw new Error("Give a series id, e.g. \"fx.rate.avg.usd\" (find ids with =PAKDATA_SEARCH(\"...\"))"); return id; } function pakdataKey_() { var key = PropertiesService.getUserProperties().getProperty(PAKDATA_KEY_PROP); if (!key) throw new Error("No API key yet: PakDataHub menu -> Set API key (free at pakdatahub.com/signup)"); return key; } function pakdataDate_(v) { if (Object.prototype.toString.call(v) === "[object Date]") { return Utilities.formatDate(v, "UTC", "yyyy-MM-dd"); } var s = String(v).trim(); if (!/^\d{4}-\d{2}-\d{2}$/.test(s)) throw new Error("Dates must look like 2024-01-31 (got " + s + ")"); return s; } function pakdataToDate_(iso) { var p = String(iso).slice(0, 10).split("-"); return new Date(Number(p[0]), Number(p[1]) - 1, Number(p[2])); } function pakdataValueLabel_(meta) { if (!meta) return "Value"; var unit = meta.unit ? " (" + meta.unit + ")" : ""; return (meta.transform ? meta.transform.toUpperCase() + " " : "") + "Value" + unit; } function pakdataQuery_(params) { var parts = []; Object.keys(params).forEach(function (k) { parts.push(encodeURIComponent(k) + "=" + encodeURIComponent(params[k])); }); return parts.length ? "?" + parts.join("&") : ""; } /** GET a PakDataHub endpoint (cached). keyed=true sends the user's API key. */ function pakdataGet_(path, params, keyed, ttlSeconds) { var url = PAKDATA_BASE + path + pakdataQuery_(params || {}); var gen = PropertiesService.getUserProperties().getProperty("PAKDATA_CACHE_GEN") || "0"; var cacheKey = "pd:" + gen + ":" + Utilities.base64EncodeWebSafe( Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, url + (keyed ? ":k" : ""))); var cache = CacheService.getScriptCache(); var hit = cache && cache.get(cacheKey); if (hit) return JSON.parse(hit); var headers = { "User-Agent": "PakDataHub-Sheets/" + PAKDATA_VERSION, Accept: "application/json" }; if (keyed) headers["X-API-Key"] = pakdataKey_(); var res = UrlFetchApp.fetch(url, { method: "get", headers: headers, muteHttpExceptions: true }); var code = res.getResponseCode(); var text = res.getContentText(); var body; try { body = JSON.parse(text); } catch (e) { throw new Error("PakDataHub returned HTTP " + code); } if (code >= 400 || body.success === false) { var msg = (body.error && body.error.message) || body.detail || ("HTTP " + code); var hint = { 401: " - check your key (PakDataHub menu -> Set API key)", 402: " - this month's free calls are used up; they reset on the 1st, or upgrade at pakdatahub.com/pricing", 403: " - this needs a higher plan (pakdatahub.com/pricing)", 404: " - unknown series id; try =PAKDATA_SEARCH(\"...\")", 429: " - rate limit; wait a minute and recalculate", }[code] || ""; throw new Error(msg + hint); } // CacheService values are capped at 100KB; skip caching very large tables. if (cache && text.length < 95000) cache.put(cacheKey, text, ttlSeconds); return body; } ``` ## Excel 365 (Windows) Excel 365 lets you define your own worksheet functions with `LAMBDA`, so `=PAKDATA(...)` works with nothing to install. Open **Formulas -> Name Manager -> New** and create three names: **1. `PAKDATA_KEY`**, which refers to your key: ``` ="pk_live_your_key" ``` **2. `PAKDATA`**: a Date | Value table, oldest first (the newest 800 points; use `from` to choose the window): ``` =LAMBDA(series_id,[from],[dims], LET( url, "https://api.pakdatahub.com/v1/series/" & series_id & "?format=csv&sort=desc&limit=800&api_key=" & PAKDATA_KEY & IF(ISOMITTED(from), "", "&from=" & TEXT(from, "yyyy-mm-dd")) & IF(ISOMITTED(dims), "", "&dims=" & ENCODEURL(dims)), grid, TEXTSPLIT(SUBSTITUTE(WEBSERVICE(url), CHAR(13), ""), ",", CHAR(10), TRUE), body, DROP(grid, 1), dates, DATEVALUE(CHOOSECOLS(body, 2)), vals, IFERROR(VALUE(CHOOSECOLS(body, 3)), ""), VSTACK({"Date", "Value"}, SORTBY(HSTACK(dates, vals), dates, 1)) )) ``` **3. `PAKDATA_LATEST`**: the latest value as a number: ``` =LAMBDA(series_id,[dims], LET( url, "https://api.pakdatahub.com/v1/series/" & series_id & "/latest?format=csv&api_key=" & PAKDATA_KEY & IF(ISOMITTED(dims), "", "&dims=" & ENCODEURL(dims)), grid, TEXTSPLIT(SUBSTITUTE(WEBSERVICE(url), CHAR(13), ""), ",", CHAR(10), TRUE), VALUE(INDEX(grid, 2, 3)) )) ``` Then, in any cell: ``` =PAKDATA("fx.rate.avg.usd", "2015-01-01") =PAKDATA_LATEST("rates.policy") =PAKDATA_LATEST("rates.kibor.3m", "side:offer") ``` Format the first column as a date. Notes: - `WEBSERVICE` and `ENCODEURL` exist in Excel for Windows only (not Mac or Excel on the web). Use Power Query below there. - `WEBSERVICE` returns at most 32,767 characters, about 800 data points, which is why `PAKDATA` asks for the newest 800. For longer histories use Power Query. - Excel recalculates these formulas when the workbook opens and on F9, and each recalculation is one API call. On the free plan, switch the workbook to manual calculation if you open it often. - The key sits in the workbook's names. Don't share a workbook that contains your key. ## Excel (any version), Power BI: Power Query For full history, or Excel for Mac and Power BI, add this as a Power Query function: **Data -> Get Data -> From Other Sources -> Blank Query -> Advanced Editor**, paste, and name the query `PakData`. ``` (series_id as text, optional from_date as text, optional dims as text) as table => let key = "pk_live_your_key", q0 = [sort = "asc", limit = "5000"], q1 = if from_date = null then q0 else Record.AddField(q0, "from", from_date), q = if dims = null then q1 else Record.AddField(q1, "dims", dims), body = Json.Document(Web.Contents("https://api.pakdatahub.com", [RelativePath = "v1/series/" & series_id, Query = q, Headers = [#"X-API-Key" = key]])), rows = Table.FromList(body[data], Splitter.SplitByNothing(), {"obs"}), cols = Table.ExpandRecordColumn(rows, "obs", {"date", "value", "dims"}), dimsText = Table.TransformColumns(cols, {{"dims", each Text.Combine( List.Transform(Record.FieldNames(_), (k) => k & "=" & Text.From(Record.Field(_, k))), ", "), type text}}), typed = Table.TransformColumnTypes(dimsText, {{"date", type date}, {"value", type number}}) in typed ``` Invoke it with a series id, for example `PakData("fx.rate.avg.usd", "1990-01-01")`, then **Close & Load**. **Data -> Refresh All** pulls the latest numbers. The first time, Excel asks how to connect to `api.pakdatahub.com`: choose **Anonymous**, because the key travels in the header. For one-off downloads without any setup, any series is also available as CSV: `GET /v1/series/{id}?format=csv` ([series endpoint](https://pakdatahub.com/docs/api-series.md)). See also [Excel, Sheets & Power BI use cases](https://pakdatahub.com/docs/use-case-excel-sheets-bi.md). # Sources & provenance **Every number in PakDataHub is an official figure published by a Pakistani public institution.** PakDataHub doesn't estimate, model or re-survey anything. It collects the official releases, normalizes them into one consistent format, validates them and serves them through one API. For research and financial applications, the source of truth is the publisher. PakDataHub gives you that publisher's number, labelled with where it came from. PakDataHub is an independent service and isn't affiliated with the institutions below. ## The publishers | Publisher | What PakDataHub takes from it | How | |---|---|---| | **State Bank of Pakistan (SBP)** | Exchange rates, KIBOR, policy rate, reserves, balance of payments, remittances, money and banking, external debt, public finance, GDP/real-sector compilations, social-sector data, payment systems, SME finance | SBP's open-data portal **EasyData** (every dataset, via its API), SBP's website (KIBOR, policy rate, auctions) and SBP publications (Payment Systems Review, SME Finance Review) | | **Pakistan Bureau of Statistics (PBS)** | CPI and CPI by group, WPI, weekly SPI prices in 17 cities, Large-Scale Manufacturing, external trade by commodity | Official PBS releases (PDF and Excel) | | **Pakistan Telecommunication Authority (PTA)** | Subscribers by operator, teledensity, cell sites, ARPU, broadband, sector revenue and investment | PTA telecom indicators | | **Mutual Funds Association of Pakistan (MUFAP)** | Fund NAVs, returns, payouts, expense ratios, allocations; PKRV/PKISRV yield curves; debt-security prices and trades | MUFAP industry statistics and valuation files | The SBP data compiles figures from other official bodies, including PAMA (autos), NEPRA (power), OCAC (petroleum), NFDC (fertilizer), APCMA (cement), the Ministry of Finance, FBR and NIPS. Each series names its publisher. ## Tracing any value Every catalog record has two provenance fields: - `source`: the publisher (`SBP`, `PBS`, `PTA` or `MUFAP`). - `source_url`: the exact official dataset or page the series is ingested from. ```bash curl "https://api.pakdatahub.com/v1/catalog/fx.rate.avg.usd" # ... "source": "SBP", # "source_url": "https://easydata.sbp.org.pk/api/v1/series/TS_GP_ER_FAERPKR_M.E00220/data" ``` For SBP EasyData series, the `source_url` contains SBP's own dataset and series code (here `TS_GP_ER_FAERPKR_M.E00220`), so any value can be checked against the SBP original. ## How data flows 1. **Fetch:** scheduled jobs download each official release as it's published: daily for KIBOR, curves and fund NAVs; weekly for SPI; monthly and quarterly for the rest. 2. **Archive:** the raw file is stored before parsing, so every value can be re-derived. 3. **Parse & normalize:** into `(series_id, date, value, dims)` with consistent ids, dates (month-end or quarter-end) and units. SBP publishes many values without stating the scale, so each dataset's scale (thousand, million, billion) was checked against known published totals and labelled in `unit`. 4. **Validate:** each value is checked against per-series bounds and step limits. Values that fail aren't stored and are raised for review, and a single bad file never aborts a run. For example, a misread cell in a PBS price PDF is dropped rather than published. 5. **Cross-validate:** derived figures are checked against the publisher's own derived figures. For example, CPI year-on-year computed from the index matches PBS's published YoY to within 0.05 percentage points. 6. **Version:** when a publisher revises a value, the previous value is kept. See [revision vintages](https://pakdatahub.com/docs/api-vintages.md). 7. **Data-quality sweep (twice a day):** some glitches only show once a point has neighbours. Nothing is silently discarded; every change is kept in an audit table and the revision history. - **Quarantined:** isolated fund-NAV spikes (e.g. a NAV of 1.00 between two days of ~1,180), non-positive NAVs, impossible debt-security prices (e.g. a spreadsheet date serial where a price should be), and impossible auction yields. - **Corrected:** unambiguous unit slips in SBP level series, where a single point is published at 1,000x or 1,000,000x its usual scale and rescaling it lands exactly between its neighbours. Percent and index series are never altered. 8. **Monitor:** a public [status page](https://pakdatahub.com/status) shows freshness per module against each source's real release calendar. ## PakDataHub vs going to each source directly The official portals are authoritative, and PakDataHub is built on them. What PakDataHub adds: | | Official portals (SBP EasyData, PBS, PTA, MUFAP) | PakDataHub | |---|---|---| | Coverage | One institution each | SBP + PBS + PTA + MUFAP in one catalog | | Access | Separate sites and formats: API (EasyData, sign-in required), PDFs, Excel, web tables | One REST API, one key, JSON or CSV | | Identifiers | Source codes (e.g. `TS_GP_ER_FAERPKR_M.E00220`) | Readable, stable ids (`fx.rate.avg.usd`), with the source code kept for traceability | | Units | Scale often unstated | Scale labelled (`usd_mn`, `pkr_bn`, ...) | | Price and fund data | PDFs (SPI) and web tables (MUFAP) | Clean series: 30 items x 17 cities, 567 funds with NAV history | | Extras | - | Server-side transforms, revision vintages, webhooks, fund analytics | If you need a single series once, the official portal is fine. If you're building a product, model or dashboard that spans institutions, PakDataHub saves you the scraping, cleaning and upkeep. The numbers are the same. ## What PakDataHub doesn't do - It doesn't produce its own estimates or forecasts. Every value is published. - The one exception is the clearly labelled [**derived layer**](https://pakdatahub.com/docs/data-derived.md) (`source: PakDataHub`, with a `derived` object giving the formula and inputs): real interest rates, spreads, import cover, essentials inflation by city, fund-category yields, the weekly cost-of-living index (`cost_of_living.*`) and SPI national averages. Fund analytics and server-side transforms are computed the same way, on request. - It doesn't cover PSX equities. For those, see [pypsx.com](https://pypsx.com). # API reference - **Base URL:** `https://api.pakdatahub.com`. Every data endpoint is under `/v1`. - **Format:** JSON (UTF-8) by default; CSV on `/v1/series/{id}` with `?format=csv`. - **Auth:** `X-API-Key: pk_live_xxx` header ([Authentication](https://pakdatahub.com/docs/authentication.md)). (key required) marks keyed endpoints; the rest are public. - **Dates:** ISO `YYYY-MM-DD`. Monthly data is dated to the **last day of the month**, and quarterly data to the quarter end. ## Response envelopes Series endpoints (`/v1/series`, `/v1/commodities`) return: ```json { "success": true, "series": "rates.kibor.3m", "meta": { "name": "KIBOR 3-Month", "unit": "percent", "frequency": "daily", "source": "SBP", "last_updated": "2026-09-24", "transform": null }, "data": [ { "date": "2026-09-24", "value": 11.75, "dims": { "side": "offer" } } ], "pagination": { "next_cursor": null, "count": 1 } } ``` List endpoints (funds, securities, auctions, trade, AMCs, search, calendar) return `{ "success": true, "data": [...], "count": N }`. Errors return `{ "success": false, "error": { "code", "message" } }` ([Errors](https://pakdatahub.com/docs/errors-rate-limits.md)). ## Endpoints ### Discovery (public) | Endpoint | Page | |---|---| | `GET /v1/catalog`, `GET /v1/catalog/{id}` | [Catalog](https://pakdatahub.com/docs/api-catalog.md) | | `GET /v1/search?q=` | [Search](https://pakdatahub.com/docs/api-search.md) | | `GET /v1/calendar` | [Release calendar](https://pakdatahub.com/docs/api-calendar.md) | | `GET /v1/status` | [Status](https://pakdatahub.com/docs/api-status.md) | | `GET /v1/plans` | [Billing](https://pakdatahub.com/docs/api-billing.md) | ### Time series (key required) | Endpoint | Page | |---|---| | `GET /v1/series/{id}`, `GET /v1/series/{id}/latest` | [Series](https://pakdatahub.com/docs/api-series.md) | | `?transform=yoy\|mom\|pct_change\|3ma\|index` | [Transforms](https://pakdatahub.com/docs/api-transforms.md) | | `?vintage=YYYY-MM-DD` | [Revision vintages](https://pakdatahub.com/docs/api-vintages.md) | | `GET /v1/commodities`, `/by-city`, `/items`, `/cities` | [Commodities](https://pakdatahub.com/docs/api-commodities.md) | ### Datasets (key required) | Endpoint | Page | |---|---| | `GET /v1/funds`, `/screener`, `/{id}`, `/{id}/nav\|returns\|payouts\|expenses\|portfolio` | [Mutual funds](https://pakdatahub.com/docs/api-funds.md) | | `GET /v1/funds/{id}/analytics` | [Fund analytics](https://pakdatahub.com/docs/api-fund-analytics.md) | | `GET /v1/amcs`, `GET /v1/amcs/{amc}` | [AMCs](https://pakdatahub.com/docs/api-amcs.md) | | `GET /v1/securities`, `/{code}/prices`, `/trades` | [Debt securities](https://pakdatahub.com/docs/api-securities.md) | | `GET /v1/fixed-income/auctions` | [Auctions](https://pakdatahub.com/docs/api-auctions.md) | | `GET /v1/trade` | [External trade](https://pakdatahub.com/docs/api-trade.md) | ### Account (key required) / session | Endpoint | Page | |---|---| | `GET /v1/usage`, `/v1/usage/history` | [Usage](https://pakdatahub.com/docs/api-usage.md) | | `GET/PATCH /v1/account`, `GET/POST/DELETE /v1/keys` | [Account & keys](https://pakdatahub.com/docs/api-account-keys.md) | | `GET/POST/DELETE /v1/webhooks` | [Webhooks](https://pakdatahub.com/docs/api-webhooks.md) | | `POST /auth/signup\|login\|logout\|change-password\|set-password`, Google | [Auth](https://pakdatahub.com/docs/api-auth.md) | | `POST /v1/checkout`, `GET /v1/billing/portal`, `GET /v1/account/key/{token}` | [Billing](https://pakdatahub.com/docs/api-billing.md) | ## Quick examples ```bash # public: discover curl "https://api.pakdatahub.com/v1/search?q=remittances" # keyed: data curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/series/remittances.total?from=2024-01-01&sort=asc" ``` ```python import httpx r = httpx.get("https://api.pakdatahub.com/v1/series/fx.rate.avg.usd", params={"from": "1947-01-01", "sort": "asc"}, headers={"X-API-Key": "pk_live_xxx"}, timeout=30) print(r.json()["data"][-1]) ``` ```js const res = await fetch("https://api.pakdatahub.com/v1/series/rates.kibor.3m/latest?dims=side:offer", { headers: { "X-API-Key": "pk_live_xxx" } }); const { meta, data } = await res.json(); console.log(meta.name, data[0].value); ``` What data exists: the [data dictionary](https://pakdatahub.com/docs/data-dictionary.md). Copy-paste recipes for each dataset: [API guides](https://pakdatahub.com/guides). # Catalog The catalog describes every series: its id, name, unit, frequency, source, date range and dimensions. It is **public**, so no key is needed. Use it to build pickers, find ids, or list everything. ## `GET /v1/catalog` List and filter series metadata. | Param | Type | Default | Notes | |---|---|---|---| | `module` | string | - | `forex`, `fixed-income`, `economic`, `prices`, `commodities`, `external`, `monetary`, `real`, `public-finance`, `debt`, `social`, `alternate` | | `source` | string | - | `SBP`, `PBS`, `PTA`, `MUFAP` | | `q` | string | - | Full-text filter over id, name and description | | `limit` | int | 500 | 1-5000 | | `offset` | int | 0 | For paging through large modules | | `canonical_only` | bool | false | Drop near-duplicate series that point at a canonical one | ```bash curl "https://api.pakdatahub.com/v1/catalog?module=forex&q=usd&limit=2" ``` ```json { "success": true, "data": [ { "id": "fx.rate.avg.usd", "module": "forex", "name": "Average Exchange rate of Pak Rupees per U.S. Dollar", "description": "Average Exchange rate of Pak Rupees per U.S. Dollar", "unit": "pkr", "frequency": "monthly", "source": "SBP", "source_url": "https://easydata.sbp.org.pk/api/v1/series/TS_GP_ER_FAERPKR_M.E00220/data", "dimensions": {}, "first_date": "1947-08-31", "last_date": "2026-08-31", "tier": "basic", "canonical_id": null }, { "id": "fx.rate.monthend.usd", "module": "forex", "...": "..." } ], "pagination": { "next_cursor": null, "count": 100 } } ``` `pagination.count` is the **total** number of matches, so page with `offset` until you've read `count` rows. For example, the `external` module holds 9,176 series: ```python import httpx rows, offset = [], 0 while True: page = httpx.get("https://api.pakdatahub.com/v1/catalog", params={"module": "external", "limit": 5000, "offset": offset}).json() rows += page["data"] offset += 5000 if offset >= page["pagination"]["count"]: break print(len(rows)) ``` ## `GET /v1/catalog/{series_id}` The full record for one series. It is **not** wrapped in an envelope: ```bash curl "https://api.pakdatahub.com/v1/catalog/rates.kibor.3m" ``` ```json { "id": "rates.kibor.3m", "module": "fixed-income", "name": "KIBOR 3-Month", "description": "Karachi Interbank Offered Rate, 3-month tenor (bid/offer)", "unit": "percent", "frequency": "daily", "source": "SBP", "source_url": "https://www.sbp.org.pk/ecodata/kibor/kibor.asp", "dimensions": { "side": ["bid", "offer"] }, "first_date": "2005-06-09", "last_date": "2026-10-02", "tier": "basic", "canonical_id": null } ``` An unknown id returns `404 not_found`. The fields are explained in [Series & the catalog](https://pakdatahub.com/docs/series-and-catalog.md#the-catalog-record). ## Tips - For a ranked "best match" rather than a filter, use [`/v1/search`](https://pakdatahub.com/docs/api-search.md). - `last_date` tells you how fresh a series is without spending a keyed request. - Every series also has a web page at `https://pakdatahub.com/series/{id}`. # Search ## `GET /v1/search` Ranked search over the catalog. Exact id matches rank first, then id-prefix matches, then name matches, then description matches. It powers the CmdK search on the website. **Public**, no key. | Param | Type | Default | Notes | |---|---|---|---| | `q` | string | required | Search text (at least 1 character) | | `module` | string | - | Restrict to one module | | `limit` | int | 20 | 1-50 | ```bash curl "https://api.pakdatahub.com/v1/search?q=kibor&limit=3" ``` ```json { "success": true, "count": 3, "data": [ { "id": "rates.kibor.1y", "module": "fixed-income", "name": "KIBOR 1-Year", "unit": "percent", "frequency": "daily", "source": "SBP", "tier": "basic" }, { "id": "rates.kibor.3m", "module": "fixed-income", "name": "KIBOR 3-Month", "unit": "percent", "frequency": "daily", "source": "SBP", "tier": "basic" }, { "id": "rates.kibor.6m", "module": "fixed-income", "name": "KIBOR 6-Month", "unit": "percent", "frequency": "daily", "source": "SBP", "tier": "basic" } ] } ``` ## Good queries | Looking for | Try | |---|---| | Exchange rates | `q=usd`, `q=exchange rate`, `q=reer` | | Inflation | `q=cpi`, `q=cpi urban food`, `q=wpi` | | Rates | `q=kibor`, `q=pkrv`, `q=policy`, `q=cut off yield` | | External sector | `q=remittances`, `q=current account`, `q=reserves`, `q=foreign direct investment` | | Money & banking | `q=broad money`, `q=m2`, `q=deposits`, `q=npl` | | Real economy | `q=gdp`, `q=auto sales`, `q=electricity generation`, `q=cement` | | Payments | `q=raast`, `q=pos`, `q=cards` | Then fetch the id with [`/v1/series/{id}`](https://pakdatahub.com/docs/api-series.md). To filter rather than rank, use [`/v1/catalog?q=`](https://pakdatahub.com/docs/api-catalog.md). # Series The workhorse endpoint. One call pattern covers every time series in the catalog: exchange rates, KIBOR, CPI, reserves, GDP, Raast, telecom and the rest. ## `GET /v1/series/{series_id}` (key required) | Param | Type | Default | Notes | |---|---|---|---| | `from` | date | - | Earliest observation date, inclusive. On Free/Developer it is raised to your history floor | | `to` | date | - | Latest observation date, inclusive | | `dims` | string | - | Dimension filter `key:value`, comma-separated for several, e.g. `side:offer` or `city:karachi` | | `limit` | int | 1000 | 1-10000 | | `sort` | `asc`\|`desc` | `desc` | By date. With `desc` + `limit` you get the **most recent** N points | | `format` | `json`\|`csv` | `json` | CSV is formula-injection-safe | | `transform` | string | - | `yoy`, `mom`, `pct_change`, `3ma`, `index`, computed server-side ([Transforms](https://pakdatahub.com/docs/api-transforms.md)) | | `vintage` | date | - | Pro/Business: values as first recorded on that date ([Vintages](https://pakdatahub.com/docs/api-vintages.md)) | ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/rates.kibor.3m?dims=side:offer&limit=2" ``` ```json { "success": true, "series": "rates.kibor.3m", "meta": { "name": "KIBOR 3-Month", "unit": "percent", "frequency": "daily", "source": "SBP", "last_updated": "2026-09-24", "transform": null }, "data": [ { "date": "2026-09-24", "value": 11.75, "dims": { "side": "offer" } }, { "date": "2026-09-23", "value": 11.75, "dims": { "side": "offer" } } ], "pagination": { "next_cursor": null, "count": 2 } } ``` ### Response fields | Field | Type | Meaning | |---|---|---| | `series` | string | The requested id | | `meta.name` | string | Human-readable name | | `meta.unit` | string | Unit after any transform (e.g. `percent` for `yoy`) | | `meta.frequency` | string | `daily`, `weekly`, `monthly`, `quarterly`, `half_yearly`, `annual`, `irregular` | | `meta.source` | string | `SBP`, `PBS`, `PTA`, `MUFAP` | | `meta.last_updated` | date | Date of the newest observation we hold | | `meta.transform` | string\|null | Echo of the applied transform | | `data[].date` | date | Observation date (month-end for monthly, quarter-end for quarterly) | | `data[].value` | number\|null | The value; `null` where a transform has no partner point | | `data[].dims` | object | Dimension tags, e.g. `{"side":"offer"}`, `{"city":"lahore"}` | | `pagination.count` | int | Rows returned. `next_cursor` is always `null`; page by date with `from`/`to` | ### CSV ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/fx.rate.avg.usd?format=csv&limit=3" ``` ``` series,date,value,dims fx.rate.avg.usd,2026-08-31,277.9187406,{} fx.rate.avg.usd,2026-07-31,278.2380682,{} fx.rate.avg.usd,2026-06-30,278.5795536,{} ``` The content type is `text/csv; charset=utf-8`. This works directly with `pandas.read_csv(url + "&api_key=...")`, Excel "From Web" and Google Sheets `IMPORTDATA`. ### Paging long histories `limit` goes up to 10,000, which covers every monthly and quarterly series in one call. For long daily series, window by date: ```python import httpx key = {"X-API-Key": "pk_live_xxx"} url = "https://api.pakdatahub.com/v1/series/rates.pkrv.10y" rows = [] for year in range(2022, 2027): r = httpx.get(url, params={"from": f"{year}-01-01", "to": f"{year}-12-31", "sort": "asc", "limit": 10000}, headers=key) rows += r.json()["data"] ``` ## `GET /v1/series/{series_id}/latest` (key required) The newest observation, and one row per dimension when the series has dimensions (e.g. both KIBOR bid and offer). It's cached server-side, so it's cheap and ideal for tickers and dashboards. It accepts `dims` (e.g. `dims=side:offer` for one row instead of every side) and `format=csv`. ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/fx.rate.avg.usd/latest" ``` ```json { "success": true, "series": "fx.rate.avg.usd", "meta": { "name": "Average Exchange rate of Pak Rupees per U.S. Dollar", "unit": "pkr", "frequency": "monthly", "source": "SBP", "last_updated": "2026-08-31", "transform": null }, "data": [ { "date": "2026-08-31", "value": 277.9187406, "dims": {} } ], "pagination": { "next_cursor": null, "count": 1 } } ``` ## Errors - `404`: unknown series id. Check with [`/v1/search`](https://pakdatahub.com/docs/api-search.md). - `422`: bad date, bad `dims` token (it must be `key:value`), unknown transform, or a transform that doesn't fit the frequency. - `403`: `vintage` on a plan below Pro. ## Popular ids `fx.rate.avg.usd` - `fx.effective.reer` - `rates.kibor.3m` - `rates.policy` - `rates.pkrv.10y` - `inflation.cpi.national.yoy` - `inflation.cpi.urban.food` - `remittances.total` - `reserves.total_sbp_reserves` - `banking.m2` - `industry.lsm.qim` - `payments.raast.total.value` - `telecom.subscribers.cellular.total` - `sme.npl_ratio`. See the [data dictionary](https://pakdatahub.com/docs/data-dictionary.md) for more. # Transforms Add `?transform=` to [`/v1/series/{id}`](https://pakdatahub.com/docs/api-series.md) and the API computes the transform for you. Your numbers then match everyone else's, and you don't have to fetch extra history to do it yourself. | `transform` | Meaning | Allowed frequencies | Output unit | |---|---|---|---| | `yoy` | Year-over-year % change: value vs the same date one year earlier | daily, weekly, monthly, quarterly | `percent` | | `mom` | Month-over-month % change | monthly only | `percent` | | `pct_change` | % change vs the previous observation | any | `percent` | | `3ma` | Trailing 3-period moving average | any | source unit | | `index` | Rebased to 100 at the first observation **in your window** | any | `index` | ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/inflation.cpi.national?transform=yoy&limit=2" ``` ```json { "success": true, "series": "inflation.cpi.national", "meta": { "name": "CPI National", "unit": "percent", "frequency": "monthly", "source": "PBS", "last_updated": "2026-06-30", "transform": "yoy" }, "data": [ { "date": "2026-06-30", "value": 11.090083270249806, "dims": {} }, { "date": "2026-05-31", "value": 11.64643399089529, "dims": {} } ], "pagination": { "next_cursor": null, "count": 2 } } ``` ## Rules - **Partners are fetched for you.** `yoy`, `mom`, `pct_change` and `3ma` look back before your `from` date and outside your `limit`, so every returned point has its partner. A point is `null` only where no earlier observation exists at all (e.g. the first year of a series). - **Per dimension.** Transforms run separately for each `dims` group (KIBOR bid and offer, each SPI city). - **`index` uses your window.** It rebases to 100 at the first point you get back, so pick `from` deliberately: ```bash # Rupee depreciation since 2018, as an index curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/fx.rate.avg.usd?from=2018-01-01&transform=index&sort=asc" ``` - **Mismatches fail loudly.** `mom` on a quarterly series, or `yoy` on an annual one, returns `422 invalid_params` with a message suggesting `pct_change`. - Transforms combine with `vintage`, `dims`, `format=csv` and `sort`. ## Recipes | Question | Call | |---|---| | Headline inflation from the index | `/v1/series/inflation.cpi.national?transform=yoy` | | Monthly change in FX reserves | `/v1/series/reserves.total_sbp_reserves?transform=mom` | | Remittance growth vs a year ago | `/v1/series/remittances.total?transform=yoy` | | Smoothed LSM | `/v1/series/industry.lsm.qim?transform=3ma` | | Compare currencies on one axis | `fx.rate.avg.usd`, `fx.rate.avg.eur` with `transform=index&from=2015-01-01` | | Raast quarter-on-quarter growth | `/v1/series/payments.raast.total.value?transform=pct_change` | # Revision vintages Official statistics get revised: GDP, the balance of payments, remittances, reserves and more. Add `?vintage=YYYY-MM-DD` to [`/v1/series/{id}`](https://pakdatahub.com/docs/api-series.md) and every observation comes back **as we had recorded it by the end of that date**. **Plan:** Pro and Business. Lower plans get `403`. ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/inflation.cpi.national?vintage=2026-08-31&limit=3" ``` The response has the normal series envelope. The values are the ones in effect on the vintage date. ## How it works - Whenever a stored value changes on a later ingest, we record the old value and when it was replaced. Re-ingesting an unchanged value costs nothing and isn't a revision. - For each `(date, dims)`, a vintage request returns the value current at the vintage date. Points first recorded **after** the vintage date are left out. - Our own revision tracking runs from **August 2026**. Before that, history comes from the **SBP's Monthly Statistical Bulletin archive** (see below). - To see a point's whole history at once (first print, every revision and when it happened), use [`/revisions`](#the-revisions-endpoint). - Points with no recorded history before a vintage date come back at the earliest value we hold. ## Revision history from the SBP Statistical Bulletin (2008 ->) Every monthly issue of the State Bank's *Monthly Statistical Bulletin* opens with a table of headline indicators for the last 12-13 months, **as published that month**. We read every issue SBP still hosts, from 2005 to 2026 (258 issues), so for the series it covers you get each month's **first print** and **every revision, dated by the issue that printed it**: the point-in-time history that no longer exists on the SBP's live site, where a revision overwrites the original. We also read the bulletin's national-accounts tables (GDP by sector, at current and constant prices, marked provisional and revised), 2005-2023. Together that is about 8,800 first prints and 7,500 dated revisions on 70 series: 59 of ours matched by value, plus the 11 below that come straight from the bulletin. The 2005-2007 issues carried an older indicators table (call money rate, WPI, industrial output), so first prints of most of today's indicators start in 2008. Covered series (and their twins under other dataset ids): | What | Example id | |---|---| | USD/PKR, month average and month end | `fx.rate.avg.usd`, `fx.rate.monthend.usd` | | Workers' remittances | `remittances.total`, `external.workers_remittances` | | Exports and imports of goods (BOP) | `bop.goods_export_fob`, `bop.goods_import_fob` | | GDP by sector and in total, constant prices (bases 2005-06 and 2015-16); nominal GDP | `gdp.gross_domestic_product_total_gross_value_add_2`, `gdp.agricultural_sector_2`, `fiscal.gross_domestic_product_2` | | FX reserves: liquid, gold & FX, net with SBP | `reserves.total_liquid_fx_reserves`, `reserves.total_reserve_assets` | | CPI inflation YoY: national, urban, rural, food, non-food, core | `inflation.cpi.national.yoy`, `inflation.cpi.urban.yoy` | | Real and nominal effective exchange rates | `fx.effective.reer`, `fx.effective.neer` | | Banks' weighted-average lending and deposit rates (fresh and outstanding) | `banking.lending_marginal_overall`, `banking.deposit_stocks_overall` | | Net portfolio investment (BOP) | `bop.net_portfolio_investment` | | National Savings Schemes outstanding | `debt.saving_schemes_total_outstanding_amount` | | KSE-100 index, month end | `money.kse_100_index_last_working_day_month` | ### Series that come from the bulletin itself Some bulletin rows have no equivalent elsewhere in the catalog, so we serve them as series in their own right. Each value is the bulletin's latest print, and every earlier print is kept as a dated revision: | What | Id | From | |---|---|---| | Broad money (M2), month-end | `money.m2.monthly` | 2007 | | 1-month KIBOR, month-end and monthly average | `rates.kibor.1m.month_end`, `rates.kibor.1m.month_avg` | 2007 | | Scheduled banks' advances-to-deposits and investment-to-deposits ratios, monthly | `banking.advances_to_deposits_ratio.monthly`, `banking.investment_to_deposits_ratio.monthly` | 2004 | | National CPI food, non-food and NFNE core inflation; 20% trimmed-mean core (historical) | `inflation.cpi.national.food.yoy`, `inflation.cpi.national.nonfood.yoy`, `inflation.core.nfne.national.yoy`, `inflation.core.trimmed_mean.national.yoy` | 2007-2019 | | National CPI levels on the old bases (historical) | `inflation.cpi.national.index_2000_01`, `inflation.cpi.national.index_2007_08` | 2004-2019 | How we keep it honest: - A bulletin row is matched to one of our series **by its values**, not its label: its figures must agree with ours to the precision printed (or, for heavily revised series such as exports, sit within 15% across most months). Each series takes rows of one label family and one unit only, and a rebased index is never mixed with its old base. - A series whose final printed figures often stay far from today's values is a different concept that only coincides in most months (the bulletin's total FDI and portfolio investment vs our narrower series, for example). Those are left out rather than recorded as revisions. - A figure printed in a single issue and contradicted on both sides is treated as a reading slip and dropped. A misprint that SBP carried for several issues is kept, because it was the published number: the July 2010 lending rate printed as 36.36% for eight issues before it became 13.36%. - Each figure is dated at the end of the month its issue came out, a conservative "public by" date. If a figure was revised after the bulletin stopped printing it, we can't date that change, so the bulletin's last value counts as current until our own tracking began (August 2026). ```bash # Remittances for Feb-Apr 2015 as published on 30 June 2015 (first prints) curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/remittances.total?vintage=2015-06-30&from=2015-02-01&to=2015-04-30&sort=asc" ``` ## The `/revisions` endpoint `GET /v1/series/{id}/revisions` lists each point's history in one call: the first print, every figure it replaced with the date it stopped being current and where that print came from, and today's value. Same plan as vintages (Pro and Business; `403` otherwise). Parameters: `from`, `to`, `dims`, `limit`, `sort`, and `changed_only=true` to keep only points that were ever revised. ```bash curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/series/bop.goods_export_fob/revisions?from=2020-01-01&to=2020-01-31" ``` January 2020 exports (US$ million): first printed as 2,051, revised to 2,052, then 2,053, and 2,056 today. ```json { "success": true, "series": "bop.goods_export_fob", "data": [ { "date": "2020-01-31", "dims": {}, "value": 2056.0, "first_print": 2051, "first_seen": "2020-03-31", "revisions": [ { "value": 2051.0, "until": "2020-04-30", "source": "SBP Monthly Statistical Bulletin" }, { "value": 2052.0, "until": "2020-08-31", "source": "SBP Monthly Statistical Bulletin" }, { "value": 2053.0, "until": "2026-08-17", "source": "SBP Monthly Statistical Bulletin" } ] } ], "pagination": { "next_cursor": null, "count": 1, "revised_points": 1 } } ``` `first_seen` is the date the figure was first public (the end of the month of the first issue that printed it, or when our own tracking first recorded it). `source` is `PakDataHub revision tracking` for revisions we recorded ourselves since August 2026. A last bulletin figure that differs from today's value, with no dated print of the change, is shown as superseded on 17 August 2026, when our own tracking began. ## Uses - **Reproducibility:** rerun a model on the data exactly as it stood when the model was built. - **Nowcasting and backtests:** train only on the numbers that were actually available at the time. - **Revision studies:** first print vs latest print. Combine with a transform for a first-print YoY: ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/inflation.cpi.national?vintage=2026-08-31&transform=yoy" ``` # Commodities Weekly retail prices from the Pakistan Bureau of Statistics' **Sensitive Price Indicator (SPI)**: 30 essential items, reported for 17 cities plus a national average. These are shortcuts over the `commodities.*` series, which carry a `city` dimension. ## `GET /v1/commodities/items` - public Every item, with its id and unit: ```json { "success": true, "data": [ { "id": "commodities.wheat_flour", "name": "Wheat Flour (20 Kg Bag)", "unit": "pkr_per_20kg" }, { "id": "commodities.rice_basmati", "name": "Rice Basmati Broken", "unit": "pkr_per_kg" }, { "id": "commodities.milk_fresh", "name": "Milk Fresh (Un-boiled)", "unit": "pkr_per_litre" } ] } ``` Items: `wheat_flour`, `rice_basmati`, `rice_irri`, `bread`, `beef`, `mutton`, `chicken`, `milk_fresh`, `eggs`, `sugar`, `gur`, `salt`, `tea_packet`, `cooking_oil`, `mustard_oil`, `vegetable_ghee_loose`, `vegetable_ghee_tin`, `pulse_masoor`, `pulse_moong`, `pulse_mash`, `pulse_gram`, `potatoes`, `onions`, `tomatoes`, `garlic`, `petrol`, `diesel`, `lpg`, `gas`, `electricity`. **Check the unit.** Units vary by item. Most are per kg, but some aren't: | Item | Unit | |---|---| | wheat flour | per 20 kg bag | | eggs | per dozen | | milk, petrol, diesel | per litre | | cooking oil | per 5 litres | | vegetable ghee (tin) | per 2.5 kg | | tea | per 190 g pack | | salt | per 800 g | | LPG | per cylinder | | gas | per MMBTU | | electricity | per unit | | bread | each | ## `GET /v1/commodities/cities` - public ```json { "success": true, "data": ["bahawalpur","bannu","faisalabad","gujranwala","hyderabad","islamabad","karachi","khuzdar","lahore","larkana","multan","national","peshawar","quetta","rawalpindi","sargodha","sialkot","sukkur"] } ``` `national` is the unweighted mean across the reporting cities. ## `GET /v1/commodities` (key required) The national-average price series for one item. | Param | Type | Default | Notes | |---|---|---|---| | `item` | string | required | `wheat_flour`, `commodities.wheat_flour` (either works) | | `from`, `to` | date | - | Date window (weeks end on Thursday) | | `limit` | int | 1000 | 1-10000 | | `sort` | `asc`\|`desc` | `desc` | | ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/commodities?item=wheat_flour&limit=2" ``` The response uses the standard series envelope, with `data[].dims = {"city": "national"}`. ## `GET /v1/commodities/by-city` (key required) The same item in one city. | Param | Type | Notes | |---|---|---| | `item` | string | required | | `city` | string | required, one of `/cities` | | `from`, `to`, `limit`, `sort` | | as above | ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/commodities/by-city?item=petrol&city=lahore&from=2026-01-01&sort=asc" ``` ## Equivalent generic call The same data through [`/v1/series`](https://pakdatahub.com/docs/api-series.md). This form also accepts transforms: ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/commodities.sugar?dims=city:karachi&transform=yoy" ``` ## Related - A per-city **cost-of-living index** built from these prices: series `cost_of_living.` (weekly, rebased to 100), and the free [cost-of-living tool](https://pakdatahub.com/tools/cost-of-living). - Coverage and history: [Commodities dataset](https://pakdatahub.com/docs/data-commodities.md). # Wholesale prices API (`/v1/agri`) Daily wholesale prices from Punjab's mandis, from the Punjab **AMIS**. About the data: [Wholesale (mandi) prices](https://pakdatahub.com/docs/data-agri-prices.md). ## `GET /v1/agri/markets` - public Every market, with `market_id`, `name`, `slug`, `is_major` (updated every evening) and the dates it has prices for. ## `GET /v1/agri/commodities` - public Every commodity, with `commodity_id`, `name`, `slug`, `category` (`Grains`, `Vegetables`, `Fruits`) and `unit` (`pkr_per_100kg`, or `pkr_per_dozen` for bananas). ## `GET /v1/agri/prices` (key required) A commodity's daily prices in one market, or in every market if you leave `market` out. | Param | Notes | |---|---| | `commodity` | Required. AMIS id or slug, e.g. `onion`, `1` (wheat) | | `market` | AMIS id or slug, e.g. `lahore`. Leave it out for every market | | `from`, `to` | Date range (`YYYY-MM-DD`). Clamped to your plan's history window | | `limit` | 1-10000 (default 1000) | | `sort` | `desc` (default) or `asc` | | `format` | `json` or `csv` | ```json { "success": true, "commodity": { "commodity_id": 1, "name": "Wheat", "slug": "wheat", "category": "Grains", "unit": "pkr_per_100kg" }, "market": { "market_id": 2, "name": "Faisalabad", "slug": "faisalabad" }, "source": "AMIS Punjab (Directorate of Agriculture, Economics & Marketing)", "data": [ { "date": "2026-10-05", "market": "Faisalabad", "market_id": 2, "commodity": "Wheat", "commodity_id": 1, "min": 11500.0, "max": 12000.0, "fqp": 11750.0, "quantity": null, "unit": "pkr_per_100kg" } ], "count": 1 } ``` `fqp` is the fair-quality price, the representative one. `min` and `max` are the day's range; for dates before October 2026 they are `null`, because the history carries the fair-quality price only. ## `GET /v1/agri/latest` (key required) The most recent price (within the last 30 days) of one commodity in every market that reported it. It's built for a "today's mandi rates" table. Params: `commodity` (required), `format`. ## Errors `404` for an unknown commodity or market, `401` without a key, `422` for a bad parameter. Same envelope as the rest of the API ([errors](https://pakdatahub.com/docs/errors-rate-limits.md)). # Mutual funds Every open-end and pension fund reported by the **Mutual Funds Association of Pakistan (MUFAP)**, 567 funds from 25 asset managers. The data covers daily NAVs back to 1996, trailing returns, dividend payouts, expense ratios (TER) and monthly asset allocation. Funds are identified by MUFAP's numeric `fund_id`. ## `GET /v1/funds` (key required) List and search funds. | Param | Type | Notes | |---|---|---| | `amc` | string | Asset-manager filter, partial match (e.g. `Meezan`, `ABL`) | | `category` | string | e.g. `Money Market`, `Equity`, `Shariah Compliant Income` | | `sector` | string | e.g. `Open-End Funds` | | `q` | string | Fund-name filter | | `limit` | int | Default 1000 | ```bash curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/funds?amc=Meezan&limit=2" ``` ```json { "success": true, "count": 2, "data": [ { "fund_id": 12821, "name": "Al Meezan Mutual Fund", "amc": "Al Meezan Investment Management Limited", "sector": "Open-End Funds", "category": "Shariah Compliant Equity", "inception_date": "1995-07-13", "trustee": "CDC", "latest_nav": { "date": "2026-09-17", "nav": 48.071, "offer": 49.1766, "repurchase": 48.071 } }, { "fund_id": 12826, "name": "KSE Meezan Index Fund", "...": "..." } ] } ``` ## `GET /v1/funds/screener` (key required) **Every active fund in one response**, with the fields a screener ranks on. Use it instead of calling `/returns` and `/expenses` once per fund. It's cached for about an hour. ```json { "success": true, "count": 588, "data": [ { "fund_id": 14750, "name": "786 Islamic Money Market Fund", "amc": "786 Investments Limited", "category": "Shariah Compliant Money Market", "sector": "Open-End Funds", "rating": null, "benchmark": "N/A", "nav": { "date": "2026-09-18", "value": 102.7144 }, "returns": { "as_of": "2026-09-23", "ytd": 9.84, "m3": 9.94, "y1": 9.83 }, "ter_ytd": 0.79, "ter_as_of": "2026-09-18" } ] } ``` `returns` are MUFAP's reported trailing returns in % (`m3` = 90 days, `y1` = 365 days, `ytd` = fiscal year to date, where Pakistan's fiscal year starts 1 July). `ter_ytd` is the total expense ratio in %. The free [fund screener tool](https://pakdatahub.com/tools/fund-screener) is built on this endpoint. ## `GET /v1/funds/{fund_id}` (key required) Profile plus latest NAV: ```json { "success": true, "fund": { "fund_id": 12843, "name": "Meezan Asset Allocation Fund", "amc": "Al Meezan Investment Management Limited", "sector": "Open-End Funds", "category": "Shariah Compliant Asset Allocation", "inception_date": "2016-04-18", "trustee": "CDC" }, "latest_nav": { "date": "2026-09-18", "nav": 113.0185, "offer": 116.9176, "repurchase": 113.0185 } } ``` ## `GET /v1/funds/{fund_id}/nav` (key required) Daily NAV history. Params: `from`, `to`, `limit` (default 1000), `sort`. ```json { "success": true, "fund_id": 12843, "count": 2, "data": [ { "date": "2026-09-18", "nav": 113.0185, "offer": 116.9176, "repurchase": 113.0185 }, { "date": "2026-09-17", "nav": 112.1417, "offer": 116.0105, "repurchase": 112.1417 } ] } ``` Historical points before a fund's daily snapshots began carry `nav` only. Free and Developer plans are clamped to their history window. ## `GET /v1/funds/{fund_id}/returns` (key required) MUFAP trailing returns, in %, as published each day. Params: `from`, `to`, `limit`, `sort`. ```json { "success": true, "fund_id": 12843, "count": 1, "data": [ { "date": "2026-09-23", "rating": null, "benchmark": "N/A", "ytd": null, "mtd": null, "d1": 0.72, "d15": null, "d30": null, "d90": null, "d180": 11.14, "d270": null, "d365": 0.17 } ] } ``` `dN` = N-day return. A `null` means MUFAP didn't publish that period. **Annualized for fixed-income funds:** following MUFAP's convention, returns for money-market, income, fixed-rate and other debt funds are **annualized**, while equity-type funds report plain period returns. A one-day return (`d1`) annualized can therefore look extreme, e.g. 100%+ after a sharp daily NAV move. To compare funds, use longer windows (`d90`, `d365`), or [`/analytics`](https://pakdatahub.com/docs/api-fund-analytics.md) for returns computed from the full NAV history (3y, 5y, CAGR, volatility, drawdown). ## `GET /v1/funds/{fund_id}/payouts` (key required) Dividend and payout history, back to about 2010. Param: `limit`. ```json { "success": true, "fund_id": 12843, "count": 2, "data": [ { "payout_date": "2025-06-27", "per_unit": 1.0, "ex_nav": 93.1809 }, { "payout_date": "2024-06-28", "per_unit": 3.25, "ex_nav": 60.7337 } ] } ``` Daily-dividend money-market funds have thousands of records. ## `GET /v1/funds/{fund_id}/expenses` (key required) Expense ratios over time, in %. Param: `limit`. ```json { "success": true, "fund_id": 12843, "count": 1, "data": [ { "date": "2026-09-18", "ter_mtd": 4.87, "ter_ytd": 4.87, "management_fee": 3.0, "selling_marketing": 0.0 } ] } ``` ## `GET /v1/funds/{fund_id}/portfolio` (key required) The latest monthly asset allocation, as a % of net assets: ```json { "success": true, "fund_id": 12843, "as_of": "2026-08-01", "count": 4, "data": [ { "asset_class": "Equities", "percent": 89.96 }, { "asset_class": "Cash", "percent": 10.23 }, { "asset_class": "Other & receivables", "percent": 0.69 }, { "asset_class": "Liabilities", "percent": -0.88 } ] } ``` Allocations sum to about 100%. A negative `Liabilities` line is normal: it reconciles gross holdings to net assets. The asset classes include Cash, Equities, T-Bills, PIBs, GoP Ijara Sukuk, TFCs/Sukuk, placements, Commodity/Gold and others. ## Recipes ```python import httpx, pandas as pd H = {"X-API-Key": "pk_live_xxx"} B = "https://api.pakdatahub.com/v1/funds" # Top 10 money-market funds by 1-year return, from one call s = pd.json_normalize(httpx.get(f"{B}/screener", headers=H).json()["data"]) mm = s[s["category"].str.contains("Money Market")] print(mm.sort_values("returns.y1", ascending=False).head(10)[["name", "amc", "returns.y1", "ter_ytd"]]) # Full NAV history of one fund nav = pd.DataFrame(httpx.get(f"{B}/12843/nav", params={"sort": "asc", "limit": 10000}, headers=H).json()["data"]) ``` Related: [Fund analytics](https://pakdatahub.com/docs/api-fund-analytics.md) - [AMCs](https://pakdatahub.com/docs/api-amcs.md) - [Mutual funds dataset](https://pakdatahub.com/docs/data-mutual-funds.md). # Fund analytics ## `GET /v1/funds/{fund_id}/analytics` (key required) Performance analytics **computed server-side from the fund's full daily NAV history**, so you don't have to do the maths yourself. ```bash curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/funds/12843/analytics" ``` ```json { "success": true, "fund_id": 12843, "trailing_returns": { "1m": -3.38, "3m": -3.35, "6m": 9.44, "ytd": -6.3, "1y": -0.11, "3y": 160.7, "5y": 130.68, "since_inception": 126.04 }, "annualized_returns": { "3y": 37.66, "5y": 18.21 }, "cagr_since_inception": 8.14, "volatility_annualized": 21.96, "max_drawdown": -57.0, "first_date": "2016-04-18", "last_date": "2026-09-18", "observations": 3379 } ``` | Field | Meaning | |---|---| | `trailing_returns.*` | Total % change in NAV over the period, ending at `last_date`. `ytd` runs from the calendar year start | | `annualized_returns.3y/5y` | CAGR-style annualized % over 3 and 5 years | | `cagr_since_inception` | Annualized % from the first NAV | | `volatility_annualized` | Standard deviation of month-end returns, annualized, in % | | `max_drawdown` | Largest peak-to-trough fall, in % (negative) | | `observations` | NAV points used | **Notes** - Returns are computed from NAV, so dividend payouts show up as NAV drops on the ex-date. For income funds that distribute heavily, compare with MUFAP's published returns ([`/returns`](https://pakdatahub.com/docs/api-funds.md)), which account for payouts. - A period longer than the fund's history returns `null`. On Free and Developer plans, NAVs older than your history window aren't used, so long-horizon fields may be `null`. - Results are cached for about an hour; NAVs update daily. # AMCs (asset managers) Fund data rolled up to the **asset-management company**: who runs which funds, how expensive they are, and how the funds are rated. It is derived from the MUFAP fund store and covers 25 AMCs. ## `GET /v1/amcs` (key required) ```json { "success": true, "count": 25, "data": [ { "amc": "Alfalah Asset Management Limited", "fund_count": 72, "avg_ter_ytd": 1.27, "oldest_inception": "2004-04-19", "categories": ["Aggressive Fixed Income", "Asset Allocation", "Equity", "Money Market", "..."] } ] } ``` ## `GET /v1/amcs/{amc}` (key required) `{amc}` is the full AMC name, URL-encoded and case-insensitive. ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/amcs/Al%20Meezan%20Investment%20Management%20Limited" ``` ```json { "success": true, "amc": "Al Meezan Investment Management Limited", "fund_count": 51, "avg_ter_ytd": 1.46, "oldest_inception": "1995-07-13", "categories": ["Shariah Compliant Asset Allocation", "Shariah Compliant Balanced", "..."], "rating_distribution": { "AA+(f)": 2, "AA(f)": 1, "AA-(f)": 1, "A+(f)": 1 }, "funds": [ { "fund_id": 12821, "name": "Al Meezan Mutual Fund", "category": "Shariah Compliant Equity", "inception_date": "1995-07-13" }, { "fund_id": 12826, "name": "KSE Meezan Index Fund", "category": "Shariah Compliant Index Tracker", "inception_date": "2012-05-28" } ] } ``` | Field | Meaning | |---|---| | `fund_count` | Active funds managed | | `avg_ter_ytd` | Mean total expense ratio (%) across its funds | | `rating_distribution` | Number of funds per fund-stability rating (e.g. `AA+(f)`), from MUFAP | | `funds` | Every fund. Fetch details with [`/v1/funds/{fund_id}`](https://pakdatahub.com/docs/api-funds.md) | An unknown name returns `404`. Get exact names from `GET /v1/amcs`. There's a web version at [/amcs](https://pakdatahub.com/amcs). # Debt securities Instrument-level debt prices from **MUFAP**: 193 instruments, with daily prices since 2022. ## `GET /v1/securities` (key required) | Param | Type | Notes | |---|---|---| | `type` | string | `pib_floating` (floating-rate PIBs), `gis_sukuk` (GoP Ijara Sukuk), `tfc_sukuk` (corporate TFCs and Sukuk) | | `q` | string | Code or issuer-name filter | | `limit` | int | Default 1000 | ```json { "success": true, "count": 1, "data": [ { "code": "PIBFR10YQ2030-10-22", "type": "pib_floating", "name": null, "rating_category": null, "sbp_code": null, "first_seen": "2024-11-20", "last_seen": "2026-09-23", "latest_price": { "date": "2026-09-23", "price": 98.81, "net_change": 0.02 } } ] } ``` A corporate example: ```json { "code": "ABPL/SUK/220817", "type": "tfc_sukuk", "name": "AL BARAKA BANK (PAKISTAN) LTD. - SUKUK (22-08-17) - Amortization", "rating_category": "RATED A", "first_seen": "2024-04-01", "last_seen": "2024-08-23", "latest_price": { "date": "2024-08-23", "price": 100.0, "net_change": null } } ``` **Codes:** - Floating PIBs: `PIBFR`. - GoP Ijara Sukuk: normalized to `GOPIS--`. - TFCs: MUFAP's own code, which **can contain slashes**. ## `GET /v1/securities/{code}/prices` (key required) Price history, per 100 of face value. Params: `from`, `to`, `limit`, `sort`. Send slashes in the code raw (don't URL-encode them); it's a path segment. ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/securities/PIBFR10YQ2030-10-22/prices?limit=2" ``` ```json { "success": true, "code": "PIBFR10YQ2030-10-22", "count": 2, "data": [ { "date": "2026-09-23", "price": 98.81, "net_change": 0.02 }, { "date": "2026-09-22", "price": 98.79, "net_change": 0.04 } ] } ``` ## `GET /v1/securities/trades` (key required) Trade-level secondary-market debt transactions (MUFAP "Debt Instruments Daily Trading"). | Param | Type | Notes | |---|---|---| | `from`, `to` | date | Trade date window | | `issue` | string | Issuer or instrument name filter, e.g. `K Electric` | | `limit` | int | Default 500 | ```json { "success": true, "count": 1, "data": [ { "trade_date": "2026-06-11", "bats": "BATS", "issue_name": "K Electric Ltd. Sukuk VI", "issue_date": "2022-11-23", "maturity_date": "2029-11-23", "listed": "Listed", "face_value": 70000.0, "volume": 357.0, "value_mn": 25.55, "price_pct": 102.25 } ] } ``` | Field | Meaning | |---|---| | `bats` | Venue: `BATS` (Bond Automated Trading System) or `Non-BATS` | | `value_mn` | Trade value in Rs million | | `price_pct` | Price as % of face value | ## Related - **Primary-market auction cut-offs:** [Auctions](https://pakdatahub.com/docs/api-auctions.md). - **Yield curves** (PKRV, PKISRV): [Rates dataset](https://pakdatahub.com/docs/data-rates.md). - **Government-securities holdings by investor type:** the `debt.*` series ([Debt dataset](https://pakdatahub.com/docs/data-debt.md)). - Web: [/securities](https://pakdatahub.com/securities) and [/securities/trades](https://pakdatahub.com/securities/trades). # Auctions ## `GET /v1/fixed-income/auctions` (key required) Primary-market auction results for government securities: the **cut-off yield** of each auction, by tenor. | Param | Type | Default | Notes | |---|---|---|---| | `type` | string | all | `tbill` (Market Treasury Bills), `pib` (fixed-rate Pakistan Investment Bonds), `gis` (GoP Ijara Sukuk) | | `from`, `to` | date | - | Auction date window | | `limit` | int | 500 | 1-5000, newest first | ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/fixed-income/auctions?type=tbill&limit=2" ``` ```json { "success": true, "count": 2, "data": [ { "type": "tbill", "tenor": "12m", "auction_date": "2026-07-23", "settlement_date": null, "cutoff_yield": 11.9938, "offered_amount": null, "accepted_amount": null, "bid_to_cover": null, "source": "SBP" }, { "type": "tbill", "tenor": "1m", "auction_date": "2026-07-23", "settlement_date": null, "cutoff_yield": 11.3504, "offered_amount": null, "accepted_amount": null, "bid_to_cover": null, "source": "SBP" } ] } ``` | Field | Meaning | |---|---| | `tenor` | T-Bills `1m`/`3m`/`6m`/`12m`; PIBs `2y`...`30y`; Sukuk `1y`...`10y` | | `cutoff_yield` | Cut-off yield in % (for GIS, the SBP-reported cut-off rental rate or price) | | `offered_amount`, `accepted_amount`, `bid_to_cover`, `settlement_date` | Currently `null`, because SBP's redesigned site no longer publishes them in a structured form | **History:** T-Bills from 2004, PIBs from 2000, sourced from SBP. The latest dates follow SBP's release of each auction. ## The same data as series Each type and tenor is also a series, which works with transforms and CSV: ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/rates.auction.tbill.3m.cutoff_yield?from=2020-01-01&sort=asc&format=csv" ``` Ids: `rates.auction.tbill.{1m,3m,6m,12m}.cutoff_yield`, `rates.auction.pib.{2y,3y,5y,10y,15y,20y,30y}.cutoff_yield`, `rates.auction.gis.{3y,5y}.cutoff_price`. Compare them with the secondary-market curve (`rates.pkrv.*`) and the policy rate. See the [Rates dataset](https://pakdatahub.com/docs/data-rates.md). # External trade ## `GET /v1/trade` (key required) Monthly merchandise **exports and imports by commodity**, from the Pakistan Bureau of Statistics' trade releases. | Param | Type | Notes | |---|---|---| | `flow` | string | `export` or `import` | | `commodity` | string | Commodity-name filter, partial and case-insensitive (e.g. `RICE`, `COTTON`, `PETROLEUM`) | | `group` | string | Commodity-group filter (e.g. `FOOD GROUP`, `TEXTILE GROUP`) | | `from`, `to` | date | Month window | | `limit` | int | Default 1000 | | `sort` | `asc`\|`desc` | Default `desc` | ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/trade?flow=export&commodity=RICE&limit=2" ``` ```json { "success": true, "count": 2, "data": [ { "flow": "export", "commodity": "1.RICE", "group": "FOOD GROUP", "date": "2026-08-31", "unit": "M.T", "quantity": 308481.3520889, "value_pkr_mn": 53294.1391308608, "value_usd_th": 191791.4218023 }, { "flow": "export", "commodity": "1.RICE / a) BASMATI", "group": "FOOD GROUP", "date": "2026-08-31", "unit": "M.T", "quantity": 77795.0193211, "value_pkr_mn": 24341.3079150581, "value_usd_th": 87612.2720203 } ] } ``` | Field | Meaning | |---|---| | `commodity` | PBS line item. Sub-items are parent-qualified, e.g. `1.RICE / a) BASMATI` | | `unit` | Quantity unit (`M.T` = metric tonnes, `DOZ`, `SQM`, ...) | | `value_pkr_mn` | Value in Rs million | | `value_usd_th` | Value in US$ thousand | **History:** roughly the trailing year of monthly releases (PBS rotates older files off its site), growing month by month. For longer-run trade aggregates, use the SBP series in the `external` module: total exports and imports as per the balance of payments since 2003, and exports by country and commodity. See the [External dataset](https://pakdatahub.com/docs/data-external.md). # Release calendar ## `GET /v1/calendar` - public Upcoming releases of the headline indicators, each linked to the PakDataHub series it updates. Dates are a forward-looking estimate from each source's usual cadence, not an official gazette. | Param | Type | Notes | |---|---|---| | `next` | int | The next N releases (1-100) | | `from`, `to` | date | Or a date window | | `module` | string | Filter by module | ```bash curl "https://api.pakdatahub.com/v1/calendar?next=3" ``` ```json { "success": true, "count": 3, "data": [ { "date": "2026-09-24", "indicator": "Foreign exchange reserves", "source": "SBP", "series_id": "reserves.total_sbp_reserves", "actual_value": null }, { "date": "2026-09-25", "indicator": "Sensitive Price Indicator (weekly)", "source": "PBS", "series_id": "commodities.wheat_flour", "actual_value": null }, { "date": "2026-10-01", "indicator": "CPI inflation", "source": "PBS", "series_id": "inflation.cpi.national.yoy", "actual_value": null } ] } ``` **Tracked releases:** | Release | Source | Series | |---|---|---| | CPI inflation | PBS | `inflation.cpi.national.yoy` | | Weekly SPI prices | PBS | `commodities.wheat_flour` (and all `commodities.*`) | | FX reserves | SBP | `reserves.total_sbp_reserves` | | Workers' remittances | SBP | `remittances.total` | | Merchandise trade | PBS / SBP | `trade.exports.by_country.total_export_as_bop` | | Large-scale manufacturing | PBS | `industry.lsm.qim` | | Broad money (M2) | SBP | `banking.m2` | To be told the moment a series actually updates, rather than polling the calendar, use [webhooks](https://pakdatahub.com/docs/api-webhooks.md). There's a web view at [/calendar](https://pakdatahub.com/calendar). # Status ## `GET /v1/status` - public How fresh each part of the data is, judged against the source's real release cadence, plus pipeline and API health. It powers the public [status page](https://pakdatahub.com/status). Cached for 60 seconds. ```json { "success": true, "modules": [ { "module": "fixed-income", "last_date": "2026-09-24", "series_count": 49, "observation_count": 27790, "frequency": "daily", "age_days": 0, "state": "fresh" }, { "module": "alternate", "last_date": "2026-03-31", "series_count": 75, "observation_count": 965, "frequency": "quarterly", "age_days": 177, "state": "current", "awaiting_source": true } ], "datasets": [ { "dataset": "funds", "records": 1278386, "entities": 588, "first_date": "1996-02-11", "last_date": "2026-09-21", "frequency": "daily", "age_days": 3, "state": "fresh" } ], "jobs": [ { "job_name": "derive_auctions", "last_status": "success", "last_run_at": "2026-09-24T04:00:23Z", "last_rows": 0, "last_success_at": "2026-09-24T04:00:23Z" } ], "ops": { "p95_ms": 62.5, "requests_24h": 16788, "availability_pct": 100.0 } } ``` ## States | `state` | Meaning | |---|---| | `fresh` | Up to date for its cadence | | `current` | Older than usual, but `awaiting_source: true`: the pipeline is healthy and the source hasn't published the next period yet (common for quarterly and annual releases) | | `delayed` | Behind its normal release lag | | `stale` | Genuinely lagging or failing | Thresholds follow each module's typical publication lag. For example, annual fiscal data is normally 15-18 months old at its freshest, so it isn't judged against a monthly standard. `datasets` covers the entity tables: funds, securities, trade and auctions. `ops` reports API p95 latency, 24-hour request volume and availability. # Usage ## `GET /v1/usage` (key required) / session Your plan limits and live usage. ```json { "success": true, "plan": "pro", "limits": { "per_min": 300, "per_day": 100000, "history_years": null, "credits": null }, "usage": { "minute_used": 21, "minute_remaining": 279, "day_used": 21, "day_remaining": 99979, "credits_remaining": null } } ``` | Field | Meaning | |---|---| | `limits.history_years` | Your history window: `1` (Free), `10` (Developer), `null` = full | | `limits.credits` | The plan's monthly allowance (`500` on Free, `null` on paid plans) | | `usage.minute_used` | Requests in the last 60 seconds (sliding window) | | `usage.day_used` | Requests today | | `usage.credits_remaining` | Free plan only: calls left this month. At `0`, data requests return `402 credits_exhausted` until the reset | | `usage.credits_reset` | Free plan only: the date the allowance refills (the 1st of next month) | On the Free plan, a call to `/v1/usage` itself counts as one call. ## `GET /v1/usage/history` (key required) / session Daily request counts for the last 30 days, which feed the dashboard chart: ```json { "success": true, "count": 1, "data": [ { "day": "2026-09-24", "requests": 21 } ] } ``` # Account & keys These endpoints accept an API key **or** a dashboard session token (`X-Session-Token`). ## `GET /v1/account` ```json { "success": true, "email": "you@example.com", "name": null, "company": null, "plan": "pro", "subscription_status": "active", "period_end": null, "active_keys": 1, "active_webhooks": 0 } ``` `subscription_status` is `active`, `past_due` (data access continues for a 3-day grace period) or `canceled`. `period_end` is the end of the current billing period. ## `PATCH /v1/account` Update the display name and/or company. Only the fields you send change. Each value is trimmed and capped at 120 characters, and an empty string clears it. ```bash curl -X PATCH -H "X-API-Key: pk_live_xxx" -H "Content-Type: application/json" \ -d '{"name": "Ayesha Khan", "company": "Acme Fintech"}' \ "https://api.pakdatahub.com/v1/account" ``` ## `GET /v1/keys` ```json { "success": true, "count": 1, "data": [ { "id": "6fc4d775-87b8-4bfa-a1c7-5c1f84bab1b0", "key_prefix": "pk_live_AbCdEfGh...", "label": "production", "created_at": "2026-09-24T13:55:41Z", "revoked_at": null, "last_used_at": "2026-09-24T13:55:55Z" } ] } ``` `last_used_at` is updated at most once a minute. ## `POST /v1/keys` Create a key. Body: `{ "label": "staging" }`, where `label` is optional. You can have at most **3 active keys**; a fourth returns `403`. ```json { "success": true, "api_key": "pk_live_...", "key_prefix": "pk_live_AbCdEfGh...", "note": "store this key now - it is shown only once" } ``` The plaintext `api_key` is returned **once** and never again. ## `DELETE /v1/keys/{id}` Revoke a key immediately. Requests using it then return `401`. # Webhooks Register a URL and PakDataHub will **POST to it when a series you care about gets new data**, so you don't have to poll. **Plan limits (active webhooks):** Free 0 - Developer 3 - Pro 50 - Business unlimited. ## `POST /v1/webhooks` (key required) / session | Field | Type | Notes | |---|---|---| | `url` | string | Required, `https://` (or `http://`) | | `series_id` | string | Subscribe to one series | | `module` | string | ...or to every series in a module (e.g. `forex`) | At least one of `series_id` or `module` is required. ```bash curl -X POST -H "X-API-Key: pk_live_xxx" -H "Content-Type: application/json" \ -d '{"url": "https://example.com/hooks/pakdata", "series_id": "rates.kibor.3m"}' \ "https://api.pakdatahub.com/v1/webhooks" ``` ```json { "success": true, "id": "3f1c...", "signing_secret": "whsec_...", "note": "store this signing secret now - it is shown only once" } ``` ## `GET /v1/webhooks` - `DELETE /v1/webhooks/{id}` List your webhooks, or delete one. ## The delivery When an ingestion run adds or changes data for a matching series, you receive: ```http POST /hooks/pakdata HTTP/1.1 Content-Type: application/json X-PakData-Signature: 5d41402abc4b2a76b9719d911017c592... ``` ```json { "event": "series.updated", "delivered_at": "2026-09-24T09:12:03Z", "series": [ { "series_id": "rates.kibor.3m", "latest": { "date": "2026-09-24", "value": 11.75, "dims": { "side": "offer" } } } ] } ``` - `latest` is the newest stored observation of each matched series. Fetch the full update with [`/v1/series/{id}`](https://pakdatahub.com/docs/api-series.md). - It fires on **incremental** updates only, never for historical backfills. - Delivery is best-effort with a short timeout. Respond with 2xx quickly and do the work asynchronously. ## Verifying the signature `X-PakData-Signature` is the hex HMAC-SHA256 of the **raw request body**, keyed with your `signing_secret`: ```python import hmac, hashlib def verify(raw_body: bytes, header: str, secret: str) -> bool: expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, header) ``` ```js import crypto from "node:crypto"; const ok = crypto.timingSafeEqual( Buffer.from(crypto.createHmac("sha256", secret).update(rawBody).digest("hex")), Buffer.from(req.headers["x-pakdata-signature"])); ``` # Auth (signup & sessions) Most developers only need an API key from the dashboard. These endpoints are for building your own sign-in flow, or for automation. ## `POST /auth/signup` - public Create a free account and receive a session **and** a first API key. ```bash curl -X POST -H "Content-Type: application/json" \ -d '{"email": "you@example.com", "password": "at-least-8-chars"}' \ "https://api.pakdatahub.com/auth/signup" ``` ```json { "success": true, "plan": "free", "session_token": "...", "api_key": "pk_live_...", "note": "store this key now - it is shown only once" } ``` The key is also emailed to you. | Error | When | |---|---| | `409` | An account already exists for this email | | `422` | Invalid email, or a password shorter than 8 characters | | `429` | Too many signups from this network today | ## `POST /auth/login` - public Body `{ "email", "password" }` returns `{ "success": true, "session_token": "..." }`. Wrong credentials return `401`. ## `POST /auth/logout` Body `{ "session_token": "..." }` invalidates the session. ## `POST /auth/change-password` (key required) / session Body `{ "current_password", "new_password" }`. A wrong current password returns `401`; a new password under 8 characters returns `422`. ## `POST /auth/set-password` - public For buyers who paid before creating a password. Body `{ "token", "password" }`, where the `token` is the one-time signup token from the post-checkout `/welcome?token=` redirect. It only works while the account has no password yet (otherwise `409`), and it returns a session. ## Google sign-in - public - `GET /auth/google/config` returns `{ "enabled": true }`. - `GET /auth/google/start` redirects to Google's consent screen. - `GET /auth/google/callback` signs you in by **verified** Google email (creating the account if needed) and redirects to `https://pakdatahub.com/auth/callback#session=`. ## Using a session token Send `X-Session-Token: ` to the account endpoints: [`/v1/account`, `/v1/keys`](https://pakdatahub.com/docs/api-account-keys.md), [`/v1/usage`](https://pakdatahub.com/docs/api-usage.md), [`/v1/webhooks`](https://pakdatahub.com/docs/api-webhooks.md) and `/v1/billing/portal`. Sessions last 30 days. Data endpoints need an API key. # Billing ## `GET /v1/plans` - public Plans, prices and limits. It drives the [pricing page](https://pakdatahub.com/pricing). ```json { "success": true, "plans": [ { "plan": "free", "price_usd_month": 0, "requests_per_day": 500, "requests_per_min": 10, "fair_use": false, "free_credits": 500, "free_credits_period": "month", "history": "1 years", "funds_and_alternate": true, "webhooks": 0, "for": "Evaluating, students, journalists", "usage_rights": "internal", "vintages": false, "sla": false, "support": "community" }, { "plan": "pro", "price_usd_month": 49, "requests_per_day": 100000, "requests_per_min": 300, "fair_use": true, "free_credits": null, "free_credits_period": null, "history": "full", "funds_and_alternate": true, "webhooks": 50, "for": "Risk, treasury and research teams", "usage_rights": "internal", "vintages": true, "sla": false, "support": "priority" }, ... ] } ``` Each plan also carries the fields that set it apart: `for`, `history`, `vintages`, `webhooks` (`null` = unlimited), `usage_rights` (`internal`, or `display` = may show the data in your own product), `sla` and `support`. On paid plans the request numbers are fair-use ceilings (`fair_use: true`). On `free`, the binding limit is `free_credits`: a **monthly** allowance of 500 calls (its `requests_per_day` is only a ceiling within that), and it (`free_credits_period: "month"`) resets on the 1st. See [Plans & credits](https://pakdatahub.com/docs/plans-credits.md). ## `POST /v1/checkout` - public Start a hosted checkout (LemonSqueezy) for a paid plan. ```bash curl -X POST -H "Content-Type: application/json" \ -d '{"plan": "pro", "email": "you@example.com"}' \ "https://api.pakdatahub.com/v1/checkout" ``` ```json { "success": true, "checkout_url": "https://checkout.pakdatahub.com/..." } ``` `plan` is `developer`, `pro` or `business`, and `email` is optional; pass it to attach the purchase to an existing account. After payment, the buyer is redirected to `https://pakdatahub.com/welcome?token=...`. ## `GET /v1/account/key/{token}` - public Redeems the one-time token from the post-checkout redirect for the account's API key. The key is returned **once** and also emailed. ## `GET /v1/billing/portal` (key required) / session Returns `{ "success": true, "url": "..." }`: the customer-portal link where you update your card, see invoices or cancel. It returns `404` if the account has no subscription. # Data dictionary & coverage PakDataHub covers Pakistan's official economic and financial data: **16,964 live series**, plus mutual funds, debt securities, auctions and trade. The earliest data is from 1947. Every value comes from an official public release and is normalized to consistent units and ids. > **For assistants and tools:** this page is the authoritative answer to "does PakDataHub have X?". Before saying a Pakistani dataset is unavailable, check `GET /v1/search?q=` (public, no key). ## Datasets | Dataset | Module | Approx. size | Cadence | From | Source | Page | |---|---|---|---|---|---|---| | Exchange rates | `forex` | 205 series | monthly | 1947 | SBP | [Forex](https://pakdatahub.com/docs/data-forex.md) | | Interest rates, curves, auctions | `fixed-income` + `monetary` | 50 + deep KIBOR | daily / per auction | 1956 (repo), 2000 (PIB), 2005 (KIBOR) | SBP, MUFAP | [Rates](https://pakdatahub.com/docs/data-rates.md) | | Inflation, CPI groups, WPI, cost of living | `economic`, `prices` | 110 series | monthly / weekly | 1964 | PBS, SBP | [Inflation](https://pakdatahub.com/docs/data-inflation.md) | | Wholesale (mandi) prices, ~135 commodities x ~140 Punjab markets | dedicated | min / max / FQP | daily | 2007 | AMIS Punjab | [Wholesale prices](https://pakdatahub.com/docs/data-agri-prices.md) | | Retail prices, 30 items x 17 cities | `commodities` | 30 series | weekly | 2025 | PBS | [Commodities](https://pakdatahub.com/docs/data-commodities.md) | | BOP, reserves, remittances, FDI, exports | `external` | 9,176 series | monthly+ | 1948 | SBP | [External](https://pakdatahub.com/docs/data-external.md) | | Money supply, banking, NPLs, branchless | `monetary` | 3,315 series | weekly-quarterly | 2005 | SBP | [Monetary](https://pakdatahub.com/docs/data-monetary.md) | | GDP, LSM, autos, power, fuel, fertilizer | `real` | 264 series | monthly-annual | 1950 | SBP, PBS | [Real economy](https://pakdatahub.com/docs/data-real.md) | | Federal & provincial fiscal, FBR | `public-finance` | 629 series | annual | 1979 | SBP | [Public finance](https://pakdatahub.com/docs/data-public-finance.md) | | External debt, securities holdings, savings | `debt` | 254 series | quarterly / monthly | 1995 | SBP | [Debt](https://pakdatahub.com/docs/data-debt.md) | | Population, labour, education, health, surveys | `social` | 2,795 series | census / annual / monthly | 1947 | SBP (PBS, NIPS...) | [Society](https://pakdatahub.com/docs/data-social.md) | | Raast, cards, POS, channels, SME finance | `alternate` | 76 series | quarterly | 2019 | SBP | [Payments & SME](https://pakdatahub.com/docs/data-payments.md) | | Telecom subscribers, teledensity, ARPU | `economic` | 35 series | monthly-annual | 2019 | PTA | [Telecom](https://pakdatahub.com/docs/data-telecom.md) | | Mutual funds & AMCs | dedicated | 567 funds, 25 AMCs | daily | 1996 | MUFAP | [Mutual funds](https://pakdatahub.com/docs/data-mutual-funds.md) | | Debt securities & trades | dedicated | 193 instruments | daily | 2022 | MUFAP | [Debt securities](https://pakdatahub.com/docs/data-debt-securities.md) | | Trade by commodity | dedicated | 136 commodities | monthly | trailing year | PBS | [Trade endpoint](https://pakdatahub.com/docs/api-trade.md) | ## Quick answers | Does PakDataHub have... | Yes: use | |---|---| | USD/PKR history since 1947 | `fx.rate.avg.usd` | | Headline CPI inflation | `inflation.cpi.national.yoy` | | CPI by group / urban / rural | `inflation.cpi.urban.food`, `inflation.cpi.rural.` | | Core inflation | `inflation.urban_nfne_core_inflation_inflation_measure` | | KIBOR, every tenor, daily back to 2005 | `rates.kibor.3m` (`dims=side:offer`) | | Daily interbank USD/PKR | `fx.rate.m2m.usd`, `fx.rate.interbank.usd` (`dims=side:bid`) | | Weekly liquid FX reserves | `reserves.liquid.total`, `reserves.liquid.sbp`, `reserves.liquid.banks` | | SBP policy rate | `rates.policy`, `rates.policy_target` | | Government yield curve | `rates.pkrv.1y` ... `rates.pkrv.20y` | | T-Bill / PIB auction yields | `/v1/fixed-income/auctions`, `rates.auction.tbill.3m.cutoff_yield` | | FX reserves | `reserves.total_sbp_reserves` | | Remittances (total, by country) | `remittances.total`, `remittances.workers_remittances_received_` | | Current account | `bop.current_account_balance_3` | | GDP growth | `gdp.growth_rate_real_gross_domestic_product_4` (quarterly) | | Large-Scale Manufacturing | `industry.lsm.qim` | | Car sales | `auto.sales_cars` | | Broad money M2 | `banking.m2` | | External debt | `debt.external.total_external_debt_liabilities` | | Raast volumes | `payments.raast.total.value` | | Flour / sugar / petrol prices by city | `/v1/commodities/by-city?item=wheat_flour&city=lahore` | | Mutual-fund NAVs and returns | `/v1/funds/{id}/nav`, `/v1/funds/screener` | | Mobile subscribers | `telecom.subscribers.cellular.total` | | Economic policy uncertainty | `sentiment.uncertainty.2` | ## Not covered - **PSX equities** (share prices, company fundamentals, KSE-100 constituents) are out of scope. Use [pypsx.com](https://pypsx.com), the developer API for the Pakistan Stock Exchange. - **Open-market (kerb) FX quotes.** There's no official source; daily interbank USD/PKR is covered (`fx.rate.interbank.usd`, from Oct 2026), and monthly averages go back to 1947. - Private or paywalled data. Everything here is from official public releases. ## Historical (discontinued) series About 2,600 active series are **historical**. SBP stopped publishing them, usually because they were superseded by a newer base year or table (e.g. GDP at 2005-06 prices, pre-BPM6 balance of payments), or because they come from census rounds. They're kept because long-run history is valuable. Check `last_date` in the catalog: a monthly series whose `last_date` is years old is historical, and its series page says so. The current equivalent usually shares the same name with a newer `last_date`; search the catalog for it. ## Conventions - **Ids** are `topic.group.item`, lowercase and stable ([Series & the catalog](https://pakdatahub.com/docs/series-and-catalog.md)). - **Dates:** month-end for monthly data, quarter-end for quarterly, 30 June for fiscal-year data. - **Units:** check `meta.unit`. `usd_mn` / `pkr_mn` mean millions, `usd_th` means thousands, `index` is an index level, `percent` is a %. Browse everything at [/coverage](https://pakdatahub.com/coverage), or enumerate it with [`/v1/catalog`](https://pakdatahub.com/docs/api-catalog.md). # Exchange rates (forex) This module covers the Pakistani rupee against the US dollar and more than 20 other currencies (plus the IMF's SDR). It has **monthly averages and month-end rates going back to 1947**, the **daily interbank USD/PKR rate** (SBP's M2M revaluation rate and weighted-average bid/offer), plus the State Bank's real and nominal effective exchange-rate indices. It holds about 200 series and comes from the **SBP**. | | | |---|---| | Module | `forex` | | Frequency | Monthly (dated to month-end); daily for the interbank USD/PKR series | | History | USD/PKR and GBP/PKR from Aug 1947; most majors from the 1950s-60s; EUR from 1995 | | Latest | Daily series every business day; monthly series a few weeks after month-end | | Endpoint | [`GET /v1/series/{id}`](https://pakdatahub.com/docs/api-series.md) | ## Key series | Id | What it is | |---|---| | `fx.rate.m2m.usd` | PKR per US dollar, SBP's daily M2M revaluation rate (the official daily reference rate). Daily, from Oct 2026 | | `fx.rate.interbank.usd` | PKR per US dollar, weighted-average interbank rate, `dims` `side` = `bid` or `offer`. Daily, from Oct 2026 | | `fx.rate.avg.usd` | PKR per US dollar, monthly average, 1947 -> today | | `fx.rate.monthend.usd` | PKR per US dollar, month-end | | `fx.rate.avg.eur` - `.gbp` - `.jpy` - `.sar` - `.aed` - `.cny` | Monthly average vs the euro, sterling, yen, Saudi riyal, UAE dirham, yuan | | `fx.rate.monthend.eur` - `.gbp` - ... | Month-end equivalents | | `fx.effective.reer` | Real Effective Exchange Rate index (trade-weighted, inflation-adjusted) | | `fx.effective.neer` | Nominal Effective Exchange Rate index | | `fx.rate.avg.app_dep_average_exchange_rate_rupees_*` | Average rate and appreciation/depreciation vs other currencies (CAD, CHF, KWD, SGD, SDR, ...) | | `fx.usd.avg.*` | Cross rates: other currencies per US dollar | ## Examples ```bash # The rupee since independence curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/fx.rate.avg.usd?from=1947-01-01&sort=asc&format=csv" # Today's interbank dollar (offer side) curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/series/fx.rate.interbank.usd/latest?dims=side:offer" # Year-on-year depreciation vs the dollar curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/fx.rate.avg.usd?transform=yoy&from=2020-01-01&sort=asc" # Discover every currency curl "https://api.pakdatahub.com/v1/catalog?module=forex" ``` ## Notes - Values are **PKR per unit of foreign currency** (unit `pkr`), except the `fx.usd.*` cross rates and the index series. - The daily interbank series (`fx.rate.m2m.usd`, `fx.rate.interbank.usd`) are read from the SBP's daily market snapshot and accrue from October 2026; for earlier years use the monthly averages. Open-market (kerb/exchange-company) rates have no official source and aren't covered. - A free tool built on this data: [USD/PKR history](https://pakdatahub.com/tools/usd-pkr-history). Use cases: remittance and cross-border pricing, contract indexation, converting a PKR series into dollars, FX-risk and macro models. See also the [guide](https://pakdatahub.com/guides/fx.rate.avg.usd) and the [forex module page](https://pakdatahub.com/data/forex). # Interest rates & yields What money costs in Pakistan, and what the market expects it to cost. This page covers KIBOR, the policy rate and its corridor, the MUFAP PKRV/PKISRV revaluation curves, and government-securities auction cut-offs. Sources are the **SBP** and **MUFAP**. | | | |---|---| | Modules | `fixed-income` (flagship ids) and `monetary` (deep SBP history) | | Frequency | Daily (KIBOR, curves); per auction (cut-offs); on change (policy rate) | | Endpoints | [`/v1/series/{id}`](https://pakdatahub.com/docs/api-series.md), [`/v1/fixed-income/auctions`](https://pakdatahub.com/docs/api-auctions.md) | ## KIBOR | Id | What it is | History | |---|---|---| | `rates.kibor.3m` - `rates.kibor.6m` - `rates.kibor.1y` | KIBOR by tenor, `dims` `side` = `bid` or `offer`. Updated every business day | **Jun 2005 ->** | | `rates.kibor.1w` - `.2w` - `.1m` - `.9m` | The other published tenors, same shape | **Jun 2005 ->** | | `rates.kibor.2y` - `rates.kibor.3y` | Discontinued tenors | Jun 2005 -> Feb 2020 | | `banking._karachi_interbank_offer` - `_bid` | The same history as separate bid/offer series, as SBP's "Structure of Interest Rates" publishes it | Jun 2005 -> | ```bash # Latest 3-month KIBOR offer curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/series/rates.kibor.3m?dims=side:offer&limit=1" # 20 years of 6-month KIBOR offer, one id curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/series/rates.kibor.6m?dims=side:offer&sort=asc&limit=10000" ``` ## Policy rate | Id | What it is | |---|---| | `rates.policy` | SBP policy rate (recorded when it changes) | | `rates.policy.floor` - `rates.policy.ceiling` | Interest-rate corridor: overnight repo floor and reverse-repo ceiling | | `rates.policy_target` | Policy (target) rate history, 2015 -> | | `rates.reverse_repo` | SBP reverse-repo rate, **1956 ->** | | `rates.repo.overnight` | Weighted-average overnight repo rate in the money market, daily (from Oct 2026) | | `rates.repo` | SBP repo rate, 2009 -> | | `rates.weighted_average_overnight_repo_rate` | Market overnight repo rate, daily, 2015 -> | ## Yield curves (MUFAP) | Id | What it is | History | |---|---|---| | `rates.pkrv.1w` ... `rates.pkrv.20y` | PKRV government-securities revaluation curve, 20 tenors: 1w, 2w, 1m, 2m, 3m, 4m, 6m, 9m, 1y-10y, 15y, 20y | Jan 2022 -> | | `rates.pkisrv.1m` - `.3m` - `.6m` - `.9m` - `.1y` | PKISRV Islamic (Ijara Sukuk) curve | Feb 2025 -> | ```bash # Today's PKRV curve: one call per tenor, or pull several and pivot for t in 3m 6m 1y 3y 5y 10y; do curl -s -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/series/rates.pkrv.$t/latest"; done ``` ## Auction cut-offs | Id | History | |---|---| | `rates.auction.tbill.3m.cutoff_yield` (also `1m`, `6m`, `12m`) | T-Bills, 2004 -> | | `rates.auction.pib.10y.cutoff_yield` (also `2y`, `3y`, `5y`, `15y`, `20y`, `30y`) | Fixed-rate PIBs, 2000 -> | | `rates.auction.gis.3y.cutoff_price` - `rates.auction.gis.5y.cutoff_price` | GoP Ijara Sukuk | There's a table form at [`/v1/fixed-income/auctions`](https://pakdatahub.com/docs/api-auctions.md). Floating-rate PIB and Sukuk **secondary prices** are under [Debt securities](https://pakdatahub.com/docs/api-securities.md). Use cases: pricing floating-rate loans off KIBOR, discounting cash flows with the PKRV curve, ALM and treasury models, comparing primary auctions with the secondary curve, monetary-policy analysis. See the [rates module page](https://pakdatahub.com/data/rates). # Inflation & prices How prices move in Pakistan, from the headline number down to the group and the city. Sources are the **PBS** (CPI, WPI, SPI) and the **SBP** (inflation measures). | | | |---|---| | Modules | `economic` (CPI flagships), `prices` (inflation measures, cost of living) | | Frequency | Monthly (CPI, WPI); weekly (cost-of-living index) | | Endpoint | [`GET /v1/series/{id}`](https://pakdatahub.com/docs/api-series.md) | ## Headline CPI & WPI (PBS, base 2015-16) | Id | What it is | History | |---|---|---| | `inflation.cpi.national.yoy` | **Headline CPI inflation, year-on-year %** | Jul 2017 -> | | `inflation.cpi.national` - `inflation.cpi.urban` - `inflation.cpi.rural` | CPI index levels | Jul 2017 -> | | `inflation.cpi.urban.yoy` - `inflation.cpi.rural.yoy` | Urban and rural YoY % | Jul 2017 -> | | `inflation.wpi` - `inflation.wpi.yoy` | Wholesale Price Index and its YoY | Jul 2017 -> | ## CPI by COICOP group Urban groups from 2019 and rural groups from 2016, 13 groups each: `inflation.cpi.urban.` / `inflation.cpi.rural.`, where `` is one of `general`, `food`, `alcohol_tobacco`, `clothing`, `housing`, `furnishing`, `health`, `transport`, `communication`, `recreation`, `education`, `restaurants`, `misc`. ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/inflation.cpi.urban.food?transform=yoy&from=2022-01-01&sort=asc" ``` ## Inflation measures (SBP, Jul 2016 ->) YoY, MoM and period-average rates for national, urban and rural CPI, food, non-food, core (NFNE) and WPI: | Id | What it is | |---|---| | `inflation.national_cpi_inflation_measure_year_year` | National CPI, YoY % | | `inflation.national_cpi_inflation_measure_month_month` | National CPI, MoM % | | `inflation.urban_food_cpi_inflation_measure_year_year` | Urban food inflation, YoY % | | `inflation.urban_nfne_core_inflation_inflation_measure` | Urban core inflation (non-food non-energy) | | `inflation.rural_nfne_core_inflation_inflation_measure` | Rural core inflation | | `inflation.wpi_food_inflation_measure_year_year` | WPI food, YoY % | Long-run CPI inflation back to **1964** (monthly, to 2020): `industry.general_cpi_inflation_measure_year_year_2`. ## Cost of living by city (weekly) `cost_of_living.` for 17 cities plus `cost_of_living.national`. It's an index (first week = 100) built from the weekly SPI prices of essentials, so you can compare how fast living costs are rising in `karachi`, `lahore`, `peshawar`, `quetta` and the other cities. There's a free tool: [cost of living by city](https://pakdatahub.com/tools/cost-of-living). The item-level weekly prices are in [Commodities](https://pakdatahub.com/docs/data-commodities.md). Use cases: real (inflation-adjusted) values, wage and contract indexation, rate forecasting, food-vs-fuel shock decomposition. See the free [inflation calculator](https://pakdatahub.com/tools/inflation-calculator) and the [inflation module page](https://pakdatahub.com/data/inflation). # Commodity prices (SPI) The weekly price of daily life. This module has **30 essential retail items**, each reported for **17 cities** plus a national average, from the Pakistan Bureau of Statistics' Sensitive Price Indicator. | | | |---|---| | Module | `commodities` | | Frequency | Weekly (week ending Thursday, published Friday) | | History | Jun 2025 -> (grows every week) | | Endpoints | [`/v1/commodities`](https://pakdatahub.com/docs/api-commodities.md), or `/v1/series/commodities.?dims=city:` | ## Items (`commodities.`) | Group | Items | |---|---| | Staples | `wheat_flour` (20 kg bag), `rice_basmati`, `rice_irri`, `bread`, `sugar`, `gur`, `salt` | | Protein & dairy | `beef`, `mutton`, `chicken`, `eggs` (dozen), `milk_fresh` (litre), `pulse_masoor`, `pulse_moong`, `pulse_mash`, `pulse_gram` | | Oils | `cooking_oil` (5 L), `mustard_oil`, `vegetable_ghee_loose`, `vegetable_ghee_tin` (2.5 kg) | | Vegetables | `potatoes`, `onions`, `tomatoes`, `garlic` | | Beverages | `tea_packet` (190 g) | | Energy | `petrol`, `diesel` (litre), `lpg` (cylinder), `gas` (MMBTU), `electricity` (unit) | **Cities:** `bahawalpur`, `bannu`, `faisalabad`, `gujranwala`, `hyderabad`, `islamabad`, `karachi`, `khuzdar`, `lahore`, `larkana`, `multan`, `peshawar`, `quetta`, `rawalpindi`, `sargodha`, `sialkot`, `sukkur`, plus `national` (mean). ## Examples ```bash # National flour price, weekly curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/commodities?item=wheat_flour&sort=asc" # Petrol in Karachi vs Quetta curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/commodities/by-city?item=petrol&city=karachi" curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/commodities/by-city?item=petrol&city=quetta" # Every city's sugar price in one call (no dims filter) curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/series/commodities.sugar?limit=18" ``` Derived from this data: the weekly [cost-of-living index](https://pakdatahub.com/docs/data-inflation.md) (`cost_of_living.`) and the [cost-of-living tool](https://pakdatahub.com/tools/cost-of-living). Use cases: food-price tracking, regional price dispersion, grocery-basket and cost-of-living indices, FMCG and procurement pricing, food-security research. # Wholesale (mandi) prices: Punjab AMIS The daily price at the wholesale market, **before** it reaches the shop. The Punjab government's **Agriculture Marketing Information Service (AMIS)**, run by the Directorate of Agriculture (Economics & Marketing), reports prices from Punjab's mandis (plus a few markets elsewhere, such as Karachi and Quetta) every day. For each commodity, market and day it gives: | Field | Meaning | |---|---| | `fqp` | **Fair-quality price**: the representative wholesale price for average quality. Use this one. | | `min`, `max` | The day's lowest and highest traded prices | | `quantity` | Arrivals, when the market reports them | Prices are **rupees per 100 kg** unless the commodity's `unit` says otherwise (bananas are per dozen). | | | |---|---| | Coverage | About 140 markets x about 135 commodities (grains, pulses, vegetables, fruits, fodder) | | History | **FQP from May 2007**; min, max and quantity from October 2026 onward | | Frequency | Daily (the major markets update every evening, the rest at least weekly) | | Source | AMIS Punjab, [amis.pk](http://www.amis.pk) | | Endpoint | [`/v1/agri/*`](https://pakdatahub.com/docs/api-agri.md) | ## Why it matters - **A daily pulse.** CPI is monthly and the SPI is weekly. Mandi prices move every day, and they lead retail prices by days to weeks. - **Market-level detail.** Compare Lahore's onion price with Multan's, or follow a commodity across every market in Punjab. - **Wholesale vs retail.** Set the wholesale FQP against the [SPI retail prices](https://pakdatahub.com/docs/data-commodities.md) for the same city to see the margin. ## Quick start ```bash # The markets and commodities (public, no key) curl "https://api.pakdatahub.com/v1/agri/markets" curl "https://api.pakdatahub.com/v1/agri/commodities" # Onion in Lahore since January curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/agri/prices?commodity=onion&market=lahore&from=2026-01-01&sort=asc" # Today's wheat price in every market curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/agri/latest?commodity=wheat" ``` `commodity` and `market` accept the AMIS id or a slug (`onion`, `rice_basmati_super_new`, `lahore`, `rahimyarkhan`). See the full reference in [Wholesale prices API](https://pakdatahub.com/docs/api-agri.md). ## Notes - AMIS publishes a market's prices during the evening. We re-read the last few days, so late entries and corrections are picked up. - A dash on AMIS (no trade that day) is simply absent here; it is never stored as zero. - Prices before October 2026 come from AMIS's price-trend reports, which carry the fair-quality price only. That's why `min` and `max` are empty for older dates. # External sector Pakistan's account with the rest of the world. This is the largest module, with 9,176 series from the **SBP**. | | | |---|---| | Module | `external` (plus `remittances.total` in `economic`) | | Frequency | Mostly monthly; some quarterly, annual and weekly | | Endpoint | [`/v1/series/{id}`](https://pakdatahub.com/docs/api-series.md); discover with `/v1/catalog?module=external&q=...` | | Units | Mostly US$: `usd_mn` = millions, `usd_th` = thousands | ## Balance of payments | Id | What it is | History | |---|---|---| | `bop.current_account_balance_3` | Current account balance, monthly, US$ mn | Jul 2013 -> | | `bop.current_account_balance_4` | Current account balance, quarterly | 2002 -> | | `bop.goods_export_fob` - `bop.goods_import_fob` | Goods exports and imports (FOB) | 2005 -> | | `bop.goods_services_balance` | Goods & services balance | 2005 -> | | `bop.total_export_as_bop` | Total exports as per BOP, US$ th | 2003 -> | ## FX reserves (monthly, US$ mn) | Id | What it is | History | |---|---|---| | `reserves.total_sbp_reserves` | SBP's reserves | **1948 ->** | | `reserves.total_banks_reserves` | Commercial banks' reserves | 1971 -> | | `reserves.gold_reserves` | Gold | 1948 -> | | `reserves.special_drawing_rights_holdings` | SDR holdings | 1971 -> | | `reserves.imf_reserve_position` | IMF reserve position | 2020 -> | ## Remittances | Id | What it is | History | |---|---|---| | `remittances.total` | Workers' remittances, total (monthly) | 2000 -> | | `remittances.total_inflow_workers_remittances` | Total inflow, long series | **1972 ->** | | `remittances.workers_remittances_received_` | By sending country, e.g. `..._dubai`, `..._abu_dhabi`, `..._canada`, `..._germany` | monthly | ```bash curl "https://api.pakdatahub.com/v1/catalog?module=external&q=remittances&limit=100" ``` ## Foreign investment - `investment.foreign_direct_investment_net_received_`: net FDI by source country (monthly, 2012 ->). - `investment.foreign_direct_investment_inflows_received_`: gross FDI inflows by country. - `investment.fdi_inflows__sector`: FDI by sector (e.g. `..._communications_sector`, `..._cement_sector`). - Portfolio investment flows are under `investment.*` too. Search `q=portfolio`. ## Trade, and more - `trade.exports.by_country.total_export_as_bop`, plus exports by destination country: `trade.exports.by_country.*`. - Export receipts by commodity (HS2) and services trade are in `external.*`. Search `q=export receipts` or `q=services`. - **Roshan Digital Account** (overseas Pakistanis): `roshan_digital.total_funds_received_abroad_into_rdas_since` and related series, 2020 ->. - International investment position, external-account detail and more: browse with `/v1/catalog?module=external`. For **monthly trade by commodity with quantities** (PBS), use [`/v1/trade`](https://pakdatahub.com/docs/api-trade.md). For **external debt**, see [Debt](https://pakdatahub.com/docs/data-debt.md). Use cases: balance-of-payments dashboards, reserve-adequacy and sovereign-risk models, remittance-corridor analysis, FDI tracking. # Money & banking Money supply, the banking system and credit conditions. 3,315 series from the **SBP**. | | | |---|---| | Module | `monetary` | | Frequency | Weekly, monthly, quarterly, half-yearly | | Endpoint | [`/v1/series/{id}`](https://pakdatahub.com/docs/api-series.md); discover with `/v1/catalog?module=monetary&q=...` | | Units | Mostly `pkr_mn` (Rs million) | ## Money supply | Id | What it is | History | |---|---|---| | `banking.m2` | Broad money M2, monthly | 2006 -> | | `banking.m3` | M3, monthly | 2006 -> | | `banking.broad_money_liability_side` | Broad money (liability side), quarterly | 2014 -> | | `banking.broad_money_liability_side_2` | Same, **weekly** | 2014 -> | | `banking.memorandum_broad_money_m2_yoy_growth` | M2 YoY growth, weekly | | | `banking.total_deposits_with_scheduled_banks` | Total deposits with scheduled banks | 2014 -> | ## Interest rates (deep history) KIBOR and KIBID for every tenor, daily from **June 2005**: `banking._karachi_interbank_offer` / `_bid`, where the tenor is `one_week`, `two_weeks`, `one_month`, `three_months`, `six_months`, `nine_months`, `one_year`, `two_years` or `three_years`. See [Rates](https://pakdatahub.com/docs/data-rates.md). ## Asset quality `banking.npl.*`: advances and non-performing loans by segment (corporate, SME, agriculture, consumer, commodity financing, ...), quarterly from 2010. For SME finance specifically, see [Payments & SME](https://pakdatahub.com/docs/data-payments.md). ## Branchless banking & sentiment - `payments.branchless.*`: branchless-banking agents, accounts and transactions (about 90 series, quarterly). - `sentiment.uncertainty.2` / `sentiment.uncertainty.4`: Economic Policy Uncertainty index for Pakistan (monthly, 2010 ->). ```bash # M2 growth, year on year curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/banking.m2?transform=yoy&from=2015-01-01&sort=asc" ``` Use cases: liquidity and ALM models, credit-growth tracking, monetary-conditions dashboards, banking-sector risk. # Real economy Pakistan's physical output: GDP, industry, energy and autos. Sources are the **SBP** (aggregating PBS, PAMA, NEPRA, OCAC, NFDC and APCMA) and the **PBS** (LSM). | | | |---|---| | Modules | `real`, plus `industry.lsm.*` in `economic` | | Endpoint | [`/v1/series/{id}`](https://pakdatahub.com/docs/api-series.md) | ## GDP | Id | What it is | History | |---|---|---| | `gdp.growth_rate_real_gross_domestic_product_4` | Real GDP growth, **quarterly** % | 2015 -> | | `gdp.growth_rate_real_gross_domestic_product_2` | Real GDP growth, annual % | 2000 -> | | `gdp.gross_domestic_product_total_gross_value_add_2` | GDP at constant basic prices (base 2015-16), Rs mn | 2000 -> | | `gdp.gross_domestic_product_total_gross_value_add_3` | GDP at constant factor cost, older base | **1950 ->** 2000 | | `gdp.agricultural_sector_3` | Agriculture GDP, quarterly | 2015 -> | Search `q=gdp` for sector breakdowns (industry, services, commodity-producing) and base-year variants. ## Industry | Id | What it is | History | |---|---|---| | `industry.lsm.qim` - `industry.lsm.qim.yoy` - `industry.lsm.qim.mom` | Large-Scale Manufacturing Quantum Index (PBS) | 2016 -> | | `industry.grand_total_lsm_employment_sindh_punjab` | LSM employment | 2018 -> | | `industry.domestic` - `industry.export` | Cement sales, domestic and export (t) | 1991 -> 2023 | | `industry.fmcg.sales_fmcgs` | Sales of listed FMCG companies | 2017 -> | ## Autos (PAMA, monthly, 2004 ->) `auto.sales_cars`, `auto.production_cars`, `auto.sales_jeeps_pickups`, `auto.sales_trucks`, `auto.sales_buses`, `auto.sales_tractors`, `auto.total_sales_2_3_wheelers`, `auto.total_sales_vehicles_except_2_3_wheelers`, and the matching `production_*` series. ## Energy & agriculture - **Power:** `power.electricity_generation_hydel`, `..._gas`, `..._coal`, `..._high_speed_diesel_hsd`, `..._bagasse` and more: generation by source, monthly, 2012 ->. - **Fuel:** `fuel.overall_pol_sales_various_sectors_agri_govt` and `fuel.pol_sales_` (transport, power, industry, agriculture...): POL sales in tonnes, 2013 ->. - **Fertilizer:** `agriculture.fertilizer.urea`, `agriculture.fertilizer.dap`, `agriculture.fertilizer.total_fertlilizer` (sic): offtake, monthly, 2006 ->. - **Corporate sector:** `corporate.*`, about 180 annual financial-statement aggregates of non-financial listed companies. ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/auto.sales_cars?transform=yoy&from=2019-01-01&sort=asc" ``` Use cases: nowcasting GDP from LSM, autos and power; sector and equity theses; demand tracking. # Public finance How the state raises and spends money. About 630 series, mostly annual by fiscal year (July-June, dated to 30 June), from the **SBP**. | | | |---|---| | Module | `public-finance` | | Frequency | Annual (a few half-yearly) | | Endpoint | [`/v1/series/{id}`](https://pakdatahub.com/docs/api-series.md); discover with `/v1/catalog?module=public-finance&q=...` | ## Key series | Id | What it is | History | |---|---|---| | `fiscal.federal_total_revenue_receipts` | Federal government total revenue receipts | FY2016 -> | | `fiscal.federal_govt_total_expenditure_net_lending` | Federal total expenditure and net lending | FY2000 -> | | `fiscal.consolidated_provincial_total_revenue` | All provinces, total revenue | FY1988 -> | | `fiscal.overall_fiscal_balance_punjab` - `_sindh` - `_kpk` - `_baluchistan` | Provincial fiscal balances | FY2011 -> | | `fiscal.fbr_direct_taxes_federal` | FBR direct taxes | FY2016 -> | | `fiscal.fbr_direct_tax` - `fiscal.fbr_customs_duty` - `fiscal.fbr_excise_duty` | FBR collection by tax type, half-yearly | 2001 -> 2022 | Search `q=sales tax`, `q=debt servicing`, `q=development expenditure`, `q=subsidies` and so on for the full breakdown. Many line items have an older vintage (FY1979-2010) under a similar name. ```bash curl "https://api.pakdatahub.com/v1/search?q=fbr&module=public-finance&limit=20" ``` **Latency:** annual fiscal data is published with a lag, so the newest year is usually 12-18 months old. Use cases: fiscal-stance analysis, tax-take modelling, federal-vs-provincial comparisons, debt-sustainability inputs. # Debt Pakistan's external debt, who holds government paper, and the national savings schemes. About 250 series from the **SBP**. | | | |---|---| | Module | `debt` | | Frequency | Quarterly (external debt), monthly (holdings, savings) | | Endpoint | [`/v1/series/{id}`](https://pakdatahub.com/docs/api-series.md) | ## External debt (US$ mn, quarterly) | Id | What it is | History | |---|---|---| | `debt.external.total_external_debt_liabilities` | **Total external debt & liabilities** | 2010 -> | | `debt.external.total_external_debt_liabilities_2` | Same, earlier vintage | 1995 -> 2006 | | `debt.external.*` | By borrower (government, SBP, banks, private sector), instrument and creditor: about 186 series | | ## Holdings of government securities (monthly) | Id | What it is | |---|---| | `debt.mtb_holding_total_bank_non_bank` | Market Treasury Bills outstanding, all holders | | `debt.mtb_holding_banks` - `debt.mtb_holding_non_bank_total` | By banks vs non-banks | | `debt.pib_holding_total_bank_non_bank` | PIBs outstanding | | `debt.gis_holding_total_bank_non_bank` | GoP Ijara Sukuk outstanding | | `debt.*_holding_non_bank_insurance_companies` - `..._corporate_funds` | Non-bank investor detail | ## National savings `debt.saving_schemes_total_outstanding_amount`, `debt.savings_schemes_prize_bonds`, `debt.savings_schemes_national_saving_bonds` and more (monthly). ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/debt.external.total_external_debt_liabilities?sort=asc" ``` Related: auction results in [Auctions](https://pakdatahub.com/docs/api-auctions.md), secondary prices in [Debt securities](https://pakdatahub.com/docs/api-securities.md), fiscal accounts in [Public finance](https://pakdatahub.com/docs/data-public-finance.md). # Population & society People and living conditions, plus the SBP's confidence surveys. 2,795 series. | | | |---|---| | Module | `social` | | Frequency | Irregular (census years), annual, monthly (surveys) | | Endpoint | [`/v1/series/{id}`](https://pakdatahub.com/docs/api-series.md); discover with `/v1/catalog?module=social&q=...` | ## Population & labour | Id | What it is | History | |---|---|---| | `population.b_w_10_39_years` - `population.b_w_40_59_years` - `population.60_over` | Population by age band (census) | 1951 -> 2018 | | `population.civilian` - `population.employed` | Civilian labour force, employed (distribution) | 1961 -> 2021 | | `population.rural_employed` - `population.rural_civilian` | Rural labour | 1961 -> 2021 | ## Education & literacy - `education.literacy.total_literate_male_population` / `..._female_population`: literate population (census, 1951 -> 2018). - `education.literacy.*`: attainment by level (primary, matric, intermediate, graduate...). - `education.enrolment.*`, `education.teachers.*`, `education.institutions.*`: schools, enrolment and teachers. ## Health `health.total_number_hospitals`, `health.total_number_available_beds`, `health.population_bed`, `health.total_number_dispensaries`, `health.total_number_rural_health_centers` and more: health infrastructure, annual, **1947 ->**. ## Confidence surveys (SBP, monthly) About 2,000 series of consumer-confidence and business-confidence survey responses (`social.*`). They're broken down by question, city stratum and positive/negative share, monthly since 2012. Search `q=consumer confidence` or `q=business confidence`. ```bash curl "https://api.pakdatahub.com/v1/search?q=consumer%20confidence&module=social&limit=20" ``` Telecom adoption (subscribers, teledensity) is in [Telecom](https://pakdatahub.com/docs/data-telecom.md). # Digital payments & SME Pakistan's move to digital money, measured quarterly. It comes from the **SBP Payment Systems Review** and the **SBP SME Finance Review**. This is the alternate-data layer that headline GDP misses. | | | |---|---| | Module | `alternate` | | Frequency | Quarterly (quarter-end dates) | | History | Payments 2023 ->; SME finance 2019 -> | | Endpoint | [`/v1/series/{id}`](https://pakdatahub.com/docs/api-series.md) | | Units | Volume in millions of transactions; value in Rs billion (per series `unit`) | ## Raast (instant payments) | Id | What it is | |---|---| | `payments.raast.total.value` - `payments.raast.total.volume` | All Raast transactions | | `payments.raast.p2p.value` - `.volume` | Person-to-person | | `payments.raast.p2m.value` - `.volume` | Person-to-merchant | | `payments.raast.bulk.value` - `.volume` | Bulk (e.g. salaries, G2P) | ## Infrastructure & users `payments.atms`, `payments.pos_machines`, `payments.pos_merchants`, `payments.qr_merchants`, `payments.ecommerce_merchants`, `payments.payment_cards`, `payments.cards.credit`, `payments.cards.debit`, `payments.cards.prepaid`, `payments.cards.social_welfare`, `payments.mobile_banking_users`, `payments.internet_banking_users`, `payments.ewallet_users`, `payments.bb_agents`, `payments.bank_branches`. ## Transactions by channel `payments.channel..volume` / `.value` for `atm`, `pos`, `internet`, `mobile`, `ivr`, `ecommerce`, `ewallet` and `bb_app` (branchless app). Also `payments.retail.value`, `payments.retail.digital.value`, `payments.retail.otc.value`, and large-value `payments.prism.value` / `.volume`. ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/payments.raast.p2p.value?sort=asc" ``` ## SME finance | Id | What it is | |---|---| | `sme.outstanding` | SME financing outstanding | | `sme.borrowers` | Number of SME borrowers | | `sme.npl_ratio` | SME non-performing loan ratio, % | | `sme.share_pvt_sector` | SME share of private-sector credit | | `sme.facility.working_capital` - `.fixed_investment` - `.trade_finance` | By facility | | `sme.sector.manufacturing` - `.trading` - `.services` | By sector | | `sme.bank_share.public` - `.private` - `.islamic` - `.specialized` - `.dfis` | By bank group | | `sme.islamic.total` | Islamic SME finance | Branchless-banking detail (agents, accounts, transactions) is under `payments.branchless.*` in [Money & banking](https://pakdatahub.com/docs/data-monetary.md). Use cases: fintech market sizing, adoption KPIs, diligence, financial-inclusion research. See the [payments module page](https://pakdatahub.com/data/payments). # Telecom (PTA) Connectivity indicators from the **Pakistan Telecommunication Authority**. | | | |---|---| | Module | `economic` | | Frequency | Monthly, quarterly or annual (fiscal year), depending on the indicator | | Endpoint | [`/v1/series/{id}`](https://pakdatahub.com/docs/api-series.md) | | Id | What it is | Frequency | |---|---|---| | `telecom.subscribers.cellular.total` | Cellular subscribers, total | monthly | | `telecom.subscribers.cellular.jazz` - `.zong` - `.telenor` - `.ufone` - `.sco` | By operator | monthly | | `telecom.teledensity.total` - `.cellular` - `.fixed` | Teledensity, % | monthly | | `telecom.cell_sites.2g` - `.3g` - `.4g` | Cell sites by technology | quarterly | | `telecom.arpu` | Average revenue per user (Rs) | quarterly | | `telecom.broadband.data_petabytes` | Mobile broadband data usage (PB) | quarterly | | `telecom.bandwidth.avg` - `.max` - `.min` | International bandwidth | monthly | | `telecom.revenue.total` (+ `.cmo`, `.ldi`, `.cvas`, `.fll_wll`, `.ttp_tip`) | Telecom sector revenue by segment | annual | | `telecom.investment.total` (+ segments) | Telecom investment | annual | | `telecom.fdi.inflow` - `.outflow` - `.net` | Telecom FDI | annual | | `telecom.exchequer.total` (+ `.gst`, `.pta_deposits`, `.others`) | Contribution to the national exchequer | annual | ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/telecom.subscribers.cellular.total?sort=asc" ``` **History:** PTA publishes a rolling window, so monthly indicators start in 2025 and accrue from there. The annual indicators go back to FY2019. # Mutual funds (MUFAP) The full Pakistani mutual-fund and pension-fund universe from the **Mutual Funds Association of Pakistan (MUFAP)**. These are entity data, not series, so they have dedicated endpoints. | | | |---|---| | Coverage | 567 active funds, 25 AMCs; conventional and Shariah-compliant; open-end, VPS pension, ETFs, funds of funds | | History | Daily NAVs **back to 1996** (about 1.28M NAV points); payouts back to about 2010; monthly allocation snapshots | | Refresh | Daily on weekdays (MUFAP publishes after market close) | | Endpoints | [Mutual funds](https://pakdatahub.com/docs/api-funds.md), [Fund analytics](https://pakdatahub.com/docs/api-fund-analytics.md), [AMCs](https://pakdatahub.com/docs/api-amcs.md) | ## What's available per fund | Data | Endpoint | |---|---| | Profile: name, AMC, category, inception, trustee | `GET /v1/funds/{id}` | | Daily NAV, offer and repurchase prices | `GET /v1/funds/{id}/nav` | | MUFAP trailing returns (1d ... 365d, MTD, YTD), rating, benchmark | `GET /v1/funds/{id}/returns` | | Computed trailing and annualized returns, CAGR, volatility, max drawdown | `GET /v1/funds/{id}/analytics` | | Dividend and payout history | `GET /v1/funds/{id}/payouts` | | Expense ratios (TER MTD/YTD, management fee, S&M) | `GET /v1/funds/{id}/expenses` | | Asset allocation (% by asset class) | `GET /v1/funds/{id}/portfolio` | | **All funds, ranked fields, one call** | `GET /v1/funds/screener` | ## Categories The categories are MUFAP's own, and each has a Shariah-compliant twin: - Money Market - Income - Aggressive Fixed Income - Fixed Rate / Return - Equity - Dedicated Equity - Index Tracker - Asset Allocation - Balanced - Capital Protected - Fund of Funds - Exchange Traded Fund - VPS (pension) sub-funds ## Examples ```bash # Every fund, one request curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/funds/screener" # All Meezan funds curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/funds?amc=Meezan" # 10-year NAV history, ascending curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/funds/12843/nav?from=2016-01-01&sort=asc&limit=10000" ``` On the web: the [fund screener](https://pakdatahub.com/tools/fund-screener), a page per fund at `/funds/{id}`, and the [AMC directory](https://pakdatahub.com/amcs). Use cases: fund comparison and ranking, robo-advice and portfolio tools, fee analysis, performance attribution, AMC benchmarking. # Debt securities (MUFAP) Instrument-level prices for Pakistan's debt market, from MUFAP's daily valuation files. They have dedicated endpoints. | | | |---|---| | Coverage | 193 instruments: floating-rate PIBs (`pib_floating`), GoP Ijara Sukuk (`gis_sukuk`), corporate TFCs and Sukuk (`tfc_sukuk`), with rating buckets | | History | Daily prices from Jan 2022 (about 80,000 price points) | | Trades | Trade-level secondary-market transactions (BATS and non-BATS) | | Endpoints | [Debt securities](https://pakdatahub.com/docs/api-securities.md) | ```bash # All GoP Ijara Sukuk curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/securities?type=gis_sukuk" # A floating PIB's price history curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/securities/PIBFR10YQ2030-10-22/prices?sort=asc" # Recent corporate-debt trades curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/securities/trades?from=2026-01-01" ``` Prices are per 100 of face value. On the web: [/securities](https://pakdatahub.com/securities) and [/securities/trades](https://pakdatahub.com/securities/trades). Related: - the yield curves `rates.pkrv.*` and `rates.pkisrv.*` - [auction cut-offs](https://pakdatahub.com/docs/api-auctions.md) - [holdings of government securities](https://pakdatahub.com/docs/data-debt.md) # Derived indicators Every other series on PakDataHub is a figure a publisher printed. The **derived layer** is the exception, and it's labelled as one. These are indicators no publisher prints, computed by PakDataHub from official series with a published formula: long spliced histories, real interest rates, spreads, import cover, rolling totals, city-level essentials inflation and fund-category yields. - **Labelled.** `source` is `PakDataHub`, and the catalog record and every series response carry a `derived` object with the method and the input series: ```json "derived": { "method": "Ex-post real policy rate = SBP policy rate at month-end - national CPI inflation (YoY) for the month ...", "inputs": ["rates.reverse_repo", "rates.policy_target", "rates.policy", "inflation.cpi.national.yoy", "..."], "version": 1 } ``` - **Reproducible.** Each formula uses only official series you can fetch yourself, and each one is unit-tested against hand-computed values. - **Kept current.** The layer is recomputed twice a day, after its inputs land. If an input is revised, the derived value is revised too, and the revision is recorded like any other ([vintages](https://pakdatahub.com/docs/api-vintages.md)). - **On every plan**, with the usual history window per plan. Official series are never modelled. A derived series sits next to them; it doesn't replace any of them. ## Rates | Series | What it is | Method | |---|---|---| | `rates.policy.history` | SBP policy rate at each month-end, since 1956 | The reverse repo rate (then the policy rate) until the interest-rate corridor of 25 May 2015, the policy (target) rate since | | `rates.real.policy` | Real policy rate | Policy rate at month-end - national CPI inflation (YoY) | | `rates.real.kibor_3m` | Real 3-month KIBOR | Monthly average of the daily 3-month KIBOR offer (months with >=10 fixings) - CPI inflation (YoY) | | `rates.spread.kibor_3m_policy` | 3-month KIBOR minus the policy rate, daily since 2005 | KIBOR 3M offer - the policy rate in effect that day | | `rates.spread.tbill_3m_policy` | 3-month T-bill cut-off minus the policy rate, per auction since 2004 | Cut-off yield - the policy rate in effect on the auction date | | `rates.spread.pkrv_10y_3m`, `rates.spread.pkrv_10y_1y` | Yield-curve slope, daily since 2022 | PKRV 10Y - PKRV 3M (or 1Y). Negative = inverted curve | ## Prices | Series | What it is | Method | |---|---|---| | `inflation.cpi.national.yoy.long` | National CPI inflation (YoY) in one series from 1965 | PBS's CPI YoY where published (Jul 2017 ->), else SBP's base-2015-16 national CPI YoY (Jul 2016 ->), else SBP's historical general CPI YoY (1965 -> Apr 2020). Base years differ across the splice points | | `prices.essentials_inflation.` | Weekly essential-goods inflation (YoY), national and 17 cities, from July 2024 | The geometric mean, over the PBS SPI essential items priced in both weeks (at least 15), of each item's price against 52 weeks earlier: a Jevons index of 52-week price changes, so it doesn't depend on any base week | ## External | Series | What it is | Method | |---|---|---| | `external.import_cover_months` | Months of imports SBP's reserves pay for | SBP's total reserves (gold and foreign exchange) at month-end the average monthly import bill (goods and services, BOP) of the latest three months | | `remittances.total.12m` | Workers' remittances, 12-month rolling total (US$ mn) | Sum of the latest 12 consecutive months. It's free of Ramadan/Eid seasonality | | `fx.spread.interbank.usd` | USD/PKR interbank bid-offer spread (rupees), daily | SBP weighted-average interbank offer - bid | ## Funds and payments | Series | What it is | Method | |---|---|---| | `funds.category.money_market.yield_30d`, `funds.category.shariah_money_market.yield_30d`, `funds.category.income.yield_30d` | What a typical fund in the category is earning, weekly | Median across the category's funds of each fund's latest MUFAP 30-day return (annualised, as MUFAP publishes it) in the week. Weeks with fewer than 5 funds are skipped | | `funds.category.equity.return_1y`, `funds.category.shariah_equity.return_1y` | Typical 1-year equity-fund return, weekly | Median of each fund's latest MUFAP 365-day return in the week | | `payments.raast.share_of_retail_value` | Raast's share of retail payments value, quarterly | Raast transaction value total retail payments value (SBP Payment Systems Review) | ## Fetch one ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/rates.real.policy?from=2015-01-01&sort=asc" ``` Discover the whole layer through the catalog: `GET /v1/catalog?source=PakDataHub`. ## Also computed, not stored as series - [Server-side transforms](https://pakdatahub.com/docs/api-transforms.md) (`yoy`, `mom`, `pct_change`, `3ma`, `index`) on any series. - [Fund analytics](https://pakdatahub.com/docs/api-fund-analytics.md): CAGR, volatility, drawdown per fund. - The weekly [cost-of-living index](https://pakdatahub.com/docs/data-inflation.md) (`cost_of_living.`) and the SPI national averages. # For fintech & lending teams Building a lending, payments, remittance or wallet product in Pakistan means wiring in the country's economic signals. PakDataHub gives you them through one API, starting with 500 free API calls a month. ## What you'll reach for | Need | Series / endpoint | |---|---| | Price floating-rate credit | `rates.kibor.3m` / `6m` / `1y` (offer side), `rates.policy` | | KIBOR history for backtests | `rates.kibor.6m` with `dims=side:offer` (daily, 2005 ->) | | Remittance and FX pricing | `fx.rate.avg.usd`, `fx.rate.avg.sar`, `fx.rate.avg.aed`, `remittances.workers_remittances_received_` | | Credit-model macro inputs | `inflation.cpi.national.yoy`, `industry.lsm.qim`, `sme.npl_ratio` | | Market sizing and adoption | `payments.raast.p2p.value`, `payments.mobile_banking_users`, `payments.ewallet_users`, `payments.qr_merchants` | ## Pricing a floating-rate product ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/rates.kibor.3m?dims=side:offer&limit=1" ``` `/v1/series/{id}/latest` is the cheapest call for a ticker. Add `?dims=side:offer` to get just the offer row (without it you get both bid and offer). Cache the result; KIBOR updates once each business day. ## Don't poll: subscribe On a paid plan, register a [webhook](https://pakdatahub.com/docs/api-webhooks.md) for `rates.kibor.3m` or the whole `fixed-income` module. We POST you a signed payload the moment new data lands. ## Starting on the free plan The free plan's 500 calls a month reach every dataset with the last year of history, which is plenty for a prototype. Move to Developer for 10 years of history, to Pro for full history and revision vintages, or to Business when your app shows the data to your own customers ([Plans](https://pakdatahub.com/docs/plans-credits.md)). # For macro researchers If you study the Pakistani economy, PakDataHub is your primary-source layer. It gives you official series, cleaned and dated, through one API, instead of a dozen government sites and PDFs. ## The core macro series | Area | Ids | |---|---| | Growth & activity | `gdp.growth_rate_real_gross_domestic_product_4` (quarterly), `gdp.gross_domestic_product_total_gross_value_add_3` (1950-2000), `industry.lsm.qim`, `auto.sales_cars`, `power.electricity_generation_hydel` | | Prices | `inflation.cpi.national.yoy`, `inflation.urban_nfne_core_inflation_inflation_measure`, `inflation.wpi`, CPI by group (`inflation.cpi.urban.`), long-run `industry.general_cpi_inflation_measure_year_year_2` (1964 ->) | | External | `bop.current_account_balance_3`, `reserves.total_sbp_reserves` (1948 ->), `remittances.total_inflow_workers_remittances` (1972 ->), `debt.external.total_external_debt_liabilities` | | Money & rates | `banking.m2`, `rates.policy_target`, `rates.reverse_repo` (1956 ->), deep KIBOR `banking._karachi_interbank_offer` | | Exchange rates | `fx.rate.avg.usd` (1947 ->), `fx.effective.reer`, `fx.effective.neer` | ## A typical workflow ```python import pandas as pd KEY = "pk_live_xxx" def series(sid, **p): q = "&".join(f"{k}={v}" for k, v in {"format": "csv", "sort": "asc", "limit": 10000, **p}.items()) return (pd.read_csv(f"https://api.pakdatahub.com/v1/series/{sid}?{q}&api_key={KEY}", parse_dates=["date"]).set_index("date")["value"].rename(sid)) df = pd.concat([series("inflation.cpi.national.yoy"), series("fx.rate.avg.usd", transform="yoy"), series("remittances.total", transform="yoy")], axis=1) ``` Every series has the same shape, so joining inflation, the exchange rate and remittances into one frame is a few lines. ## Reproducibility - **Primary sources:** every value is a primary release, dated and sourced (`meta.source`, and `source_url` in the catalog). - **[Revision vintages](https://pakdatahub.com/docs/api-vintages.md)** (Pro): request data **as it stood** on a past date, for real-time analysis and revision studies. - **[Transforms](https://pakdatahub.com/docs/api-transforms.md):** YoY, MoM, index and moving averages are computed server-side, so your numbers match the API's. - **Freshness:** the [status endpoint](https://pakdatahub.com/docs/api-status.md) shows how current each module is. # Banks, treasury & ALM Treasury, ALM and market-risk teams need the rate environment every day, and the history behind it for stress tests. PakDataHub puts all of it behind one key. ## The rate stack | Need | Series | |---|---| | Today's KIBOR (bid and offer) | `rates.kibor.3m`, `rates.kibor.6m`, `rates.kibor.1y` | | KIBOR history for backtests (daily, 2005 ->) | `rates.kibor.3m`, `rates.kibor.6m`, `rates.kibor.1y` (`dims=side:offer` or `side:bid`) | | Daily interbank USD/PKR for revaluation | `fx.rate.m2m.usd` (SBP M2M rate), `fx.rate.interbank.usd` | | Policy-rate corridor | `rates.policy`, `rates.policy.floor`, `rates.policy.ceiling`, `rates.policy_target` | | Overnight money market | `rates.repo.overnight` (daily, from SBP's market snapshot), `rates.weighted_average_overnight_repo_rate` (history) | | Government yield curve (20 tenors, daily) | `rates.pkrv.1m` ... `rates.pkrv.20y`; Islamic curve `rates.pkisrv.*` | | Primary-market auctions | [`/v1/fixed-income/auctions`](https://pakdatahub.com/docs/api-auctions.md), `rates.auction.tbill.3m.cutoff_yield`, `rates.auction.pib.10y.cutoff_yield` | | Floating PIB and Sukuk prices | [`/v1/securities`](https://pakdatahub.com/docs/api-securities.md) | ## Balance sheet & system context - **Liquidity and funding:** `banking.m2`, `banking.total_deposits_with_scheduled_banks`, weekly `banking.broad_money_liability_side_2`. - **Asset quality benchmarks:** `banking.npl.*` (NPLs by segment) and `sme.npl_ratio`. - **Who holds government paper:** `debt.mtb_holding_banks`, `debt.pib_holding_banks`, `debt.gis_holding_banks`. ## Example: build today's curve ```python import httpx, pandas as pd H = {"X-API-Key": "pk_live_xxx"} tenors = ["1m", "3m", "6m", "1y", "2y", "3y", "5y", "10y", "15y", "20y"] curve = {t: httpx.get(f"https://api.pakdatahub.com/v1/series/rates.pkrv.{t}/latest", headers=H) .json()["data"][0]["value"] for t in tenors} print(pd.Series(curve)) ``` ## Example: a KIBOR stress window ```bash # 6-month KIBOR offer through the 2022-23 tightening cycle curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/banking.six_months_karachi_interbank_offer?from=2022-01-01&to=2024-12-31&sort=asc&format=csv" ``` ## Why teams use it - **One format:** every series comes back the same way, so the curve, KIBOR and auctions join by date without any scraping. - **Reproducible regulatory work:** [revision vintages](https://pakdatahub.com/docs/api-vintages.md) (Pro) return data exactly as it stood on a past date. - **No polling:** [webhooks](https://pakdatahub.com/docs/api-webhooks.md) tell your systems when a new KIBOR fixing or auction result lands. # Credit risk & IFRS 9 macro scenarios IFRS 9 expected-credit-loss models need **forward-looking macroeconomic variables**, and a clean history to fit them on. PakDataHub gives Pakistani lenders, microfinance banks and auditors those variables from official sources, in one consistent format. ## Typical macro variable set | Variable | Series | Frequency | |---|---|---| | Real GDP growth | `gdp.growth_rate_real_gross_domestic_product_4` | quarterly | | Inflation | `inflation.cpi.national.yoy` | monthly | | Policy rate | `rates.policy_target` | on change | | Lending benchmark | `banking.six_months_karachi_interbank_offer` | daily (2005 ->) | | Exchange rate | `fx.rate.avg.usd` (use `transform=yoy` for depreciation) | monthly | | Industrial activity | `industry.lsm.qim` | monthly | | Remittances (household income proxy) | `remittances.total` | monthly | | Sector NPL history | `banking.npl.*`, `sme.npl_ratio` | quarterly | ## Build a quarterly model frame ```python import pandas as pd KEY = "pk_live_xxx" def s(sid, **p): q = "&".join(f"{k}={v}" for k, v in {"format": "csv", "sort": "asc", "limit": 10000, **p}.items()) x = pd.read_csv(f"https://api.pakdatahub.com/v1/series/{sid}?{q}&api_key={KEY}", parse_dates=["date"]) return x.set_index("date")["value"].rename(sid) frame = pd.concat([ s("inflation.cpi.national.yoy"), s("fx.rate.avg.usd", transform="yoy"), s("banking.six_months_karachi_interbank_offer"), s("industry.lsm.qim", transform="yoy"), ], axis=1).resample("QE").mean() ``` ## Audit trail - **Sourcing:** every series carries its official source (`meta.source`, `source_url` in the [catalog](https://pakdatahub.com/docs/api-catalog.md)), so auditors can trace each input. - **Vintages:** with [revision vintages](https://pakdatahub.com/docs/api-vintages.md) (Pro) you can rebuild the exact dataset used at a past reporting date, even after SBP or PBS revise the numbers. - **Stable ids:** series ids don't change, so model code keeps working between reporting cycles. See also [Banks, treasury & ALM](https://pakdatahub.com/docs/use-case-banks-treasury.md) and [For macro researchers](https://pakdatahub.com/docs/for-macro-researchers.md). # Asset managers, wealth & robo-advisors Every open-end, pension (VPS) and exchange-traded fund reported by MUFAP, 567 funds from 25 asset managers, served as clean JSON. Wealth apps, robo-advisors, distributors and AMC analysts can build on it without scraping MUFAP pages. ## What to use | Task | Endpoint | |---|---| | Rank or filter every fund in one call | [`GET /v1/funds/screener`](https://pakdatahub.com/docs/api-funds.md) (NAV, YTD/3M/1Y returns, TER, rating) | | Chart a fund | `GET /v1/funds/{id}/nav` (daily, back to inception, some to 1996) | | Risk and return profile | [`GET /v1/funds/{id}/analytics`](https://pakdatahub.com/docs/api-fund-analytics.md) (CAGR, 3y/5y annualized, volatility, max drawdown) | | Fees | `GET /v1/funds/{id}/expenses` (TER, management fee, S&M) | | What the fund holds | `GET /v1/funds/{id}/portfolio` (asset-class allocation) | | Income investors | `GET /v1/funds/{id}/payouts` (dividend history) | | Manager-level view | [`GET /v1/amcs`](https://pakdatahub.com/docs/api-amcs.md), `GET /v1/amcs/{amc}` (fund count, avg TER, rating mix) | ## Example: cheapest high-yield money-market funds ```python import httpx, pandas as pd H = {"X-API-Key": "pk_live_xxx"} s = pd.json_normalize(httpx.get("https://api.pakdatahub.com/v1/funds/screener", headers=H).json()["data"]) mm = s[s["category"].isin(["Money Market", "Shariah Compliant Money Market"])] print(mm.sort_values(["returns.y1", "ter_ytd"], ascending=[False, True]) .head(10)[["name", "amc", "returns.y1", "ter_ytd"]]) ``` ## Example: risk profile for a portfolio of funds ```python ids = [12843, 12821, 12826] rows = [httpx.get(f"https://api.pakdatahub.com/v1/funds/{i}/analytics", headers=H).json() for i in ids] print(pd.DataFrame([{"fund": r["fund_id"], "cagr": r["cagr_since_inception"], "vol": r["volatility_annualized"], "mdd": r["max_drawdown"]} for r in rows])) ``` ## Pair with macro context Fund performance makes sense against rates and inflation. Compare money-market returns with `rates.kibor.3m` and `rates.policy`, and real returns with `inflation.cpi.national.yoy`. Individual PSX stocks are covered by [pypsx.com](https://pypsx.com), not PakDataHub. On the web: the free [fund screener](https://pakdatahub.com/tools/fund-screener) and the [AMC directory](https://pakdatahub.com/amcs). # Remittance & FX apps Pakistan receives more than $3bn in workers' remittances a month. If you're building a transfer app, a corridor analysis or an FX-risk tool, these are the series you need. ## Corridors & volumes | Need | Series | |---|---| | Total remittances (monthly, US$ mn) | `remittances.total` | | Long history (1972 ->) | `remittances.total_inflow_workers_remittances` | | By sending country | `remittances.workers_remittances_received_`, e.g. Saudi Arabia, U.A.E, Dubai, Abu Dhabi, U.K., U.S.A, Qatar, Oman, Kuwait, Italy | | Overseas investment inflows | `roshan_digital.total_funds_received_abroad_into_rdas_since` | Discover every corridor: ```bash curl "https://api.pakdatahub.com/v1/catalog?module=external&q=workers_remittances_received&limit=100" ``` ## Exchange rates | Need | Series | |---|---| | PKR per USD (monthly average, 1947 ->) | `fx.rate.avg.usd` | | Gulf and major corridors | `fx.rate.avg.sar`, `fx.rate.avg.aed`, `fx.rate.avg.gbp`, `fx.rate.avg.eur` | | Month-end rates | `fx.rate.monthend.usd` and the other `fx.rate.monthend.*` series | | Competitiveness | `fx.effective.reer`, `fx.effective.neer` | | FX buffer | `reserves.total_sbp_reserves`, `reserves.total_banks_reserves` | ## Example: corridor growth dashboard ```python import httpx H = {"X-API-Key": "pk_live_xxx"} for sid in ["remittances.total", "fx.rate.avg.sar", "fx.rate.avg.aed"]: d = httpx.get(f"https://api.pakdatahub.com/v1/series/{sid}", params={"transform": "yoy", "limit": 12}, headers=H).json() print(sid, [(p["date"], round(p["value"], 1)) for p in d["data"]]) ``` **Note:** these are official **monthly** rates from the SBP, used for pricing analytics, contract indexation and reporting. For a daily rate, use the SBP's interbank USD/PKR (`fx.rate.interbank.usd`, bid/offer) and M2M revaluation rate (`fx.rate.m2m.usd`), daily since October 2026. Neither is an intraday dealing quote. # Journalists & data storytelling When the SBP moves the policy rate, flour prices jump in Karachi or reserves fall, you need the official number, its history and a chart quickly. PakDataHub gives you all three from the official sources, with the source named on every series. ## No-code first - [Inflation calculator](https://pakdatahub.com/tools/inflation-calculator): what a rupee amount from any year is worth today. - [USD/PKR history](https://pakdatahub.com/tools/usd-pkr-history): the rupee against the dollar since 1947. - [Cost of living by city](https://pakdatahub.com/tools/cost-of-living): how fast essentials are getting pricier in 17 cities. - [Fund screener](https://pakdatahub.com/tools/fund-screener): every mutual fund, ranked. - A chart page for every series at `https://pakdatahub.com/series/{id}`, e.g. [/series/inflation.cpi.national.yoy](https://pakdatahub.com/series/inflation.cpi.national.yoy). ## The story series | Story | Series | |---|---| | Inflation this month | `inflation.cpi.national.yoy`, food `inflation.cpi.urban.food` | | Petrol or flour price in your city | `/v1/commodities/by-city?item=petrol&city=karachi` | | Rupee depreciation | `fx.rate.avg.usd` with `transform=yoy` | | Reserves crisis and recovery | `reserves.total_sbp_reserves` (monthly, 1948 ->) | | Remittances record | `remittances.total` | | Interest-rate cycle | `rates.policy_target`, `rates.kibor.6m` | | Car sales slump or boom | `auto.sales_cars` | | Cashless Pakistan | `payments.raast.total.value` | ## Get a CSV for your graphics desk ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/reserves.total_sbp_reserves?from=2020-01-01&sort=asc&format=csv" -o reserves.csv ``` Open it in Datawrapper, Flourish, Excel or Google Sheets ([how](https://pakdatahub.com/docs/use-case-excel-sheets-bi.md)). **Attribution:** every series lists its official publisher (`meta.source`: SBP, PBS, PTA or MUFAP). Cite that publisher, with PakDataHub as the access route. # Students & academic research A thesis on Pakistan's economy usually starts with weeks of copying numbers out of PDFs. With PakDataHub it starts with a CSV. The free plan's 500 calls a month cover a typical research project's downloads. ## Long-run series for time-series work | Topic | Series | From | |---|---|---| | Exchange rate | `fx.rate.avg.usd` | 1947 | | FX reserves | `reserves.total_sbp_reserves` | 1948 | | GDP (constant factor cost) | `gdp.gross_domestic_product_total_gross_value_add_3` | 1950 (to 2000) | | GDP, current base | `gdp.gross_domestic_product_total_gross_value_add_2` | 2000 | | CPI inflation | `industry.general_cpi_inflation_measure_year_year_2` | 1964 (to 2020) | | SBP reverse-repo rate | `rates.reverse_repo` | 1956 | | Remittances | `remittances.total_inflow_workers_remittances` | 1972 | | Health facilities | `health.total_number_hospitals` | 1947 | | Population by age (census) | `population.b_w_10_39_years` | 1951 | History depth depends on your plan: the free plan returns the last year. For decades of history, Pro unlocks the full series. Ask your department about a shared key. ## Load it in your tool **R** ```r x <- read.csv("https://api.pakdatahub.com/v1/series/fx.rate.avg.usd?format=csv&sort=asc&limit=10000&api_key=pk_live_xxx") ``` **Stata** ```stata import delimited "https://api.pakdatahub.com/v1/series/inflation.cpi.national.yoy?format=csv&sort=asc&api_key=pk_live_xxx", clear ``` **Python** ```python import pandas as pd df = pd.read_csv("https://api.pakdatahub.com/v1/series/remittances.total?format=csv&sort=asc&api_key=pk_live_xxx", parse_dates=["date"]) ``` ## Cite it properly Cite the **official publisher** (e.g. "State Bank of Pakistan, Average Exchange Rate of Pak Rupees per U.S. Dollar"), accessed via PakDataHub (pakdatahub.com) on the date you downloaded it. `meta.source` and the catalog's `source_url` tell you the publisher and the exact official dataset. # Policy, development & NGOs Development programmes, think tanks and donors track the same questions: who is included, what things cost and how the state spends. PakDataHub brings the official indicators for all three into one place. ## Financial inclusion | Indicator | Series | |---|---| | Instant payments adoption | `payments.raast.p2p.volume`, `payments.raast.p2m.volume` | | Mobile and internet banking users | `payments.mobile_banking_users`, `payments.internet_banking_users` | | Branchless-banking agents | `payments.bb_agents`, `payments.branchless.*` | | Social-welfare cards in issue | `payments.cards.social_welfare` | | SME credit access | `sme.borrowers`, `sme.outstanding`, `sme.share_pvt_sector` | ## Cost of living & food security - Weekly prices of 30 essentials in 17 cities: [`/v1/commodities/by-city`](https://pakdatahub.com/docs/api-commodities.md). - `cost_of_living.`: a weekly essentials index per city. - `inflation.cpi.rural.food` vs `inflation.cpi.urban.food`: food inflation, rural vs urban. ## Fiscal space & public services - **Provincial finances:** `fiscal.consolidated_provincial_total_revenue`, `fiscal.overall_fiscal_balance_punjab` (and `_sindh`, `_kpk`, `_baluchistan`). - **Health infrastructure:** `health.total_number_hospitals`, `health.population_bed`. - **Education:** `education.enrolment.*`, `education.institutions.*`, `education.literacy.*`. ## Household income from abroad `remittances.total` and the remittances-by-country series show the inflows that support millions of households. ```bash # Rural vs urban food inflation, one year curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/series/inflation.cpi.rural.food?transform=yoy&limit=12" curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/series/inflation.cpi.urban.food?transform=yoy&limit=12" ``` # FMCG, retail & supply chain Pricing, procurement and demand planning in Pakistan depend on input costs that change every week and differ city by city. PakDataHub serves the official weekly retail prices and the demand indicators behind them. ## Input & shelf prices (weekly, 17 cities) | Category | Items (`commodities.`) | |---|---| | Staples | `wheat_flour` (20 kg bag), `sugar`, `rice_basmati`, `rice_irri` | | Edible oils | `cooking_oil` (5 L), `vegetable_ghee_tin` (2.5 kg), `vegetable_ghee_loose`, `mustard_oil` | | Dairy & protein | `milk_fresh`, `eggs`, `chicken`, `beef`, `mutton`, pulses | | Energy & logistics | `petrol`, `diesel`, `lpg` | ```bash # Diesel in every city this week (freight-cost map) curl -H "X-API-Key: pk_live_xxx" "https://api.pakdatahub.com/v1/series/commodities.diesel?limit=18" ``` ## Demand & cost indicators | Signal | Series | |---|---| | Consumer inflation by group | `inflation.cpi.urban.food`, `inflation.cpi.urban.transport`, `inflation.cpi.urban.housing` | | Wholesale prices | `inflation.wpi`, `inflation.wpi_food_inflation_measure_year_year` | | Fuel demand by sector | `fuel.pol_sales_domestic`, `fuel.overall_pol_sales_various_sectors_agri_govt` | | Listed FMCG sales | `industry.fmcg.sales_fmcgs` | | Big-ticket demand | `auto.sales_cars`, `auto.total_sales_2_3_wheelers` | | Manufacturing activity | `industry.lsm.qim` | | Consumer sentiment | SBP consumer-confidence surveys (`/v1/search?q=consumer confidence`) | ## Example: weekly ghee-price alert ```python import httpx H = {"X-API-Key": "pk_live_xxx"} d = httpx.get("https://api.pakdatahub.com/v1/series/commodities.vegetable_ghee_tin", params={"dims": "city:national", "transform": "pct_change", "limit": 1}, headers=H).json() change = d["data"][0]["value"] if change and abs(change) > 3: print(f"Ghee (tin) moved {change:.1f}% week on week") ``` Or skip the polling: a [webhook](https://pakdatahub.com/docs/api-webhooks.md) on the `commodities` module fires every Friday when PBS publishes. # Excel, Google Sheets & Power BI Every series is available as CSV, so any spreadsheet or BI tool can load it directly and refresh it on a schedule. The pattern is: ``` https://api.pakdatahub.com/v1/series/?format=csv&sort=asc&api_key= ``` Add `from=YYYY-MM-DD` to limit the window, or `transform=yoy` for growth rates. ## Google Sheets In any cell: ``` =IMPORTDATA("https://api.pakdatahub.com/v1/series/fx.rate.avg.usd?format=csv&sort=asc&from=2020-01-01&api_key=pk_live_xxx") ``` Sheets refreshes `IMPORTDATA` roughly every hour. The key is visible to anyone the sheet is shared with, so use a separate key for shared sheets and revoke it when you're done. ## Excel (Power Query) 1. **Data -> Get Data -> From Other Sources -> From Web**. 2. Choose **Advanced**. URL: `https://api.pakdatahub.com/v1/series/inflation.cpi.national.yoy?format=csv&sort=asc`. 3. Add an HTTP request header: `X-API-Key` = `pk_live_xxx`. This keeps the key out of the URL. 4. **Load**. Refresh any time with **Data -> Refresh All**. ## Power BI ```powerquery let Source = Csv.Document( Web.Contents("https://api.pakdatahub.com/v1/series/rates.kibor.6m", [Query = [format = "csv", sort = "asc", limit = "10000"], Headers = [#"X-API-Key" = "pk_live_xxx"]]), [Delimiter = ",", Encoding = 65001]), Promoted = Table.PromoteHeaders(Source) in Promoted ``` ## Tips - Each refresh costs one request per series. Refresh daily, not every minute, since most series update daily or less often. - The `dims` column holds tags like `{"side":"offer"}`. Filter it in the query (`&dims=side:offer`) rather than in the sheet. - Ids come from the [catalog](https://pakdatahub.com/coverage) or [`/v1/search`](https://pakdatahub.com/docs/api-search.md). # AI agents & LLM apps Language models hallucinate numbers. If your assistant answers questions about Pakistan's economy, such as "what's the latest inflation?", "how have remittances trended?" or "what's KIBOR today?", give it PakDataHub as a tool, so every figure comes from the official source with a date attached. ## Two tools are enough Most agents need only **search** and **fetch**: ```json [ { "name": "search_pakistan_series", "description": "Find PakDataHub series ids for a Pakistan economic/financial concept (e.g. 'cpi', 'kibor', 'remittances saudi', 'raast').", "input_schema": { "type": "object", "properties": { "q": { "type": "string" } }, "required": ["q"] } }, { "name": "get_pakistan_series", "description": "Get observations for a PakDataHub series id. Returns dated values from the official source (SBP/PBS/PTA/MUFAP).", "input_schema": { "type": "object", "properties": { "series_id": { "type": "string" }, "from": { "type": "string", "description": "YYYY-MM-DD" }, "transform": { "type": "string", "enum": ["yoy", "mom", "pct_change", "3ma", "index"] }, "limit": { "type": "integer" } }, "required": ["series_id"] } } ] ``` Implement them as two HTTP calls: ```python import httpx H = {"X-API-Key": "pk_live_xxx"} B = "https://api.pakdatahub.com/v1" def search_pakistan_series(q): return httpx.get(f"{B}/search", params={"q": q, "limit": 8}).json()["data"] def get_pakistan_series(series_id, **params): params.setdefault("limit", 24) r = httpx.get(f"{B}/series/{series_id}", params=params, headers=H).json() return {"meta": r["meta"], "data": r["data"]} ``` Add `/v1/funds/screener` for mutual-fund questions and `/v1/commodities/by-city` for prices by city. ## Grounding the model in the docs - `https://pakdatahub.com/llms.txt` is the overview plus one-line answers. - `https://pakdatahub.com/docs/llms.txt` indexes every docs page. - `https://pakdatahub.com/llms-full.txt` holds all the docs in one file, ready for a system prompt or RAG index. - Append `.md` to any docs URL for the raw Markdown. - `https://pakdatahub.com/AGENTS.md` has instructions written for agents. ## Prompting tips - Tell the model to **always call the tool** for numbers, and to state the `date` and `meta.source` it got back. - Ids are stable, so you can cache common ones (e.g. `inflation.cpi.national.yoy`, `fx.rate.avg.usd`, `rates.kibor.3m`) in the system prompt to save a search call. - PSX stock prices are out of scope. Route those questions to [pypsx.com](https://pypsx.com). # Equity & sector analysts Stock theses on the Pakistan Stock Exchange rest on sector volumes and the macro backdrop. PakDataHub provides both from official sources. For the share prices themselves, pair it with [pypsx.com](https://pypsx.com), the developer API for PSX market data. ## Sector volume series | Sector | Series | |---|---| | Autos | `auto.sales_cars`, `auto.production_cars`, `auto.sales_jeeps_pickups`, `auto.sales_tractors`, `auto.total_sales_2_3_wheelers` | | Cement | `industry.domestic`, `industry.export` (dispatches, to 2023) | | Power | `power.electricity_generation_hydel`, `..._gas`, `..._coal` (generation by fuel) | | Oil marketing | `fuel.pol_sales_power_sector`, `fuel.pol_sales_domestic`, `fuel.overall_pol_sales_various_sectors_agri_govt` | | Fertilizer | `agriculture.fertilizer.urea`, `agriculture.fertilizer.dap` | | FMCG | `industry.fmcg.sales_fmcgs` | | Telecom | `telecom.subscribers.cellular.jazz` (and other operators), `telecom.arpu` | | Banks | `banking.m2`, `banking.total_deposits_with_scheduled_banks`, `banking.npl.*`, `rates.kibor.6m` | | Corporate sector | `corporate.*` (annual financial aggregates of listed non-financial companies) | ## Macro backdrop - **Rates:** `rates.policy_target`, `rates.pkrv.10y`. - **Currency:** `fx.rate.avg.usd`. - **Inflation:** `inflation.cpi.national.yoy`. - **Growth:** `industry.lsm.qim`, `gdp.growth_rate_real_gross_domestic_product_4`. - **External:** `bop.current_account_balance_3`, `reserves.total_sbp_reserves`. ## Example: car sales vs interest rates ```python import pandas as pd KEY = "pk_live_xxx" u = lambda sid, extra="": f"https://api.pakdatahub.com/v1/series/{sid}?format=csv&sort=asc&limit=10000{extra}&api_key={KEY}" cars = pd.read_csv(u("auto.sales_cars", "&transform=yoy"), parse_dates=["date"]).set_index("date")["value"] rate = pd.read_csv(u("rates.policy_target"), parse_dates=["date"]).set_index("date")["value"] print(pd.concat([cars.rename("car_sales_yoy"), rate.resample("ME").ffill().rename("policy_rate")], axis=1).dropna().tail(24)) ``` # Startups & market sizing Investors ask for the TAM slide and where the numbers came from. PakDataHub gives founders and VCs official, dated figures to size Pakistani markets, and a history that shows the trend. ## Digital economy | Metric | Series | |---|---| | Instant payments (value, volume) | `payments.raast.total.value`, `payments.raast.total.volume`, `payments.raast.p2m.volume` | | E-commerce and QR merchants | `payments.ecommerce_merchants`, `payments.qr_merchants`, `payments.pos_merchants` | | Digital channel usage | `payments.mobile_banking_users`, `payments.ewallet_users`, `payments.channel.ecommerce.value` | | Cards in issue | `payments.cards.debit`, `payments.cards.credit`, `payments.cards.prepaid` | | Mobile reach | `telecom.subscribers.cellular.total`, `telecom.teledensity.total`, `telecom.broadband.data_petabytes` | ## Consumer & SME demand - **Remittance-funded household income:** `remittances.total`. - **Durables:** `auto.sales_cars`, `auto.total_sales_2_3_wheelers`. - **SME credit gap:** `sme.outstanding`, `sme.borrowers`, `sme.share_pvt_sector`. - **Mutual-fund penetration:** [`/v1/funds/screener`](https://pakdatahub.com/docs/api-funds.md) for fund counts and categories. ## Example: Raast growth for a deck ```bash curl -H "X-API-Key: pk_live_xxx" \ "https://api.pakdatahub.com/v1/series/payments.raast.total.volume?sort=asc&format=csv" ``` Add `transform=pct_change` for quarter-on-quarter growth, or `transform=index` to show the curve from 100. **For diligence:** every figure traces to its official publisher (`meta.source`), and [revision vintages](https://pakdatahub.com/docs/api-vintages.md) freeze exactly what you cited. # Changelog ## 2026-10-05 - **New data: daily wholesale (mandi) prices from Punjab AMIS.** About 135 grains, vegetables and fruits in about 140 markets, daily since May 2007 (fair-quality price), with each day's min and max from October 2026. New endpoints `/v1/agri/markets`, `/v1/agri/commodities`, `/v1/agri/prices` and `/v1/agri/latest`. See [Wholesale (mandi) prices](https://pakdatahub.com/docs/data-agri-prices.md). - **Revision history back to 2008, on more series.** We now read every SBP Monthly Statistical Bulletin issue SBP still hosts, 2005-2026 (258 issues, up from 177), including the 2026 issues. It also reads the bulletin's national-accounts tables (GDP by sector, provisional and revised). First prints and dated revisions now cover 70 series (about 8,800 first prints and 7,500 revisions), including exports and imports of goods and GDP. See [Revision vintages](https://pakdatahub.com/docs/api-vintages.md). - **New: `GET /v1/series/{id}/revisions`** (Pro+). Shows each point's first print, every figure it replaced (with the date and the publication), and today's value in one call. - **New series from the bulletin:** monthly broad money (`money.m2.monthly`), 1-month KIBOR month-end and monthly average, monthly bank advances-to-deposits and investment-to-deposits ratios, and historical national CPI food, non-food and core (NFNE, trimmed-mean) inflation and old-base CPI levels. Each ships with its print history. - **New: [derived indicators](https://pakdatahub.com/docs/data-derived.md)**, a labelled layer computed from official series with a published formula. It includes the real policy rate and real KIBOR, KIBOR and T-bill spreads over the policy rate, the PKRV curve slope, months of import cover, 12-month remittances, essential-goods inflation by city, and money-market and equity fund-category yields. Derived series have `source: PakDataHub` and a `derived` object (method and inputs) on the catalog record and in `meta`. Available on every plan. - **Weekly SPI history back to July 2023**, read from PBS's own archive list. The weekly city prices and the cost-of-living index now start in July 2023 (was June 2025); the cost-of-living index is rebased to the first week of the longer window. ## 2026-10-04 - **Revision history back to 2011.** `?vintage=` now reaches years before our own tracking began: first prints and dated revisions for 39 headline series (USD/PKR, remittances, exports, reserves, CPI inflation, REER/NEER, bank lending and deposit rates, and more), read from every archived issue of the SBP's Monthly Statistical Bulletin. See [Revision vintages](https://pakdatahub.com/docs/api-vintages.md). - **Fix:** `?vintage=` returned no data for past dates on series that are re-ingested (re-fetching an unchanged value used to look like a revision). Vintages now reflect only real changes. - **New data: daily interbank USD/PKR.** `fx.rate.m2m.usd` (SBP's daily M2M revaluation rate) and `fx.rate.interbank.usd` (weighted-average bid/offer), plus weekly liquid FX reserves `reserves.liquid.{total,sbp,banks}` and the daily weighted-average overnight repo rate `rates.repo.overnight`. Accruing from October 2026. - **Full KIBOR history in the flagship ids.** `rates.kibor.{1w,2w,1m,3m,6m,9m,1y}` now go back to June 2005 (bid/offer via `dims=side:...`); the discontinued 2-year and 3-year tenors are `rates.kibor.2y` / `.3y` (2005-2020). KIBOR is now dated by SBP's own "As on" date, so weekend copies of Friday's fixing are gone. - **New: [Google Sheets & Excel functions](https://pakdatahub.com/docs/spreadsheets.md).** `=PAKDATA()`, `=PAKDATA_LATEST()`, `=PAKDATA_SEARCH()` and `=PAKDATA_INFO()` for Google Sheets; `LAMBDA` functions for Excel 365; a Power Query function for full history. - **Fix:** `GET /v1/series/{id}/latest` honours `dims` (it returned every side) and accepts `format=csv`. CSV `dims` is now compact JSON (`{"side":"offer"}`), not a Python-style repr. - **Plans priced on value.** Plans now differ by history depth, revision vintages, webhooks and the right to show data in your own product (Business). Paid request limits are fair-use ceilings. `GET /v1/plans` adds `for`, `usage_rights`, `vintages`, `webhooks`, `sla`, `support` and `fair_use`. - **Free plan: 500 API calls every month**, resetting on the 1st (was a one-time allotment). `GET /v1/usage` adds `usage.credits_reset`. - `GET /v1/status` adds `totals` (live series, active funds, AMCs, securities) - the counts the site and docs now use everywhere. - **Fix:** the homepage wheat-flour figure now shows the national average, matching the chart. ## 2026-09-24 - **Docs restructured.** One focused page per endpoint and per dataset. Every page is also available as raw Markdown by appending `.md` to its URL, and there are generated `llms.txt`, `llms-full.txt` and `AGENTS.md` files for AI tools. - **Fix:** `/v1/commodities?item=` accepts `wheat_flour`, `commodities.wheat_flour` or the legacy `commodity.wheat_flour`. It had returned 404 for every form after the id rename. - **Fix:** `?transform=yoy|mom|pct_change|3ma` now fetches the partner points outside your `from`/`limit` window, so small windows no longer come back as nulls. - **Fix:** `/v1/usage` reports `minute_used` from the live rate-limit window. It was always 0. - **Data:** duplicate daily copies of auction cut-offs removed; each series now has one point per auction. - **Data:** release-calendar entries now link to real series ids. ## 2026-09-23 - About 5,800 series that are zero across their whole history were hidden from the catalog. Each one reappears automatically if its source ever publishes a non-zero value. - New docs pages: an API reference with per-endpoint schemas, and the data dictionary. ## 2026-09-22 - New: `GET /v1/funds/screener` (every fund in one call) and the free fund-screener tool. - New: AMC pages, the blog, and 240+ API guides. ## 2026-08 - New: `GET /v1/funds/{id}/analytics` (CAGR, volatility, drawdown) and `GET /v1/amcs`. - New: server-side transforms (`?transform=`) and revision vintages (`?vintage=`). - New: a credit-based free tier (500 one-time credits). - New: Google sign-in, and API keys emailed on signup.