Skip to main content

GET /v1/rates/historical

Returns historical OHLCV (Open, High, Low, Close, Volume) candle data for a single pair. Supports 5-minute, hourly, and daily intervals with cursor-based pagination for fetching large ranges efficiently.

Authentication

note

This endpoint requires an API key. See Authentication.

Parameters

ParameterTypeRequiredDescription
pairstringYesPair identifier (e.g., USDTNGN). See Pairs for the full list.
startstringYesStart date in YYYY-MM-DD format (inclusive).
endstringYesEnd date in YYYY-MM-DD format (inclusive). Maximum range is 5 years from start.
intervalstringNoCandle interval. One of 5m, 1h, or 1d. Default: 1h.
limitintegerNoMaximum number of candles to return per page. Must be between 1 and your tier's page cap. Defaults to your tier cap if omitted.
cursorstringNoPagination cursor returned in the previous response as next_cursor. Pass this to fetch the next page. Omit for the first page.

Tier page caps:

TierMax limit
Free500
Builder2,500
Professional5,000
Enterprise10,000

Response

FieldTypeDescription
pairstringThe requested pair.
intervalstringThe interval used for aggregation.
candlesarrayArray of OHLCV candle objects ordered chronologically.
candles[].timestampstringISO 8601 UTC timestamp marking the start of the candle period.
candles[].opennumberVWAP at the start of the period.
candles[].highnumberHighest VWAP observed during the period.
candles[].lownumberLowest VWAP observed during the period.
candles[].closenumberVWAP at the end of the period.
candles[].volumenumberTotal base volume traded across all exchanges during the period.
has_morebooleantrue if there are more candles beyond this page. Use next_cursor to fetch them.
next_cursorstringOpaque cursor to pass as the cursor parameter on the next request. Only present when has_more is true.
warningstringPresent only when data quality issues are detected, such as gaps in the requested range.

Examples

First page

curl
curl -X GET "https://api.moxiemetrx.com/v1/rates/historical?pair=USDTNGN&start=2026-01-01&end=2026-03-01&interval=1h&limit=100" \
-H "X-API-Key: your_key"
Python
import requests

response = requests.get(
"https://api.moxiemetrx.com/v1/rates/historical",
params={
"pair": "USDTNGN",
"start": "2026-01-01",
"end": "2026-03-01",
"interval": "1h",
"limit": 100,
},
headers={"X-API-Key": "your_key"},
)

data = response.json()
print(f"Returned {len(data['candles'])} candles, has_more={data['has_more']}")
JavaScript
const response = await fetch(
"https://api.moxiemetrx.com/v1/rates/historical?pair=USDTNGN&start=2026-01-01&end=2026-03-01&interval=1h&limit=100",
{ headers: { "X-API-Key": "your_key" } }
);

const data = await response.json();
console.log(`Returned ${data.candles.length} candles, has_more=${data.has_more}`);
TypeScript
interface Candle {
timestamp: string;
open: number;
high: number;
low: number;
close: number;
volume: number;
}

interface HistoricalResponse {
pair: string;
interval: string;
candles: Candle[];
has_more: boolean;
next_cursor?: string;
warning?: string;
}

const response = await fetch(
"https://api.moxiemetrx.com/v1/rates/historical?pair=USDTNGN&start=2026-01-01&end=2026-03-01&interval=1h&limit=100",
{ headers: { "X-API-Key": "your_key" } }
);

const data: HistoricalResponse = await response.json();
console.log(`Returned ${data.candles.length} candles, has_more=${data.has_more}`);

Response:

{
"pair": "USDTNGN",
"interval": "1h",
"has_more": true,
"next_cursor": "2026-01-05T04:00:00+00:00",
"candles": [
{
"timestamp": "2026-01-01T00:00:00Z",
"open": 1398.50,
"high": 1401.20,
"low": 1397.80,
"close": 1400.10,
"volume": 142580.0
},
{
"timestamp": "2026-01-01T01:00:00Z",
"open": 1400.10,
"high": 1402.00,
"low": 1399.50,
"close": 1401.30,
"volume": 98210.0
}
]
}

Fetching all pages

Python
import requests

def fetch_all_candles(pair: str, start: str, end: str, interval: str = "1h") -> list:
params = {"pair": pair, "start": start, "end": end, "interval": interval, "limit": 500}
headers = {"X-API-Key": "your_key"}
all_candles = []

while True:
response = requests.get(
"https://api.moxiemetrx.com/v1/rates/historical",
params=params,
headers=headers,
)
response.raise_for_status()
data = response.json()

all_candles.extend(data["candles"])

if not data["has_more"]:
break

params["cursor"] = data["next_cursor"]

return all_candles

candles = fetch_all_candles("USDTNGN", "2026-01-01", "2026-03-01")
print(f"Total candles: {len(candles)}")
JavaScript
async function fetchAllCandles(pair, start, end, interval = "1h") {
const allCandles = [];
let cursor = null;

while (true) {
const params = new URLSearchParams({ pair, start, end, interval, limit: 500 });
if (cursor) params.set("cursor", cursor);

const response = await fetch(
`https://api.moxiemetrx.com/v1/rates/historical?${params}`,
{ headers: { "X-API-Key": "your_key" } }
);
const data = await response.json();

allCandles.push(...data.candles);

if (!data.has_more) break;
cursor = data.next_cursor;
}

return allCandles;
}

const candles = await fetchAllCandles("USDTNGN", "2026-01-01", "2026-03-01");
console.log(`Total candles: ${candles.length}`);

Intervals

IntervalDescriptionNotes
5m5-minute candlesNative resolution. No aggregation applied.
1h1-hour candlesDefault. Aggregated from 5-minute data.
1dDaily candlesAggregated from 5-minute data. Day boundary is 00:00 UTC.

Pagination

This endpoint uses cursor-based pagination. The cursor is an ISO 8601 timestamp representing the last candle returned on the current page. Passing it as cursor on the next request returns candles strictly after that point -- so pages never overlap or skip rows.

tip

The cursor is opaque -- treat it as a string and do not parse or modify it. Its format may change.

Flow:

  1. Make the first request without cursor.
  2. If has_more is true, pass next_cursor as cursor on the next request (keep all other params identical).
  3. Repeat until has_more is false.

Errors

StatusCodeCause
400validation_errorInvalid interval, bad date format, end before start, start in the future, range > 5 years, limit out of range, invalid cursor
400validation_errorlimit exceeds your tier's page cap
401unauthorizedMissing or invalid API key
429rate_limit_exceededPer-minute or monthly quota exceeded
warning

The 5m interval returns raw data without aggregation. If an exchange was temporarily unavailable during a 5-minute window, that candle may be missing entirely. The response will include a warning field when gaps are detected.

note

Free tier accounts can only access the last 7 days of historical data. Builder, Professional, and Enterprise plans have access to the full history. See Pricing for details.