---
name: realmarketapi-integration
description: Integrate Real Market API (realmarketapi.com) into an application — REST, WebSocket, SDKs or MCP — for live and historical forex, crypto, metals, stock, index and commodity prices, candles and technical indicators. Use when a user asks to add market data, live prices, candles, indicators or a price feed using Real Market API.
version: 1.0.0
source: https://realmarketapi.com/guide.md
---

# Real Market API integration guide

You are helping a developer add Real Market API to their project. Follow this guide instead of guessing:
the API has a few conventions (API key in the query string, camelCase params, plan-gated features) that
generic "market data API" code gets wrong.

Canonical references, if something here is unclear or seems out of date:
- OpenAPI 3 spec (every public REST route, param and schema): https://realmarketapi.com/.well-known/openapi.json
- Extended LLM reference: https://realmarketapi.com/llms-full.txt
- Human docs: https://realmarketapi.com/en-US/docs

## 1. Before writing code

1. Look at the project: language, framework, where secrets live (`.env`, appsettings, secret manager), and
   whether the code runs on a server or in the browser.
2. Ask the user for anything you cannot infer:
   - Which symbols (e.g. `XAUUSD`, `BTCUSD`, `EURUSD`) and timeframes they need.
   - Their plan, if they know it (it decides which endpoints and timeframes work, see section 7).
   - Polling once in a while (REST) or live updates (WebSocket)?
3. The user needs an API key from https://realmarketapi.com/en-US/register (Free plan, no card). Never invent
   a key, and never paste a real key into source code, docs, tests or chat output.

## 2. Golden rules

- **Base URL:** `https://api.realmarketapi.com`. REST routes are `/api/v1/<route>`.
- **Auth:** the key goes in the `apiKey` **query parameter**, not a header:
  `GET https://api.realmarketapi.com/api/v1/price?apiKey=KEY&symbolCode=XAUUSD&timeFrame=M1`
- **Params are camelCase and case-sensitive:** `symbolCode`, `timeFrame`, `period`, `startTime`, `endTime`,
  `pageNumber`, `pageSize`.
- **Responses are camelCase JSON.** Prices are decimals: parse them as numbers, keep full precision, and
  format only for display.
- **Times are UTC ISO 8601** (`2026-02-01T00:00:00Z`).
- **Timeframes:** `M1`, `M5`, `M15`, `H1`, `H4`, `D1`.
- **Keep the key server-side.** Because it travels in the URL, a key used from browser JavaScript is visible to
  every visitor. In web apps, call the API from your backend (or a serverless function) and expose your own
  endpoint to the frontend. Load the key from an environment variable such as `REALMARKETAPI_API_KEY`.
- **Don't log full request URLs** in production: they contain the key. Redact `apiKey=...` if you must.
- **Cache and batch.** Every REST call counts against the monthly quota. Prefer one `/price/market` call over
  a loop of `/price` calls, cache responses for at least a few seconds, and use WebSocket for live updates.

## 3. Response shapes

Single object, e.g. `GET /api/v1/price`:

```json
{
  "symbolCode": "XAUUSD",
  "openPrice": 2348.12,
  "highPrice": 2354.0,
  "lowPrice": 2346.1,
  "closePrice": 2351.84,
  "volume": 1284.47,
  "openTime": "2026-03-08T09:20:00Z",
  "bid": 2351.7,
  "ask": 2352.3
}
```

List: `{ "data": [ ... ], "totalCount": 42 }` — candles, indicators, symbols, market snapshots.

Paged (`/history`): `{ "data": [ ... ], "totalCount": 1200, "currentPage": 1, "totalPages": 60, "pageSize": 20 }`.

Errors are `application/problem+json`:

```json
{
  "statusCode": 400,
  "message": "...",
  "errors": [{ "propertyName": "apiKey", "errorCode": "ERR_0005_INVALID_API_KEY", "errorMessage": "..." }],
  "traceId": "..."
}
```

Branch on `errors[].errorCode`, not on the message text:

| errorCode | Meaning | What the code should do |
|---|---|---|
| `ERR_0005_INVALID_API_KEY` | Key missing, wrong or revoked | Stop; surface a configuration error. Don't retry. |
| `ERR_0012_EMAIL_NOT_VERIFIED` | Account email not verified | Stop; tell the user to verify their email. |
| `ERR_0014_INVALID_PLAN` | Endpoint not included in the plan | Stop; feature-flag it off or tell the user to upgrade. |
| `ERR_0007_INVALID_TIME_FRAME` | Timeframe not on the plan | Use a timeframe from `/api/v1/me`. |
| `ERR_0008_SYMBOL_NOT_SUPPORTED` | Symbol unknown or not on the plan | Check `/api/v1/symbol` and `/api/v1/me`. |
| `ERR_0001_DATA_NOT_FOUND` | No data for the request (e.g. empty range) | Treat as empty, not as a crash. |
| `ERR_0017_REQUEST_QUOTA_EXCEEDED` (HTTP 429) | Monthly quota used up | Back off; don't retry in a loop. |

