GET /v1/history

Returns historical OHLCV bars for a given symbol and resolution. The response format is fully compatible with the TradingView UDF protocol.


Request

GET /v1/history

Auth: Required

Query Parameters

ParameterTypeRequiredDescription
symbolstring✅Compound key (e.g. WMMARKETS:ZERO:EURUSD)
resolutionstring✅Bar interval — see table below
frominteger—Range start, Unix epoch seconds on the feed's broker clock (see below)
tointeger—Range end, Unix epoch seconds on the feed's broker clock (see below)
countbackinteger—Number of bars to return (max: 10,000)

Resolution Values

ValueTimeframeBar Duration
1M11 minute
5M55 minutes
10M1010 minutes
15M1515 minutes
30M3030 minutes
60H11 hour
120H22 hours
240H44 hours
1DDaily1 day
1WWeekly1 week
1MMonthly1 month

Which clock are from and to on?

from and to are interpreted on the same clock the response uses — the feed's broker clock, not real UTC. This matters enormously on feeds whose broker clock is far from UTC.

Two safe approaches:

1. Use countback and omit from/to. The window is then resolved server-side against the feed's own clock, so it is correct for every feed with no arithmetic on your side. This is the recommended default.

GET /v1/history?symbol=ISE:TADIL:FMLY&resolution=1D&countback=30

2. If you need an explicit window, shift it by that feed's clock_offset_seconds from /v1/status:

feed_from = real_utc_from - clock_offset_seconds
feed_to   = real_utc_to   - clock_offset_seconds

which is the inverse of the rule for reading timestamps back (real_utc = feed_timestamp + clock_offset_seconds).


Response — Data Available

{
  "s": "ok",
  "t": [1749556800, 1749560400, 1749564000],
  "o": [1.08234, 1.08198, 1.08215],
  "h": [1.08267, 1.08241, 1.08259],
  "l": [1.08190, 1.08182, 1.08198],
  "c": [1.08198, 1.08215, 1.08241],
  "v": [1250, 980, 1100],
  "meta": {
    "symbol": "WMMARKETS:ZERO:EURUSD",
    "resolution": "60",
    "bar_count": 3
  }
}

Response — No Data

{
  "s": "no_data"
}

Response — Error

{
  "s": "error",
  "errmsg": "symbol not found"
}

Response Fields

FieldTypeDescription
sstringStatus: "ok", "no_data", or "error"
tintegerBar open times as Unix epoch seconds (oldest → newest)
ofloatOpen prices
hfloatHigh prices
lfloatLow prices
cfloatClose prices
vintegerTick volume
meta.bar_countintegerNumber of bars returned

All arrays are aligned by index — t[0], o[0], h[0], l[0], c[0], v[0] all describe the same bar.


Examples

Last 1000 H1 bars

curl -H "X-API-Key: fxd_your_key" \
  "https://api.pipdata.net/v1/history?symbol=WMMARKETS:ZERO:EURUSD&resolution=60&countback=1000"

Specific date range

import requests
from datetime import datetime, timezone

headers = {"X-API-Key": "fxd_your_key"}

# January 2025
from_ts = int(datetime(2025, 1, 1, tzinfo=timezone.utc).timestamp())
to_ts   = int(datetime(2025, 1, 31, 23, 59, 59, tzinfo=timezone.utc).timestamp())

resp = requests.get(
    "https://api.pipdata.net/v1/history",
    headers=headers,
    params={
        "symbol": "WMMARKETS:ZERO:EURUSD",
        "resolution": "60",
        "from": from_ts,
        "to": to_ts
    }
)
data = resp.json()
if data["s"] == "ok":
    first = datetime.fromtimestamp(data["t"][0], tz=timezone.utc)
    last  = datetime.fromtimestamp(data["t"][-1], tz=timezone.utc)
    print(f"{len(data['t'])} bars from {first.date()} to {last.date()}")

Convert to pandas DataFrame

import pandas as pd

if data["s"] == "ok":
    df = pd.DataFrame({
        "time":   pd.to_datetime(data["t"], unit="s", utc=True),
        "open":   data["o"],
        "high":   data["h"],
        "low":    data["l"],
        "close":  data["c"],
        "volume": data["v"]
    })
    df.set_index("time", inplace=True)
    print(df.tail())

Daily bars — last 365 days

curl -H "X-API-Key: fxd_your_key" \
  "https://api.pipdata.net/v1/history?symbol=WMMARKETS:ZERO:GBPUSD&resolution=1D&countback=365"

Important Notes


Error Codes

HTTP StatusCodeDescription
401UNAUTHORIZEDAPI key missing or invalid
403SYMBOL_NOT_PERMITTEDFeed access not allowed for this key
422INVALID_PARAMSMissing or invalid parameters
500SERVER_ERRORInternal error