API Documentation

Everything you need to integrate PriceFeed Pro into your application.

Getting Started

1. Create an account and get your API key.

2. Include your API key in every request via the X-API-Key header.

3. Base URL: https://your-domain.com

Authentication

All API requests require an API key. Pass it as a header:

GET /api/v1/market/symbols HTTP/1.1
Host: api.example.com
X-API-Key: $PRICEFEED_API_KEY

Keep your API key on the server side only. Never expose it in client-side JavaScript or public repositories.

API keys start with pf_ and are 67 characters long.

REST API

GET/api/v1/market/symbols?search=&sector=&page=1&limit=50

List available symbols, optionally filtered by search term and sector. Paginated.

// Response
{
  "success": true,
  "data": {
    "symbols": [
      { "symbol": "XAUUSD", "display_name": "Gold", "sector": "metals", "digits": 2 },
      { "symbol": "EURUSD", "display_name": "EUR/USD", "sector": "forex", "digits": 5 }
    ],
    "total": 150,
    "page": 1,
    "limit": 50
  }
}
GET/api/v1/market/history/{symbol}?tf=60&limit=500&from=&to=

Get OHLC historical bars. Timeframes (in minutes): 1, 5, 15, 30, 60, 240, 1440, 10080, 43200. Requires Pro or Enterprise plan.

Bars are returned newest-first and capped by limit (default 500, max 5000). With only from set, the response contains the newest limit bars at or after from — page backward by setting the next to to the oldest time returned. from/to must be full RFC 3339 (e.g. 2026-02-10T00:00:00Z). There is no page= parameter on this endpoint.

// GET /api/v1/market/history/XAUUSD?tf=60&limit=5
{
  "success": true,
  "data": {
    "symbol": "XAUUSD",
    "source_id": "ORBEX-live-1",
    "timeframe": 60,
    "broker_tz": "Europe/Athens",
    "bars": [
      {
        "source_id": "ORBEX-live-1",
        "symbol": "XAUUSD",
        "timeframe": 60,
        "time": "2026-05-04T01:00:00Z",
        "broker_time": "2026-05-04T04:00:00+03:00",
        "open": 2650.5, "high": 2655.0, "low": 2648.0, "close": 2652.0,
        "volume": 123
      }
    ],
    "count": 1
  }
}
GET/api/v1/market/tick/{symbol}

Get the latest tick snapshot for a single symbol. Also available: /api/v1/market/ticks?symbols=EURUSD,GBPUSD for multiple symbols.

Each response includes broker_time (RFC 3339 with the broker's offset, e.g. 2026-05-04T04:00:00+03:00) and broker_tz (IANA zone, e.g. Europe/Athens). market_closed reflects the broker's schedule; data_stale goes true when no fresh tick has arrived for ~2 minutes and is decoupled from market_closed.

// GET /api/v1/market/tick/XAUUSD
{
  "success": true,
  "data": {
    "symbol": "XAUUSD",
    "source": "ORBEX-live-1",
    "bid": "2654.21",
    "ask": "2654.45",
    "high": "2660.10",
    "low": "2649.80",
    "spread": 24,
    "trade_mode": 4,
    "time": "2026-05-04T01:00:00Z",
    "broker_time": "2026-05-04T04:00:00+03:00",
    "broker_tz": "Europe/Athens",
    "market_closed": false,
    "data_stale": false,
    "trading_hours": "Sun:;Mon:00:02-23:59;..."
  }
}
GET/api/v1/account/profile

Get your subscriber profile, subscription details, and usage stats. Requires JWT Bearer token (not API key).

WebSocket Streaming

Connect via native WebSocket to receive real-time price ticks and OHLC bars.

Connection URL: wss://your-host/ws/v1/stream?api_key=YOUR_API_KEY

Authentication is done via the api_key query parameter during the initial connection.

JavaScript (Node.js / Browser)

// Load API key from environment variable — never hardcode it
const ws = new WebSocket(
  "wss://api.example.com/ws/v1/stream?api_key=" + process.env.PRICEFEED_API_KEY
);

ws.onopen = () => {
  // Subscribe to tick data
  ws.send(JSON.stringify({
    action: "subscribe",
    symbols: ["XAUUSD", "EURUSD"]
  }));

  // Subscribe to OHLC bars (optional)
  ws.send(JSON.stringify({
    action: "subscribe_bars",
    symbols: ["XAUUSD"],
    timeframes: [1, 5, 60]
  }));
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  switch (msg.type) {
    case "connected":
      console.log("Plan:", msg.plan, "Sources:", msg.sources);
      break;
    case "tick":
      // msg fields: symbol, source, bid, ask, high, low, spread, trade_mode,
      // time (UTC), broker_time (RFC 3339 + offset), broker_tz, market_closed,
      // data_stale (true when no fresh tick in ~2 min), trading_hours.
      console.log(msg.symbol, msg.bid, msg.ask, "spread:", msg.spread,
        msg.data_stale ? "(stale)" : "");
      break;
    case "error":
      console.error(msg.code + ":", msg.message);
      break;
  }
};

// Unsubscribe
ws.send(JSON.stringify({
  action: "unsubscribe",
  symbols: ["EURUSD"]
}));

Python

import os
import asyncio
import websockets
import json

async def connect():
    # Load API key from environment variable — never hardcode it
    api_key = os.environ["PRICEFEED_API_KEY"]
    uri = f"wss://api.example.com/ws/v1/stream?api_key={api_key}"

    async with websockets.connect(uri) as ws:
        # Subscribe to tick data
        await ws.send(json.dumps({
            "action": "subscribe",
            "symbols": ["XAUUSD", "EURUSD"]
        }))

        # Listen for messages
        async for message in ws:
            data = json.loads(message)
            if data["type"] == "connected":
                print(f"Connected - Plan: {data['plan']}")
            elif data["type"] == "tick":
                # Each tick also carries broker_time, broker_tz, market_closed,
                # data_stale (True when no fresh tick in ~2 min), trading_hours.
                stale = " (stale)" if data.get("data_stale") else ""
                print(f"{data['symbol']}: {data['bid']}/{data['ask']} spread={data['spread']}{stale}")
            elif data["type"] == "error":
                print(f"Error [{data['code']}]: {data['message']}")

asyncio.run(connect())

Rate Limits

TierRequests/minMax Symbols
Free105
Basic6020
Pro300100
Enterprise9,999Unlimited

Exceeding limits returns 429 Too Many Requests with a Retry-After header.

Error Codes

CodeStatusDescription
MISSING_API_KEY401No API key provided
INVALID_API_KEY401API key is invalid or inactive
API_KEY_REVOKED401API key has been revoked
ACCOUNT_INACTIVE403Subscriber account is inactive
TRIAL_EXPIRED403Free trial has expired, please upgrade
CONNECTION_LIMIT429Maximum WebSocket connections exceeded for your plan
SYMBOL_LIMITWSMaximum symbol subscriptions exceeded for your plan
RATE_LIMIT_EXCEEDED429Too many requests for your plan
RATE_LIMITED429Too many failed auth attempts (15 min lockout)