Retry only network errors and HTTP 5xx, with exponential backoff and jitter (e.g. 1s, 2s, 4s, max ~30s).

## 4. Endpoint map

All routes take `apiKey`. Most also take `symbolCode` and `timeFrame`.

**Start here**
- `GET /api/v1/me` — the key's plan: `planCode`, `requestCount`, `requestLimit`, `symbols`, `timeframes`,
  `isSocketSupport`, `webSocketConcurrentLimit`, `historicalRangeMonth`. Call it once at startup to validate
  the key and learn what's allowed. It does not consume quota.
- `GET /api/v1/symbol` — every supported symbol: `{ data: [{ symbolCode, displayName, marketClass }] }`.

**Prices and candles**
- `GET /api/v1/price?symbolCode=&timeFrame=` — latest candle with bid/ask.
- `GET /api/v1/candle?symbolCode=&timeFrame=` — recent candles.
- `GET /api/v1/history?symbolCode=&startTime=&endTime=&pageNumber=&pageSize=` — historical candles, paged
  (`pageSize` max 1000). Lookback depends on the plan. Loop over `totalPages` for bulk downloads.
- `GET /api/v1/price/market` — latest candle for every symbol on the plan, in one call.
- `GET /api/v1/price/category?category=` — one category (Forex, Crypto, Stock, Index, Commodity, ...).
- `GET /api/v1/price/24hr` — 24h open/high/low/volume/`changePercent24h` for every symbol on the plan.

**Indicators** (Pro and above), all returning `{ data: [{ openTime, ... }], totalCount }`
- `/api/v1/indicator/sma|ema|wma|rsi|atr|cci|williams-r|adx?period=`
- `/api/v1/indicator/macd?fastPeriod=12&slowPeriod=26&signalPeriod=9`
- `/api/v1/indicator/bollinger-bands?period=20&multiplier=2`
- `/api/v1/indicator/stochastic?kPeriod=14&dPeriod=3`
- `/api/v1/indicator/fibonacci?lookback=100`, `/support-resistance`, `/sentiment`

**Volatility** (Starter and above): `/api/v1/volatility`, `/volatility/spikes`, `/volatility/heatmap`.

**Insight and market structure** (Pro and above): `/api/v1/insight/score|trend|setup|next|confluence`,
`/api/v1/multi-timeframe?symbolCode=`, `/orderflow/imbalance`, `/liquidity/zones`, `/stop-hunt/zones`,
`/anomaly`, `/manipulation-risk`.

**Modules**: `POST /api/v1/screener/query`, `GET /api/v1/signals/strategy`, alerts (`GET|POST /api/v1/alerts`,
`DELETE /api/v1/alerts/{alertId}`), watchlists (`GET|POST /api/v1/watchlists`,
`POST /api/v1/watchlists/{id}/items`, `DELETE /api/v1/watchlists/{id}/items/{symbolCode}`). Write calls take an
`idempotencyKey` in the body: generate a UUID per logical action and reuse it on retry.

Exact parameters and schemas: https://realmarketapi.com/.well-known/openapi.json

## 5. Quick start by stack

Prefer the official SDK when the project's language has one; otherwise use plain HTTP.

**curl**

```bash
curl "https://api.realmarketapi.com/api/v1/price?apiKey=$REALMARKETAPI_API_KEY&symbolCode=XAUUSD&timeFrame=M1"
```

**.NET** — `dotnet add package RealMarketAPI.Sdk` (most complete SDK)

```csharp
using RealTimeMarketAPI.Sdk.Extensions;

builder.Services.AddRealMarketApiClient(o => o.ApiKey = builder.Configuration["RealMarketApi:ApiKey"]!);

// then inject IRealMarketApiClient
var price = await client.Ticker.GetPriceAsync("XAUUSD", "M1");
var rsi = await client.Indicators.GetRsiAsync("XAUUSD", "H1", period: 14);
```

**JavaScript / TypeScript** — `npm install realmarketapi-js-sdk-beta@beta` (Node.js 20+), or plain `fetch`:

```ts
const BASE = "https://api.realmarketapi.com/api/v1"

export async function getPrice(symbolCode: string, timeFrame = "M1") {
  const url = new URL(`${BASE}/price`)
  url.search = new URLSearchParams({ apiKey: process.env.REALMARKETAPI_API_KEY!, symbolCode, timeFrame }).toString()
  const res = await fetch(url)
  if (!res.ok) {
    const problem = await res.json().catch(() => null)
    throw new Error(problem?.errors?.[0]?.errorCode ?? `HTTP ${res.status}`)
  }
  return (await res.json()) as { symbolCode: string; closePrice: number; bid: number; ask: number; openTime: string }
}
```

**Python** — `pip install realmarketapi-python-sdk-beta` (Python 3.9+), or `httpx`:

