IBR Live Forex API
Real-time and historical forex data over REST and WebSocket. One API key, passed as a query parameter, unlocks everything your plan allows — no OAuth, no signing, no header gymnastics.
api_key)01Quick Start
1. Get a key. Sign up and grab your API key from Dashboard → API Settings.
2. Make a request. Append apiKey=YOUR_API_KEY to any endpoint:
curl -X GET "https://api.ibrlive.com/api/forex/snapshot/USDINR?apiKey=YOUR_API_KEY"
{
"success": true,
"requested_symbols": ["USDINR"],
"lastQuotes": [
{ "s": "USDINR", "a": 83.58, "b": 83.56, "t": 1704123456789 }
],
"source": "redis_cache",
"timestamp": "2024-01-15T18:30:00Z"
}
3. Check success. Every response — success or failure — is JSON with a top-level success boolean. See §6 Error Handling for the failure shape.
That's the whole integration loop. Everything below fills in the details: which endpoints exist, what each one needs, and what plan unlocks it.
02Authentication
| Method | API key as a query parameter: ?apiKey=YOUR_API_KEY |
| Required on | Every endpoint, REST and WebSocket, no exceptions |
| Where to find it | Dashboard → API Settings |
| Transport | Query string only — there is no header-based alternative |
// fetch fetch(`https://api.ibrlive.com/api/forex/snapshot/USDINR?apiKey=${apiKey}`) .then(r => r.json()) .then(console.log); // axios const { data } = await axios.get('https://api.ibrlive.com/api/forex/snapshot/USDINR', { params: { apiKey } });
03Endpoints
All REST endpoints share the base URL https://api.ibrlive.com. "Min. plan" is the lowest plan that unlocks the endpoint — anything higher also has access.
| # | Endpoint | Method | Min. plan | Update frequency |
|---|---|---|---|---|
| 1 | Forex Snapshot (Live Rate API) | GET | FREE | Real-time (Pro/Ultimate); periodic (Essential) |
| 2 | Snapshot WebSocket | WS | PRO | Init + delta stream, ~3s |
| 3 | Currency Conversion | GET | BASIC | Real-time / ~60s, plan-dependent |
| 4 | Forex Aggregates | GET | BASIC | Daily, midnight IST |
| 5 | Technical Indicators | GET | ULTIMATE | Every 3s |
| 6 | Previous Close | GET | BASIC | Every 3s |
| 7 | Indian Customs Reference Rates | GET | ESSENTIAL | Mon–Fri 6:40 PM IST |
| 8 | RBI Reference Rates (Latest) | GET | ESSENTIAL | On RBI publish |
| 9 | DXY Index (Last Value) | GET | ESSENTIAL | ~Every 3s |
| 10 | RBI Reference Rates (Historical) | GET | BASIC | Static — date range, up to 5 years |
| 11 | Forward Rate (Broken Date) | GET | PRO add-on | On-demand (broken-date calc) |
| 12 | Monthly Forward Rates | GET | PRO add-on | On-demand (1M–12M ladder) |
| 13 | Cash / Tom / Spot | GET | PRO add-on | On-demand (1M-derived points) |
3.1Forex Snapshot (Live Rate API)
Live bid/ask quotes and last trades. Three URL shapes depending on whether you want all pairs, one pair, or a specific list.
| Variant | URL | Min. plan | Call cost |
|---|---|---|---|
| All pairs | GET /api/forex/snapshot?apiKey=... | FREE | ceil(total pairs ÷ 5), min 1 |
| Single pair | GET /api/forex/snapshot/{symbol}?apiKey=... | FREE | 1 |
| Multiple pairs (batch) | GET /api/forex/snapshot/symbols?symbols=A,B,C&apiKey=... | FREE | 1 call per pair requested |
All-pairs Snapshot
You pay for the batch, not the count. ~150 live pairs → 30 calls per request, regardless of which pairs you actually need.
Batch / Multi-symbol
You pay for the count, not the batch. Request 7 pairs in one URL → 7 calls deducted. No discount for batching.
ceil(pairs ÷ 5) formula that the all-pairs endpoint uses. Batch is billed 1 call per pair, full stop — request 7 pairs in one URL, that's 7 calls deducted, not ceil(7 ÷ 5) = 2. Conflating the two cost models is the easiest way to misforecast usage.ceil(150 ÷ 5) = 30 calls deducted from the 100/month Free allowance — so a Free key supports roughly 3 all-pairs calls per month, or many more single/batch calls (1 call each). Free is free forever, not a one-time trial. See §4.5 for the full Free-plan onboarding guide.Path Parameter
| Name | Type | Description |
|---|---|---|
symbol | string | Single pair, e.g. USDINR (single-pair variant only) |
Query Parameters
| Name | Required | Description |
|---|---|---|
apiKey | ✅ | Your API key |
symbols | Multi-symbol only | Comma-separated pairs, e.g. USDINR,EURUSD,GBPINR |
# All pairs — Free and above curl "https://api.ibrlive.com/api/forex/snapshot?apiKey=YOUR_API_KEY" # Single pair — Free and above curl "https://api.ibrlive.com/api/forex/snapshot/USDINR?apiKey=YOUR_API_KEY" # Multiple pairs / batch — Free and above curl "https://api.ibrlive.com/api/forex/snapshot/symbols?symbols=USDINR,EURUSD,GBPINR&apiKey=YOUR_API_KEY"
"success": true, "user": "[email protected]", "lastQuotes": [ { "s": "USDINR", "a": 83.58, "b": 83.56, "t": 1704123456789, "t_ist": "2024-01-15T18:30:00+05:30" }, { "s": "EURUSD", "a": 1.0852, "b": 1.0850, "t": 1704123456789, "t_ist": "2024-01-15T18:30:00+05:30" } ], "lastTrades": [ { "s": "USDINR", "p": 83.57, "t": 1704123456789, "t_ist": "2024-01-15T18:30:00+05:30" } ] }
Response fields: a = ask, b = bid, p = last trade price, t = Unix ms timestamp (IBR response time, not upstream feed time), t_ist = same time in IST, s = symbol. The single-pair variant returns quote and trade objects instead of lastQuotes/lastTrades arrays. Multi-symbol errors may include requested_symbols and not_found_symbols in the JSON body.
3.2Snapshot WebSocket (Live Stream)
Streams snapshot updates instead of polling REST — connect once, get an init snapshot, then automatic delta pushes (~3s refresh) for as long as the socket stays open. Deltas contain only pairs whose quote/trade values changed; if nothing changed, no message is sent and no tokens are deducted.
Connection limits: Pro — up to 2 concurrent connections per account. Ultimate — up to 5.
Connection URLs
# All pairs wss://api.ibrlive.com/api/forex/ws/snapshot?api_key={apiKey} # Filtered on connect wss://api.ibrlive.com/api/forex/ws/snapshot?api_key={apiKey}&symbols=USDINR,EURUSD,GBPINR
| Param | Required | Notes |
|---|---|---|
api_key | ✅ | Also accepts apiKey |
symbols | optional | Comma-separated filter applied at connect; omit for all pairs. Changeable later via subscribe. |
Call Usage
All-pairs stream
Init: full snapshot — e.g. ~207 pairs → 42 tokens.
Delta: only changed pairs — e.g. 22 changed → 5 tokens.connected, subscribed, pong are free.
Filtered symbols (e.g. EURUSD, GBPUSD)
Init: 1 token per subscribed pair — 2 pairs → 2 tokens.
Delta: 1 token per changed pair — 1 pair moves → 1 token.
Same per-pair logic as REST batch/multi-symbol (§3.1).
- Each billed push includes
request_units_deducted,pairs_in_push, andbilling_mode(all_pairs_ceil5orfiltered_per_pair_delta). - Changing filters via
subscribesends a newinitand bills again for the new pair count.
Client → Server Messages
| Action | Payload | Effect |
|---|---|---|
subscribe | {"action":"subscribe","symbols":["USDINR","EURUSD"]} | Switch to filtered pairs |
subscribe | {"action":"subscribe"} | Switch to all pairs (no symbols / empty array) |
ping | {"action":"ping"} | Keep-alive / latency check — server replies pong |
Server → Client Message Types
// 1. connected — immediately after successful auth (free) { "type": "connected", "plan": "PRO", "max_connections": 2, "active_connections": 1, "symbols": "all", "message": "Send {\"action\":\"subscribe\",\"symbols\":[\"EURUSD\"]} to filter..." } // 2. init — full snapshot on connect or after subscribe (billed) { "type": "init", "success": true, "totalResults": 207, "lastQuotes": [{ "s": "USDINR", "a": 83.58, "b": 83.56, "t": 1704123456789, "t_ist": "2024-01-15T18:30:00+05:30" }], "lastTrades": [{ "s": "USDINR", "p": 83.57, "t": 1704123456789, "t_ist": "2024-01-15T18:30:00+05:30" }], "removedSymbols": [], "timestamp": "2024-01-15T18:30:00Z", "lastUpdate": 1704123456789, "source": "finage_snapshot", "request_units_deducted": 42, "pairs_in_push": 207, "billing_mode": "all_pairs_ceil5", "filtered_symbols": null } // 3. delta — only changed pairs on each ~3s tick (billed; skipped if nothing changed) { "type": "delta", "success": true, "totalResults": 207, "lastQuotes": [{ "s": "EURUSD", "a": 1.0852, "b": 1.0850, "t": 1704123456790, "t_ist": "2024-01-15T18:30:01+05:30" }], "lastTrades": [], "removedSymbols": [], "changed_pairs": 1, "timestamp": "2024-01-15T18:30:01Z", "lastUpdate": 1704123456790, "source": "finage_snapshot", "request_units_deducted": 1, "pairs_in_push": 1, "billing_mode": "filtered_per_pair_delta", "filtered_symbols": ["EURUSD", "GBPUSD"] } // 4. subscribed — confirms a filter change (free; followed by init) { "type": "subscribed", "symbols": ["USDINR", "EURUSD"], "message": "Receiving updates for selected symbols only" } // 5. pong — reply to ping (free) { "type": "pong", "ts": 1704123456789 } // 6. error — auth, plan, or limit failures { "type": "error", "error": "WebSocket snapshot is only available on Pro and Ultimate plans", "current_plan": "ESSENTIAL", "required_plans": ["PRO", "ULTIMATE"] }
Client Example
const apiKey = "YOUR_API_KEY"; const ws = new WebSocket(`wss://api.ibrlive.com/api/forex/ws/snapshot?api_key=${apiKey}`); ws.onopen = () => console.log("WebSocket connected"); ws.onmessage = (event) => { const msg = JSON.parse(event.data); switch (msg.type) { case "init": case "delta": console.log(msg.type, "pairs:", msg.pairs_in_push, "tokens:", msg.request_units_deducted); console.log("Quotes:", msg.lastQuotes); break; case "connected": console.log("Plan:", msg.plan, "Max connections:", msg.max_connections); break; case "error": console.error(msg.error, msg.details); break; } }; ws.send(JSON.stringify({ action: "subscribe", symbols: ["USDINR", "EURUSD"] })); ws.send(JSON.stringify({ action: "subscribe" })); ws.onerror = (err) => console.error("WebSocket error", err); ws.onclose = (e) => console.log("Closed", e.code, e.reason);
ceil(pairs ÷ 5). Filtered WebSocket (1 token per pair) is often competitive with REST batch for a small symbol list, and delta-only pushes avoid charging when prices are unchanged.3.3Currency Conversion
Converts an amount between two currencies using cached snapshot bid/ask mid rates. Cross-rates resolve via direct pair, inverse pair, or a USD cross when no direct pair exists. Rate freshness follows your plan's cache tier: Basic/Essential use ~60-second snapshot data; Pro/Ultimate use real-time data.
GET https://api.ibrlive.com/api/forex/convert?from={from}&to={to}&amount={amount}&apiKey={apiKey}
| Param | Required | Description |
|---|---|---|
from | ✅ | Source currency, 3-letter ISO code, e.g. USD |
to | ✅ | Target currency, 3-letter ISO code, e.g. INR |
amount | ✅ | Amount in source currency |
apiKey | ✅ | Your API key |
curl "https://api.ibrlive.com/api/forex/convert?from=USD&to=INR&amount=100&apiKey=YOUR_API_KEY"
{
"success": true,
"from": "USD",
"to": "INR",
"amount": 100,
"rate": 83.57,
"converted_amount": 8357,
"user": "[email protected]"
}
3.4Forex Aggregates
Historical OHLCV bars. Bar size is controlled by time + multiply; range by from/to. Server caps results at 10,000 records per request for performance.
GET https://api.ibrlive.com/api/aggregate/data?symbol={symbol}&time={time}&multiply={multiply}&from={from}&to={to}&apiKey={apiKey}
| Param | Required | Description |
|---|---|---|
symbol | ✅ | Forex pair, e.g. USDINR |
time | ✅ | Bar size: day, month, quarter, year |
multiply | optional | Positive multiplier on time. Default 1 |
from | ✅ | Start date, YYYY-MM-DD |
to | ✅ | End date, YYYY-MM-DD |
apiKey | ✅ | Your API key |
curl "https://api.ibrlive.com/api/aggregate/data?symbol=USDINR&time=day&multiply=1&from=2020-01-01&to=2026-04-30&apiKey=YOUR_API_KEY"
{
"success": true,
"symbol": "USDINR",
"time": "day",
"multiply": 1,
"from": "2020-01-01",
"to": "2026-04-30",
"limit": 10000,
"data": {
"results": [
{ "o": 83.45, "h": 83.67, "l": 83.32, "c": 83.58, "v": 1250000, "t": 1704067200000 }
]
},
"recordCount": 10000,
"source": "redis_cache",
"responseTimeMs": 15,
"dataAgeSeconds": 3600,
"lastUpdate": "2024-01-15T18:30:00Z",
"user": "[email protected]"
}
o/h/l/c = open/high/low/close, v = volume, t = Unix ms timestamp. Data refreshes daily at midnight IST; a manual refetch endpoint exists but should be used sparingly since it's a heavy backend operation and consumes extra calls.
3.5Technical Indicators
RSI, MACD, SMA/EMA, Bollinger Bands, and Stochastic oscillators, refreshed every 3 seconds.
GET https://api.ibrlive.com/api/forex/get-technical-indicators?symbol={symbol}&timeframe={timeframe}&apiKey={apiKey}
| Param | Required | Description |
|---|---|---|
symbol | ✅ | Forex pair, e.g. USDINR |
timeframe | optional | daily (default) or weekly |
apiKey | ✅ | Your API key |
import requests def get_technical_indicators(symbol, timeframe='daily', api_key='YOUR_API_KEY'): response = requests.get( "https://api.ibrlive.com/api/forex/get-technical-indicators", params={"symbol": symbol, "timeframe": timeframe, "apiKey": api_key} ) response.raise_for_status() data = response.json() if not data['success']: raise Exception(data['error']) return data['data']
{
"success": true,
"data": { /* indicator values from upstream */ },
"symbol": "USDINR",
"timeframe": "daily",
"source": "redis_cache",
"response_time_ms": 12,
"data_age_seconds": 2,
"timestamp": "2024-01-15T18:30:00Z",
"redis_key": "forex:technical:USDINR:daily",
"user_info": {
"email": "[email protected]",
"subscription_plan": "ULTIMATE",
"remaining_api_calls": 12999000
}
}
3.6Previous Close
Previous trading day's OHLCV for a pair, updated every 3 seconds and cached.
GET https://api.ibrlive.com/api/forex/previous-close?symbol={symbol}&apiKey={apiKey}
| Param | Required | Description |
|---|---|---|
symbol | ✅ | Forex pair, e.g. USDINR |
apiKey | ✅ | Your API key |
{
"success": true,
"symbol": "USDINR",
"data": {
"open": 83.42,
"high": 83.68,
"low": 83.28,
"close": 83.55,
"volume": 1180000,
"timestamp": 1703980800000,
"date": "2024-01-14T18:30:00Z"
},
"source": "redis_cache",
"response_time_ms": 8,
"data_age_seconds": 45,
"timestamp": "2024-01-15T18:30:00Z",
"user": "[email protected]"
}
3.7Indian Customs Forex Reference Rates
ICEGATE-aligned customs valuation rates. Rates are refreshed Monday to Friday at 6:40 PM IST. Response has no extra wrapper — just meta and data[], and no top-level success field, unlike every other endpoint in this API.
GET https://api.ibrlive.com/api/forex/reference-rates/indian-customs?apiKey={apiKey}
{
"meta": { "row_count": 22 },
"data": [
{
"Currency Code": "AED",
"Currency Name": "UAE Dirham",
"Effective start Date": "2026-04-06",
"Units of foreign currency equivalent to Indian rupees": "1",
"Import Rate": "26.1",
"Export Rate": "24.55"
}
]
}
success, code that does if (!data.success) throw ... (as recommended elsewhere in this doc) will misfire here. Check for data.data / data.meta instead.3.8RBI Forex Reference Rates (Latest)
Most recently published RBI reference rate (date plus USD/INR, GBP/INR, EUR/INR, JPY/INR per 100 JPY, AED/INR, and IDR/INR per 10,000 IDR — all returned as strings). Same no-success-field shape as Customs above.
GET https://api.ibrlive.com/api/forex/reference-rates/rbi-latest?apiKey={apiKey}
{
"data": [
{
"date": "04/09/2026",
"USD/INR": "94.4914",
"GBP/INR": "127.9703",
"EUR/INR": "109.8822",
"JPY/INR": "60.5200",
"AED/INR": "25.7272",
"IDR/INR": "53.5864"
}
]
}
3.9DXY Index (Last Value)
US Dollar Index value against a basket of major currencies. Cached, refreshed roughly every 3 seconds. Minimal response shape — symbol, price, timestamp, timestamp_ist (no top-level success field).
GET https://api.ibrlive.com/api/last/index/DXY?apiKey={apiKey}
{
"symbol": "DXY",
"price": 99.1852,
"timestamp": 1774339583085,
"timestamp_ist": "2026-03-24T12:16:23+05:30"
}
3.10RBI Forex Reference Rates (Historical)
Up to 5 years of RBI reference rates by date range. Fields: date, USD/INR, GBP/INR, EUR/INR, JPY/INR (per 100 JPY), AED/INR, and IDR/INR (per 10,000 IDR).
GET https://api.ibrlive.com/api/forex/reference-rates/rbi-historical?from={from}&to={to}&apiKey={apiKey}
| Param | Required | Description |
|---|---|---|
from | ✅ | Start date (inclusive), DD-MM-YYYY or DD/MM/YYYY |
to | ✅ | End date (inclusive), DD-MM-YYYY or DD/MM/YYYY |
apiKey | ✅ | Your API key |
DD-MM-YYYY) differs from Forex Aggregates (YYYY-MM-DD) — easy to trip over if you're calling both in the same integration.{
"data": [
{ "date": "15/09/2026", "USD/INR": "95.9253", "GBP/INR": "129.1900", "EUR/INR": "110.5920", "JPY/INR": "61.9400", "AED/INR": "26.1171", "IDR/INR": "54.2010" },
{ "date": "16/09/2026", "USD/INR": "95.9433", "GBP/INR": "129.3204", "EUR/INR": "110.7908", "JPY/INR": "61.8600", "AED/INR": "26.1220", "IDR/INR": "54.2073" }
]
}
3.11Forward Rate (Broken Date)
Add-on pricing: ₹9,999/mo (INR) or $119/mo (USD) on Pro or Ultimate at checkout — not included by default. Yearly billing adds the add-on to your plan total first, then applies ×12 with 10% discount on the combined amount.
What it is for: Get a forward exchange rate for any custom settlement date (not just fixed monthly tenors) — useful for hedging, invoicing, and broken-date FX pricing on your website or app.
How to use: Call the endpoint with a supported currency pair, the forward settlement date you need, and your apiKey. Optionally pass trade_date if you want to price as of a specific day (defaults to today UTC).
What you get: Spot bid/ask, forward premium bid/ask, final forward rate bid/ask, plus the related settlement dates for that request.
GET https://api.ibrlive.com/api/forex/forward-rate?pair={pair}&date={date}&apiKey={apiKey}
| Param | Required | Description |
|---|---|---|
pair | ✅ | e.g. USDINR or USD/INR — one of 24 supported pairs |
date | ✅ | Forward settlement date YYYY-MM-DD |
trade_date | optional | Defaults to today (UTC) |
apiKey | ✅ | Your API key |
curl "https://api.ibrlive.com/api/forex/forward-rate?pair=USDINR&date=2026-08-19&apiKey=YOUR_API_KEY"
{
"pair": "USDINR",
"display_pair": "USD/INR",
"trade_date": "2026-06-30",
"spot_settlement_date": "2026-07-02",
"forward_start_date": "2026-07-03",
"target_date": "2026-08-19",
"max_settlement_date": "2027-07-02",
"spot": { "bid": 94.657, "ask": 94.66 },
"premium": { "bid": 0.3666, "ask": 0.3866 },
"forward": { "bid": 95.0236, "ask": 95.0466 }
}
Supported pairs: GET /api/forex/forward-rate/pairs. Requires Pro or Ultimate with Forward Rate add-on at checkout; Free, Basic, and Essential receive 403.
Supported forward pairs (20):
USDINR USDCNY EURCNY JPYCNY HKDCNY GBPCNY
EURUSD USDJPY USDHKD GBPUSD AUDUSD USDCHF
USDCAD
JPYINR CNYINR GBPINR EURINR AUDINR CADINR CHFINR
3.12Monthly Forward Rates
What it is for: Show a full month-by-month forward premium table (1M to 12M) with exporter and importer yields — ideal for forward rate boards, exporter/importer dashboards, and tenor comparison UIs.
How to use: Call the endpoint with a supported currency pair and your apiKey. Optionally pass trade_date (defaults to today UTC). One request returns all 12 monthly tenors.
What you get: A 12-row array. Each row includes tenor, bid_premium, ask_premium, exporter_yield, and importer_yield.
GET https://api.ibrlive.com/api/forex/forward-rate/monthly?pair={pair}&apiKey={apiKey}
| Param | Required | Description |
|---|---|---|
pair | ✅ | e.g. USDINR or USD/INR — one of 24 supported pairs |
trade_date | optional | Defaults to today (UTC) |
apiKey | ✅ | Your API key |
curl "https://api.ibrlive.com/api/forex/forward-rate/monthly?pair=USDINR&apiKey=YOUR_API_KEY"
[
{
"tenor": "1M",
"bid_premium": 24.32,
"ask_premium": 26.32,
"exporter_yield": 2.9722,
"importer_yield": 3.216
},
{
"tenor": "2M",
"bid_premium": 47.46,
"ask_premium": 49.46,
"exporter_yield": 2.85,
"importer_yield": 3.08
}
/* … 3M through 12M */
]
Same 20 pairs as §3.11. Requires Pro or Ultimate with Forward Rate add-on; Free, Basic, and Essential receive 403.
3.13Cash / Tom / Spot
What it is for: Get near-term Cash, Tom, and Spot FX values for a currency pair — useful for same-day / next-day settlement screens, treasury tools, and short-dated FX pricing.
How to use: Call the endpoint with a supported currency pair and your apiKey. Optionally pass trade_date (defaults to today UTC).
What you get: Spot rate, Cash premium, Cash rate, Tom premium, and Tom rate — each with bid and ask. Enough to build a treasury Cash/Tom/Spot board.
GET https://api.ibrlive.com/api/forex/cash-tom-spot?pair={pair}&apiKey={apiKey}
| Param | Required | Description |
|---|---|---|
pair | ✅ | e.g. USDINR or USD/INR — one of 24 supported pairs |
trade_date | optional | Defaults to today (UTC) |
apiKey | ✅ | Your API key |
curl "https://api.ibrlive.com/api/forex/cash-tom-spot?pair=USDINR&apiKey=YOUR_API_KEY"
{
"spot": { "bid": 96.3227, "ask": 96.342 },
"cash_premium": { "bid": 1.5, "ask": 1.9 },
"cash": { "bid": 96.3077, "ask": 96.323 },
"tom_premium": { "bid": 0.3, "ask": 0.5 },
"tom": { "bid": 96.3197, "ask": 96.337 }
}
Same 20 pairs as §3.11. Requires Pro or Ultimate with Forward Rate add-on; Free, Basic, and Essential receive 403.
Supported Symbols
Snapshot / conversion / aggregates support 3,000+ pairs (separate from the 20 Forward Rate pairs above). Approximately 150 are live in the all-pairs Snapshot at any given time. Commonly used:
USDINR EURINR GBPINR AUDINR CADINR NZDINR AEDINR SGDINR THBINR CNYINR JPYINR CHFINR MYRINR EURUSD GBPUSD USDJPY USDCNY
Data Refresh Rates
| Data type | Frequency |
|---|---|
| Snapshot (REST & WebSocket) | ~3 seconds |
| Previous Close | ~3 seconds |
| Aggregates | Daily at midnight IST |
| Technical Indicators | ~3 seconds |
| Currency Conversion | ~60s (Basic/Essential) or real-time (Pro/Ultimate) |
| DXY Index | ~3 seconds |
| Indian Customs Rates | Mon–Fri 6:40 PM IST |
| RBI Reference (Latest) | On RBI publish |
| RBI Reference (Historical) | Static — date-range lookup |
| Forward Rate | On-demand broken-date calculation |
| Monthly Forward Rates | On-demand 1M–12M ladder |
| Cash / Tom / Spot | On-demand near-term settlement points |
04Plans & Limits
4.1Plan Tiers
60-second
60-second
real-time (3s)
real-time (3s)
real-time (3s)
4.2Overage Pricing — Calls Beyond Your Plan's Included Amount
Once a paid plan's included monthly calls are used up, additional calls are billed per-call rather than hard-blocked, up to a recommended maximum. This is new information not previously documented — earlier drafts of this doc assumed a hard monthly cap with no overage option, which was incorrect for paid plans.
| Plan | Included calls/month | Price (₹) | Price ($) | Recommended max/month |
|---|---|---|---|---|
| Basic | 35,000 | ₹0.00200 | $0.00002353 | 500,000 |
| Essential | 1,500,000 | ₹0.00175 | $0.00002059 | 1,500,000 |
| Pro | 3,500,000 | ₹0.00150 | $0.00001765 | 10,000,000 |
| Ultimate | 15,000,000 | ₹0.00125 | $0.00001471 | 30,000,000 |
How to read this table:
- Included calls is what your base price covers — once you exceed this in a billing month, you're charged per call at the additional-call rate for every call past that point.
- Recommended maximum is a guardrail, not a hard technical block. Per-call price gets cheaper at higher tiers, so heavy users get better unit economics by upgrading rather than paying overage indefinitely on a lower tier.
- Free has no overage tier. Once its 100 calls/month are used, calls fail until the next billing cycle — paid plans degrade gracefully into overage billing, Free does not.
USD Billing — Minimum Purchase & Rounding
Because the per-call USD rate is fractions of a cent, USD-billed accounts don't get charged the raw calculated amount directly. Two rules apply:
- Minimum overage purchase is $1. Even if your calculated overage comes out to a few cents, the smallest amount actually billed is $1.
- Amounts round up to the next whole dollar. A calculated overage of $0.35 rounds up to $1 — never down, never left fractional.
4.3Per-Plan Feature Access
| Plan | Real-time updates | Snapshot multi-symbol | RBI/Customs/DXY/Holidays | Technical Indicators | WebSocket |
|---|---|---|---|---|---|
| Free | ❌ (60s) | ❌ | ❌ | ❌ | ❌ |
| Basic | ❌ (60s) | ❌ | ❌ | ❌ | ❌ |
| Essential | ✅ | ✅ | ✅ | ❌ | ❌ |
| Pro | ✅ | ✅ | ✅ | ❌ | ✅ (2 conn) |
| Ultimate | ✅ | ✅ | ✅ | ✅ | ✅ (5 conn) |
Technical Indicators is Ultimate-only with no exceptions — not available even on Pro. Real-time (sub-60s) updates don't start until Essential — Free and Basic are both capped at 60-second data regardless of which endpoints they can reach.
4.4Best Practices
- Cache responses where data freshness allows it, to conserve quota and avoid unnecessary overage charges.
- Poll at 10+ second intervals for real-time REST data on Essential+. On Free/Basic, since updates are 60-second regardless, polling faster than 60s is pure waste.
- For WebSocket: all-pairs uses
ceil(pairs ÷ 5)per init/delta; filtered symbols use 1 token per pair (init) and per changed pair (delta).connected,subscribed, andpongare free. - Avoid the manual aggregates refetch unless you specifically need to force a refresh; it's a heavy operation and consumes extra calls.
- Watch usage against the recommended maximum, not just the included amount — overage billing means no hard block, but staying under the ceiling keeps your bill predictable.
- Free-plan users: see §4.5 below — this is the priority path for anyone starting out.
4.5Free Plan: Which Endpoint to Use, and Why It Matters
This section exists because getting Free-plan users to a good first experience is the highest-priority part of this documentation — Free is the funnel into every paid plan, and a confusing first call is the easiest way to lose a future customer before they ever see what the paid tiers can do.
Snapshot Endpoints Free-Plan Users Can Call
GET https://api.ibrlive.com/api/forex/snapshot?apiKey=YOUR_API_KEY GET https://api.ibrlive.com/api/forex/snapshot/USDINR?apiKey=YOUR_API_KEY GET https://api.ibrlive.com/api/forex/snapshot/symbols?symbols=USDINR,EURUSD&apiKey=YOUR_API_KEY
Free includes all three Snapshot variants (see §3.1): all-pairs, single-symbol, and batch/multi-symbol. Prefer single-symbol or a small batch when you only need a few pairs — all-pairs costs ceil(pairs ÷ 5) and uses quota much faster.
Why This Matters More Than It Looks Like It Should
A Free-plan developer's first instinct is usually to look for "give me just USDINR" — that is the single-symbol endpoint, and it is now available on Free. Use it for evaluation instead of pulling all ~150 pairs when you only need one.
What a Free-Plan Integration Should Actually Look Like
- Call the single-symbol endpoint for the pair you care about:
bash
curl "https://api.ibrlive.com/api/forex/snapshot/USDINR?apiKey=YOUR_API_KEY"
- Or request a small batch when you need a few pairs:
bash
curl "https://api.ibrlive.com/api/forex/snapshot/symbols?symbols=USDINR,EURUSD,GBPINR&apiKey=YOUR_API_KEY"
- Budget your calls carefully. Single-symbol = 1 call; batch = 1 call per pair; all-pairs =
ceil(total pairs ÷ 5)— at ~150 pairs, that's 30 calls deducted from your 100/month allowance. Prefer single/batch on Free. - Free is for evaluation and light integration testing. Anyone running a production live feed should upgrade to Basic or higher for larger quotas and additional endpoints.
The natural upgrade trigger: once a developer needs historical data, conversion, previous close, or more than 100 calls/month, surface Basic (35,000/month) and Essential for real-time refresh and reference rates.
| Need | Free can do it? | What unlocks it |
|---|---|---|
| Confirm API key works | ✅ | — |
| See live rates for evaluation/testing | ✅ | — |
| Get just one specific pair | ✅ | — |
| Multiple specific pairs in one call | ✅ | — |
| Poll regularly for a live production feature | ❌ | Basic at minimum; Essential for real-time refresh |
| Historical data, conversion, previous close, RBI historical | ❌ | Basic |
| RBI Latest / Customs / DXY reference rates | ❌ | Essential |
05Endpoint Access Matrix
A consolidated view of which plan unlocks which of the 10 endpoints, since access requirements are scattered across each endpoint's individual notes above.
| Endpoint | Free | Basic | Essential | Pro | Ultimate |
|---|---|---|---|---|---|
| Snapshot — all pairs | ✅ | ✅ | ✅ | ✅ | ✅ |
| Snapshot — single pair | ✅ | ✅ | ✅ | ✅ | ✅ |
| Snapshot — batch/multi-symbol | ✅ | ✅ | ✅ | ✅ | ✅ |
| Snapshot WebSocket | ❌ | ❌ | ❌ | ✅ (2 conn) | ✅ (5 conn) |
| Currency Conversion | ❌ | ✅ | ✅ | ✅ | ✅ |
| Forex Aggregates | ❌ | ✅ | ✅ | ✅ | ✅ |
| Previous Close | ❌ | ✅ | ✅ | ✅ | ✅ |
| Indian Customs Rates | ❌ | ❌ | ✅ | ✅ | ✅ |
| RBI Reference (Latest) | ❌ | ❌ | ✅ | ✅ | ✅ |
| DXY Index | ❌ | ❌ | ✅ | ✅ | ✅ |
| RBI Reference (Historical) | ❌ | ✅ | ✅ | ✅ | ✅ |
| Forward Rate (Broken Date) | ❌ | ❌ | ❌ | Add-on | Add-on |
| Monthly Forward Rates | ❌ | ❌ | ❌ | Add-on | Add-on |
| Cash / Tom / Spot | ❌ | ❌ | ❌ | Add-on | Add-on |
| Technical Indicators | ❌ | ❌ | ❌ | ❌ | ✅ |
06Error Handling
Most responses include success. On failure, success: false plus error and (usually) details:
{
"success": false,
"error": "Monthly API limit exceeded",
"details": "Current limit: 200000, Used: 200000"
}
success field). Error responses from these endpoints still use success: false.HTTP Status Codes
| Code | Meaning |
|---|---|
200 | Success |
400 | Bad Request — invalid parameters (e.g. unsupported symbol) |
401 | Unauthorized — missing or invalid API key |
403 | Forbidden — plan doesn't include this feature, or plan expired |
404 | Not Found — data unavailable, or endpoint doesn't exist |
429 | Rate Limit Exceeded — monthly quota reached |
500 | Internal Server Error |
Common Scenarios
| Scenario | Status | Fix |
|---|---|---|
| Invalid API key | 401 | Check the key is correct, active, and in the query string |
| Plan doesn't include endpoint | 403 | Upgrade — e.g. Technical Indicators requires Ultimate |
| Free monthly quota exhausted | 429 | Free's 100 calls/month are used up — wait for next billing cycle or upgrade. No overage option on Free. |
| Monthly quota exceeded (paid) | 429 | Wait for reset, upgrade, or accept overage billing — paid plans don't hard-block. |
| Invalid symbol | 400 | Check spelling against the supported symbol list |
| Data not available | 404 | Aggregates may still be processing, or the symbol/timeframe combo isn't supported |
| WebSocket rejected on connect | socket error | Check current_plan/required_plans in the error payload |
Example Error Bodies
// Monthly quota exceeded (Free or paid) { "success": false, "error": "Monthly API limit exceeded", "details": "Monthly API limit exceeded. Current limit: 100, Used: 100" } // Feature gated by plan { "success": false, "error": "No active subscription", "details": "Technical indicators are only available with Ultimate plan. Please upgrade your subscription." } // Bad symbol { "success": false, "error": "Invalid symbol: INVALID", "availableSymbols": ["USDINR", "EURUSD", "GBPUSD"] } // WebSocket — plan too low { "type": "error", "error": "WebSocket snapshot is only available on Pro and Ultimate plans", "current_plan": "ESSENTIAL", "required_plans": ["PRO", "ULTIMATE"] }
Recommended Client Handling (REST)
try { const { data } = await axios.get(url, { params }); if ('success' in data && !data.success) throw new Error(data.error); return data; } catch (err) { if (err.response) { console.error('API error:', err.response.status, err.response.data); } else { console.error('Network error:', err.message); } throw err; }
07Code Examples
JavaScript — Aggregates
const getForexAggregates = async (symbol, time, multiply, from, to, apiKey) => { const response = await fetch( `https://api.ibrlive.com/api/aggregate/data?symbol=${symbol}&time=${time}&multiply=${multiply}&from=${from}&to=${to}&apiKey=${apiKey}` ); const data = await response.json(); if (!data.success) throw new Error(data.error); return data; };
Node.js — Previous Close
const axios = require('axios'); async function getPreviousClose(symbol, apiKey) { try { const { data } = await axios.get('https://api.ibrlive.com/api/forex/previous-close', { params: { symbol, apiKey } }); if (!data.success) throw new Error(data.error); return data.data; } catch (error) { if (error.response) { console.error('API Error:', error.response.status, error.response.data); } else { console.error('Network Error:', error.message); } throw error; } }
Python — Technical Indicators
import requests def get_technical_indicators(symbol, timeframe='daily', api_key='YOUR_API_KEY'): response = requests.get( "https://api.ibrlive.com/api/forex/get-technical-indicators", params={"symbol": symbol, "timeframe": timeframe, "apiKey": api_key} ) response.raise_for_status() data = response.json() if not data['success']: raise Exception(data['error']) return data['data']
React — Polling Snapshot (REST)
import { useState, useEffect } from 'react'; const useForexSnapshot = (apiKey, symbols = null) => { const [snapshot, setSnapshot] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { const fetchSnapshot = async () => { try { const url = symbols ? `https://api.ibrlive.com/api/forex/snapshot/symbols?symbols=${symbols.join(',')}&apiKey=${apiKey}` : `https://api.ibrlive.com/api/forex/snapshot?apiKey=${apiKey}`; const response = await fetch(url); const data = await response.json(); if (data.success) setSnapshot(data); } catch (error) { console.error('Failed to fetch snapshot:', error); } finally { setLoading(false); } }; fetchSnapshot(); const interval = setInterval(fetchSnapshot, 10000); // 10s poll, matches 3s server refresh return () => clearInterval(interval); }, [apiKey, symbols]); return { snapshot, loading }; };
JavaScript — WebSocket Streaming Snapshot
function connectSnapshotStream(apiKey, { symbols, onUpdate, onError } = {}) { const url = symbols ? `wss://api.ibrlive.com/api/forex/ws/snapshot?api_key=${apiKey}&symbols=${symbols.join(',')}` : `wss://api.ibrlive.com/api/forex/ws/snapshot?api_key=${apiKey}`; const ws = new WebSocket(url); ws.onmessage = (event) => { const msg = JSON.parse(event.data); if (msg.type === 'init' || msg.type === 'delta') onUpdate?.(msg); if (msg.type === 'error') onError?.(msg); }; ws.onclose = (e) => console.log('Snapshot stream closed', e.code, e.reason); return ws; } const ws = connectSnapshotStream(apiKey, { symbols: ['USDINR', 'EURUSD'], onUpdate: (msg) => console.log(msg.lastQuotes), onError: (msg) => console.error(msg.error) });