Trade
Public market data: list tradeable properties, fetch property detail (order book snapshot, recent trades, session volume, market hours), and paginated candle history. No authentication required.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/trade | List tradeable properties |
GET | /api/trade/:tokenName | Property market detail |
GET | /api/trade/:tokenName/candles | Paginated OHLCV candle history |
For longer-form property disclosure (header, overview, documents), see Info. For live order book and trade streams, see WebSocket.
List tradeable properties
GET /api/trade
Returns every tradeable property with market data and a trailing-24h hourly sparkline (candlesticks), plus the active payment token address. For full chart history at other resolutions, use Candle history below — the list sparkline is not a substitute.
Request
import axios from 'axios';
const response = await axios.get('https://api.loafmarkets.com/api/trade');
console.log(response.data);Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| None | - | No | No parameters for this endpoint. |
Response
interface TradeResponse {
properties: TradePropertyItem[];
paymentTokenAddress: string;
}
interface TradePropertyItem {
propertyId: number;
tokenName: string;
assetName: string;
ticker: string;
contractAddress: string | null;
streetAddress: string;
country: string;
latitude: number;
longitude: number;
propertyType: string;
status: 'PENDING' | 'LIVE' | 'DELISTED';
totalTokens: number;
headerImageUrl: string;
videoUrl: string;
marketPrice: number;
dailyReferencePrice: number | null;
volume24h: number; // session-to-date settled notional
rentalYieldPercentage: number | null;
candlesticks: Array<{
time: number;
open: number;
high: number;
low: number;
close: number;
volume: number;
}>;
}Example response:
{
"properties": [
{
"propertyId": 42,
"tokenName": "sunset-villa",
"assetName": "Sunset Villa",
"ticker": "SSV",
"contractAddress": "0xabc…",
"streetAddress": "12 Ocean Ave",
"country": "AU",
"latitude": -33.86,
"longitude": 151.21,
"propertyType": "APARTMENT",
"status": "LIVE",
"totalTokens": 10000,
"headerImageUrl": "https://cdn.example.com/header.jpg",
"videoUrl": "",
"marketPrice": 167.49,
"dailyReferencePrice": 165.0,
"volume24h": 1204.5,
"rentalYieldPercentage": 5.2,
"candlesticks": []
}
],
"paymentTokenAddress": "0xdef…"
}Errors
| Status | Code | Description |
|---|---|---|
500 | internal_error | Unexpected server error. |
Public endpoint — no API key required. volume24h is session-to-date settled notional (resets at market open), not a strict trailing 24h window.
Property market detail
GET /api/trade/:tokenName
Full market detail for one property: nested property metadata, selector list, current order book snapshot, recent trades, session volume, payment token, and market-hours metadata. Candle history is not included — fetch it from Candle history.
Request
import axios from 'axios';
const tokenName = 'sunset-villa';
const response = await axios.get(
`https://api.loafmarkets.com/api/trade/${tokenName}`,
);
console.log(response.data);Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tokenName | string | Yes | (path) Lowercase property token symbol. |
Response
interface PropertyResponse {
propertyList: Array<{
assetName: string;
tokenName: string;
ticker: string;
streetAddress: string;
suburb: string;
status: string;
}>;
property: {
propertyId: number;
tokenName: string;
assetName: string;
ticker: string;
contractAddress: string | null;
totalTokens: number;
tokensIssued: number;
rentalYieldPercentage: number | null;
streetAddress: string;
videoUrl: string;
status: 'PENDING' | 'LIVE' | 'DELISTED';
isHalted: boolean;
};
paymentTokenAddress: string;
volume24h: number;
orderBook: {
bids: Array<{ price: number; quantity: number; orderId?: number }>;
asks: Array<{ price: number; quantity: number; orderId?: number }>;
} | null;
recentTrades: Array<{
tradeId: number;
propertyId: number;
aggressorSide: 'BUY' | 'SELL';
price: number;
quantity: number;
timestamp: number;
}>;
dailyReferencePrice: number | null;
marketOpenTime: string;
marketCloseTime: string;
marketTimezone: string;
marketClosedDays: string[];
maxSlippageBps: number;
}Example response:
{
"propertyList": [
{
"assetName": "Sunset Villa",
"tokenName": "sunset-villa",
"ticker": "SSV",
"streetAddress": "12 Ocean Ave",
"suburb": "Bondi",
"status": "LIVE"
}
],
"property": {
"propertyId": 42,
"tokenName": "sunset-villa",
"assetName": "Sunset Villa",
"ticker": "SSV",
"contractAddress": "0xabc…",
"totalTokens": 10000,
"tokensIssued": 8000,
"rentalYieldPercentage": 5.2,
"streetAddress": "12 Ocean Ave",
"videoUrl": "",
"status": "LIVE",
"isHalted": false
},
"paymentTokenAddress": "0xdef…",
"volume24h": 1204.5,
"orderBook": {
"bids": [{ "price": 167.0, "quantity": 10 }],
"asks": [{ "price": 168.0, "quantity": 5 }]
},
"recentTrades": [],
"dailyReferencePrice": 165.0,
"marketOpenTime": "09:00",
"marketCloseTime": "17:00",
"marketTimezone": "Australia/Sydney",
"marketClosedDays": ["Saturday", "Sunday"],
"maxSlippageBps": 300
}Errors
| Status | Code | Description |
|---|---|---|
400 | validation_error | Invalid tokenName. |
404 | not_found | Property not found. |
500 | internal_error | Unexpected server error. |
Public endpoint — no API key required. orderBook may be null when the book is empty. For live book/fills/volume, prefer WebSocket.
Candle history
GET /api/trade/:tokenName/candles
Paginated OHLCV candle history for a property. Candles are aggregated server-side to the requested resolution.
Request
import axios from 'axios';
const tokenName = 'sunset-villa';
const response = await axios.get(
`https://api.loafmarkets.com/api/trade/${tokenName}/candles`,
{ params: { resolution: '1h', countBack: 200 } },
);
console.log(response.data.candles.at(-1)); // latest candle
// Page older: pass previous response.oldestTs as `to` while hasMore is trueParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tokenName | string | Yes | (path) Lowercase property token symbol. |
resolution | string | Yes | (query) Bucket size: 1m, 5m, 15m, 1h, 4h, 1d, or 1w. |
to | number | No | (query) Return only candles strictly older than this unix-seconds timestamp. Omit for the most recent candles. |
countBack | number | No | (query) How many candles to return (server default 1000). |
Response
interface CandleHistoryResponse {
resolution: string;
candles: Array<{
time: number;
open: number;
high: number;
low: number;
close: number;
volume: number;
}>; // oldest → newest
oldestTs: number | null;
hasMore: boolean;
}Example response:
{
"resolution": "1h",
"candles": [
{
"time": 1718000000,
"open": 165.0,
"high": 168.5,
"low": 164.2,
"close": 167.49,
"volume": 42.5
}
],
"oldestTs": 1718000000,
"hasMore": true
}Errors
| Status | Code | Description |
|---|---|---|
400 | validation_error | Invalid tokenName or resolution. |
404 | not_found | Property not found. |
500 | internal_error | Unexpected server error. |
Public endpoint — no API key required. To page backwards, pass the previous response’s oldestTs as to while hasMore is true. Live candle updates also stream on the WebSocket chart:{propertyId} channel.