```python
import os, httpx

BASE = "https://api.realmarketapi.com/api/v1"

def get_price(symbol_code: str, time_frame: str = "M1") -> dict:
    params = {"apiKey": os.environ["REALMARKETAPI_API_KEY"], "symbolCode": symbol_code, "timeFrame": time_frame}
    r = httpx.get(f"{BASE}/price", params=params, timeout=10)
    if r.is_error:
        codes = [e.get("errorCode") for e in (r.json().get("errors") or [])] if r.content else []
        raise RuntimeError(codes[0] if codes else f"HTTP {r.status_code}")
    return r.json()
```

Other languages (Go, PHP, Java, Rust, ...): plain HTTPS GET with query parameters, JSON decoding into types that
mirror the shapes in section 3.

## 6. Live data over WebSocket (Plus and above)

Routes have **no** `/api/v1` prefix:

```
wss://api.realmarketapi.com/price?apiKey=KEY&symbolCode=XAUUSD&timeFrame=M1
```

| Route | Pushes |
|---|---|
| `/price` | Latest candle with bid/ask for one symbol, on every update |
| `/candles` | Up to 100 recent candles for one symbol, newest first |
| `/market` | Latest candles for every symbol on the plan |
| `/multi-timeframe` | Trend per timeframe for one symbol (Pro and above) |
| `/orderflow/imbalance` | Orderflow imbalance for one symbol (Pro and above) |

Each message is one JSON payload. Production checklist:
- Reconnect on close/error with exponential backoff and jitter; reset the backoff after a stable connection.
- Treat a long silence as a dead socket: if nothing arrives for ~60s, close and reconnect.
- Respect the plan's concurrent-connection limit (`webSocketConcurrentLimit` from `/me`): share one connection
  per symbol across your app instead of opening one per user or component.
- Close sockets on shutdown/unmount.
- Run sockets on the server and fan out to your clients if the key must stay secret (section 2).

```ts
import WebSocket from "ws"

function connect(symbolCode: string, onPrice: (p: unknown) => void, attempt = 0) {
  const url = `wss://api.realmarketapi.com/price?apiKey=${encodeURIComponent(process.env.REALMARKETAPI_API_KEY!)}&symbolCode=${symbolCode}&timeFrame=M1`
  const ws = new WebSocket(url)
  ws.on("open", () => (attempt = 0))
  ws.on("message", (data) => onPrice(JSON.parse(data.toString())))
  ws.on("close", () => {
    const delay = Math.min(30_000, 1000 * 2 ** attempt) + Math.random() * 500
    setTimeout(() => connect(symbolCode, onPrice, attempt + 1), delay)
  })
  ws.on("error", () => ws.close())
}
```

## 7. Plans and gating

| Plan | Requests/mo | History | WebSocket | Indicators, Insight, MCP |
|---|---|---|---|---|
| Free | 5,000 | none | no | no |
| Starter | 20,000 | 30 days | no | no (Volatility yes) |
| Plus | 75,000 | 3 months | yes (10 concurrent) | no |
| Pro | 200,000 | 1 year | yes (100) | yes |
| Business | 1,000,000 | up to 10 years | yes (300) | yes |
| Enterprise | custom | custom | custom | yes |

Free plan: timeframes M1, M5, H1 and symbols XAUUSD, XAGUSD, BTCUSD, ETHUSD, EURUSD, GOOGL.
Limits change; the live source is https://realmarketapi.com/en-US/pricing and, for a given key, `GET /api/v1/me`.

Design for gating: read `/me` once, hide or disable features the plan doesn't include, and handle
`ERR_0014_INVALID_PLAN` gracefully instead of crashing.

## 8. AI agents: MCP server (Pro and above)

For agents that should *query* market data (rather than code that calls the API), connect the MCP server:

```json
{
  "mcpServers": {
    "realmarketapi": { "url": "https://ai.realmarketapi.com/mcp?apiKey=YOUR_API_KEY" }
  }
}
```

Transport: Streamable HTTP. Tools include `get_price`, `get_candles`, `get_history`, `get_sma`, `get_rsi`,
`get_macd`, `get_volatility`, `get_insight_score`, `get_multi_timeframe` and more (33 total).
Analysis skills for agents: https://realmarketapi.com/en-US/docs/skills

## 9. Definition of done

- [ ] Key read from config/env; nothing secret committed; `.env.example` (or equivalent) documents the variable.
- [ ] Key used only server-side (or the user explicitly accepted the exposure for a private tool).
- [ ] Startup or health check calls `/api/v1/me` and reports a clear error for an invalid key.
- [ ] Errors parsed from `errors[].errorCode`; no retries on 4xx; backoff on 5xx/network errors.
- [ ] REST responses cached/batched; live views use WebSocket with reconnect.
- [ ] Features outside the user's plan are hidden or degrade gracefully.
- [ ] Tests mock the HTTP layer; no test hits the real API with a real key.
- [ ] Market data shown to end users carries a note that it is informational, not investment advice.

When done, summarise for the user: what was added, which endpoints/streams are used, the env var to set, and
how many requests per hour the integration makes at its default settings.
