Get Trades List
POST https://trade-uk.sandbox.zodiamarkets.com/api/3/trades
List Trades
Section titled “List Trades”Retrieve a list of executed trades with optional filtering. Returns a single record for each trade, whilst the transaction endpoint returns a separate record for each leg of the trade.
Trade States
Section titled “Trade States”Trades progress through various states from execution to settlement:
| State | Description |
|---|---|
PENDING_SETTLEMENT |
Trade executed, awaiting settlement |
PROCESSED |
Trade fully settled |
CANCELLED |
Trade cancelled or rejected before settlement |
Trade Classes
Section titled “Trade Classes”| Class | Description |
|---|---|
OTC |
Over-the-counter trades executed via Zodia Markets trading desk |
RFS |
Request for Stream trades executed via e-Trader or WebSocket API |
Key Difference:
- RFS trades include a
quoteIdfield (from the WebSocket price stream) - OTC trades have no
quoteId
Pagination
Section titled “Pagination”Use max (1-200) and offset parameters to paginate through large result sets.
Example: Retrieve All Trades
Section titled “Example: Retrieve All Trades”def get_all_trades(filters=None): """Retrieve all trades matching filters""" all_trades = [] offset = 0 max_per_page = 200
if filters is None: filters = {}
while True: body = { **filters, 'max': max_per_page, 'offset': offset }
response = make_api_request('POST', 'api/3/trades', body)
trades = response['data'] all_trades.extend(trades)
# Stop if we got fewer results than requested if len(trades) < max_per_page: break
offset += max_per_page
return all_tradesCode Examples
Section titled “Code Examples”Python
Section titled “Python”import jsonimport hmacimport hashlibimport timeimport requestsfrom datetime import datetime, timedelta
# Configurationapi_key = "your_api_key"api_secret = "your_api_secret"base_url = "https://trade-uk.sandbox.zodiamarkets.com"
# Request body - Get trades from last 7 daystoday = datetime.utcnow()week_ago = today - timedelta(days=7)
# Every signed request must carry a nonce or toncetonce = str(int(time.time() * 1000000))
body = { "tonce": tonce, "from": week_ago.strftime("%Y-%m-%dT%H:%M:%SZ"), "to": today.strftime("%Y-%m-%dT%H:%M:%SZ"), "tradeState": "PENDING_SETTLEMENT", "max": 50, "offset": 0}body_json = json.dumps(body)
# Generate signaturepath = "api/3/trades"message = f"{path}\0{body_json}"signature = hmac.new( api_secret.encode(), message.encode(), hashlib.sha512).hexdigest()
# Make requestheaders = { "Rest-Key": api_key, "Rest-Sign": signature, "Content-Type": "application/json"}
response = requests.post( f"{base_url}/{path}", headers=headers, data=body_json)
# Process responseif response.status_code == 200: data = response.json() print(f"Found {data['total']} trades")
for trade in data['data']: print(f"\nTrade: {trade['tradeRef']}") print(f" Client Ref: {trade['clientRef']}") print(f" Class: {trade['tradeClass']}") print(f" Side: {trade['tradeSide']}") print(f" State: {trade['tradeState']}") print(f" Traded: {trade['tradedAmount']['amount']} {trade['tradedAmount']['currency']}") print(f" Settlement: {trade['settlementAmount']['amount']} {trade['settlementAmount']['currency']}") print(f" Price: {trade['executedPrice']}") print(f" Settlement Date: {trade['settlementDate']}")
if trade.get('quoteId'): print(f" Quote ID: {trade['quoteId'][:50]}...")
if trade['beneficiary']: print(f" Third-party: {trade['beneficiary']['name']}")else: print(f"Error: {response.status_code}") print(response.text)JavaScript (Node.js)
Section titled “JavaScript (Node.js)”const crypto = require('crypto');const axios = require('axios');
// Configurationconst apiKey = 'your_api_key';const apiSecret = 'your_api_secret';const baseUrl = 'https://trade-uk.sandbox.zodiamarkets.com';
// Request body - Get trades from last 7 daysconst today = new Date();const weekAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);
// Every signed request must carry a nonce or tonceconst tonce = Date.now() * 1000;
const body = { tonce, from: weekAgo.toISOString(), to: today.toISOString(), tradeState: 'PENDING_SETTLEMENT', max: 50, offset: 0};const bodyJson = JSON.stringify(body);
// Generate signatureconst path = 'api/3/trades';const message = `${path}\0${bodyJson}`;const signature = crypto .createHmac('sha512', apiSecret) .update(message) .digest('hex');
// Make requestconst headers = { 'Rest-Key': apiKey, 'Rest-Sign': signature, 'Content-Type': 'application/json'};
axios.post(`${baseUrl}/${path}`, body, { headers }) .then(response => { console.log(`Found ${response.data.total} trades`);
response.data.data.forEach(trade => { console.log(`\nTrade: ${trade.tradeRef}`); console.log(` Client Ref: ${trade.clientRef}`); console.log(` Class: ${trade.tradeClass}`); console.log(` Side: ${trade.tradeSide}`); console.log(` State: ${trade.tradeState}`); console.log(` Traded: ${trade.tradedAmount.amount} ${trade.tradedAmount.currency}`); console.log(` Settlement: ${trade.settlementAmount.amount} ${trade.settlementAmount.currency}`); console.log(` Price: ${trade.executedPrice}`); console.log(` Settlement Date: ${trade.settlementDate}`);
if (trade.quoteId) { console.log(` Quote ID: ${trade.quoteId.substring(0, 50)}...`); }
if (trade.beneficiary) { console.log(` Third-party: ${trade.beneficiary.name}`); } }); }) .catch(error => { console.error('Error:', error.response?.status); console.error(error.response?.data); });curl -X POST https://trade-uk.sandbox.zodiamarkets.com/api/3/trades \ -H "Rest-Key: your_api_key" \ -H "Rest-Sign: your_hmac_signature" \ -H "Content-Type: application/json" \ -d '{ "tonce": 1770888183656000, "from": "2026-04-01T00:00:00Z", "to": "2026-04-30T23:59:59Z", "tradeState": "PENDING_SETTLEMENT", "max": 50, "offset": 0 }'Common Use Cases
Section titled “Common Use Cases”Get Recent Trades
Section titled “Get Recent Trades”from datetime import datetime, timedelta
def get_recent_trades(days=7): """Get trades from the last N days""" today = datetime.utcnow() start_date = today - timedelta(days=days)
body = { 'from': start_date.strftime('%Y-%m-%dT%H:%M:%SZ'), 'to': today.strftime('%Y-%m-%dT%H:%M:%SZ') }
response = make_api_request('POST', 'api/3/trades', body) return response['data']
trades = get_recent_trades(7)print(f"Found {len(trades)} trades in the last 7 days")Get Pending Settlements
Section titled “Get Pending Settlements”def get_pending_settlements(): """Get all trades pending settlement""" body = { 'tradeState': 'PENDING_SETTLEMENT' }
response = make_api_request('POST', 'api/3/trades', body) return response['data']
pending = get_pending_settlements()for trade in pending: print(f"{trade['tradeRef']}: {trade['settlementDate']}")Get Trades by Account Group
Section titled “Get Trades by Account Group”def get_trades_by_account_group(account_group_uuid): """Get trades for specific account group""" body = { 'accountGroupUuid': account_group_uuid }
response = make_api_request('POST', 'api/3/trades', body) return response['data']
trades = get_trades_by_account_group('2073252c-81ed-41be-bf4d-d51b8f2246b8')Find Trade by Reference
Section titled “Find Trade by Reference”def find_trade_by_ref(trade_ref): """Find specific trade by trade reference""" body = { 'tradeRef': trade_ref }
response = make_api_request('POST', 'api/3/trades', body)
if response['data']: return response['data'][0] return None
trade = find_trade_by_ref('f4a964ad27074a9780b5010b3514d2e0')if trade: print(f"Found trade: {trade['tradeState']}")Find Trade by Client Reference
Section titled “Find Trade by Client Reference”def find_trade_by_client_ref(client_ref): """Find trade by your custom client reference""" body = { 'clientRef': client_ref }
response = make_api_request('POST', 'api/3/trades', body)
if response['data']: return response['data'][0] return None
trade = find_trade_by_client_ref('8305ec3c-83a3-490c-aab5-4748d7436ad8')if trade: print(f"Found trade: {trade['tradeRef']}")Get RFS Trades with Quote IDs
Section titled “Get RFS Trades with Quote IDs”def get_rfs_trades(): """Get all RFS trades (includes quote IDs)""" body = { 'tradeClass': 'RFS' }
response = make_api_request('POST', 'api/3/trades', body) return response['data']
rfs_trades = get_rfs_trades()for trade in rfs_trades: print(f"Trade: {trade['tradeRef']}") if trade.get('quoteId'): print(f" Quote ID: {trade['quoteId'][:50]}...")Get Third-Party Settlement Trades
Section titled “Get Third-Party Settlement Trades”def get_third_party_trades(): """Get all trades with third-party settlement""" response = make_api_request('POST', 'api/3/trades', {})
third_party = [ t for t in response['data'] if t['beneficiary'] is not None ]
return third_party
trades = get_third_party_trades()for trade in trades: print(f"{trade['tradeRef']}: {trade['beneficiary']['name']}")Calculate Total Volume by Currency
Section titled “Calculate Total Volume by Currency”from collections import defaultdict
def calculate_volume_by_currency(): """Calculate total traded volume by currency""" response = make_api_request('POST', 'api/3/trades', {})
volume = defaultdict(float)
for trade in response['data']: currency = trade['tradedAmount']['currency'] amount = trade['tradedAmount']['amount'] volume[currency] += amount
return dict(volume)
volumes = calculate_volume_by_currency()for currency, total in volumes.items(): print(f"{currency}: {total:,.2f}")Get Trades for Specific Day
Section titled “Get Trades for Specific Day”def get_trades_for_date(date_str): """Get all trades for a specific date (YYYY-MM-DD)""" from_time = f"{date_str}T00:00:00Z" to_time = f"{date_str}T23:59:59Z"
body = { 'from': from_time, 'to': to_time }
response = make_api_request('POST', 'api/3/trades', body) return response['data']
trades = get_trades_for_date('2026-04-20')print(f"Trades on 2026-04-20: {len(trades)}")Reconcile Trades with Client References
Section titled “Reconcile Trades with Client References”def reconcile_trades(client_refs): """Check which client references have completed trades""" completed = [] missing = []
for client_ref in client_refs: body = {'clientRef': client_ref} response = make_api_request('POST', 'api/3/trades', body)
if response['data']: trade = response['data'][0] completed.append({ 'clientRef': client_ref, 'tradeRef': trade['tradeRef'], 'tradeState': trade['tradeState'] }) else: missing.append(client_ref)
return completed, missing
# Usagemy_refs = [ '8305ec3c-83a3-490c-aab5-4748d7436ad8', 'other-client-ref-123']completed, missing = reconcile_trades(my_refs)
print(f"Completed: {len(completed)}")print(f"Missing: {len(missing)}")Date Range Filtering
Section titled “Date Range Filtering”ISO 8601 Format
Section titled “ISO 8601 Format”Use ISO 8601 format for from and to parameters:
Format: YYYY-MM-DDTHH:MM:SSZ
Examples:
2026-04-20T00:00:00Z- Start of day (UTC)2026-04-20T23:59:59Z- End of day (UTC)2026-04-20T10:25:35Z- Specific time (UTC)
Common Date Ranges
Section titled “Common Date Ranges”Today’s trades:
{ "from": "2026-04-20T00:00:00Z", "to": "2026-04-20T23:59:59Z"}Last 30 days:
{ "from": "2026-03-21T00:00:00Z", "to": "2026-04-20T23:59:59Z"}Specific month:
{ "from": "2026-04-01T00:00:00Z", "to": "2026-04-30T23:59:59Z"}Best Practices
Section titled “Best Practices”Always Use Pagination for Large Datasets
Section titled “Always Use Pagination for Large Datasets”# Good - Paginated requestdef get_all_trades_paginated(): all_trades = [] offset = 0
while True: response = make_api_request('POST', 'api/3/trades', { 'max': 200, 'offset': offset })
trades = response['data'] all_trades.extend(trades)
if len(trades) < 200: break
offset += 200
return all_trades
# Bad - Requesting without paginationresponse = make_api_request('POST', 'api/3/trades', {})# May timeout or return incomplete dataFilter at API Level, Not Client Side
Section titled “Filter at API Level, Not Client Side”# Good - Filter with API parametersresponse = make_api_request('POST', 'api/3/trades', { 'tradeState': 'PENDING_SETTLEMENT', 'tradeClass': 'RFS'})
# Bad - Fetch all and filter locallyall_trades = make_api_request('POST', 'api/3/trades', {})filtered = [t for t in all_trades['data'] if t['tradeState'] == 'PENDING_SETTLEMENT']# Wastes bandwidth and timeUse Specific Date Ranges
Section titled “Use Specific Date Ranges”# Good - Specific date rangebody = { 'from': '2026-04-01T00:00:00Z', 'to': '2026-04-30T23:59:59Z'}
# Bad - Fetching all trades without date filterbody = {} # Returns all trades ever - slow!Use Client References for Tracking
Section titled “Use Client References for Tracking”# Good - Provide client reference when executing ordersorder = { 'messageType': 'order', 'quoteId': quote_id, 'tradeSide': 'BUY', 'clientRequestId': 'ORDER-123', # This becomes clientRef ...}
# Later, easily retrieve your tradetrade = find_trade_by_client_ref('ORDER-123')Related Documentation
Section titled “Related Documentation”- Order Execution - Execute trades via WebSocket (clientRequestId becomes clientRef)
- Beneficiaries - Manage third-party settlement beneficiaries
- Account Groups - Understanding account structure
Domain: Trading
Request
Section titled “Request”POST https://trade-uk.sandbox.zodiamarkets.com/api/3/tradesHeaders
Section titled “Headers”| Header | Required | Description |
|---|---|---|
Rest-Key |
API key for authentication | |
Rest-Sign |
Calculated API Signature |
| Field | Type | Required | Description |
|---|---|---|---|
tonce |
integer (int64) | yes | The current Unix time in microseconds. |
nonce |
integer (int64) | Alternative to tonce. Every request must carry either nonce or tonce, and the value must parse as a whole number; a request with neither is rejected with INVALID_NONCE_OR_TONCE. |
|
tradeRef |
string | Filter by Zodia Markets trade reference | |
clientRef |
string | Filter by your custom client reference | |
tradeState |
string (enum) | Filter by trade state — One of: CANCELLED, PROCESSED, PENDING_SETTLEMENT | |
tradeSide |
string (enum) | Filter by trade side — One of: BUY, SELL | |
tradeClass |
string (enum) | Filter by trade class — One of: OTC, RFS | |
from |
string (date-time) | Start date/time filter (ISO 8601 format) for createdAt |
|
to |
string (date-time) | End date/time filter (ISO 8601 format) for createdAt |
|
accountGroupUuid |
string (uuid) | Filter by specific account group UUID | |
sortDirection |
string (enum) | Sort direction applied to the trade ordering — One of: ASC, DESC — Default: “DESC” | |
max |
integer (int32) | Maximum results to return (1-200) — Default: 50 | |
offset |
integer (int32) | Offset for pagination — Default: 0 | |
userUuid |
string | Master API keys only: UUID of the user to act on behalf of. Ignored unless the calling key belongs to the owner of a master-API-enabled site. |
Responses
Section titled “Responses”Trade list
Section titled “Trade list”| Field | Type | Required | Description |
|---|---|---|---|
data |
array of object | Array of trade objects | |
data[].uuid |
string (uuid) | Unique trade identifier | |
data[].createdAt |
string (date-time) | Trade creation timestamp (ISO 8601) | |
data[].updatedAt |
string (date-time) | Last update timestamp (ISO 8601) | |
data[].tradeRef |
string | Zodia Markets trade reference | |
data[].clientRef |
string | Your custom client reference (if provided during RFS trade execution) | |
data[].tradeSide |
string (enum) | BUY or SELL from your perspective — One of: BUY, SELL |
|
data[].settlementAmount |
object | Amount to be settled (what you pay/receive) | |
data[].settlementAmount.amount |
number | Amount value | |
data[].settlementAmount.currency |
string | Currency code (ISO 4217 for fiat, asset symbol for crypto) | |
data[].tradedAmount |
object | Amount traded (what you buy/sell) | |
data[].tradedAmount.amount |
number | Amount value | |
data[].tradedAmount.currency |
string | Currency code (ISO 4217 for fiat, asset symbol for crypto) | |
data[].user |
string | User Account shortcode | |
data[].accountGroup |
object | Account group information | |
data[].accountGroup.uuid |
string (uuid) | Account group UUID | |
data[].accountGroup.name |
string | Account group name | |
data[].tradeClass |
string (enum) | Trade classification: OTC or RFS — One of: OTC, RFS |
|
data[].tradeState |
string (enum) | Current trade state — One of: CANCELLED, PROCESSED, PENDING_SETTLEMENT | |
data[].settlementDate |
string (date) | Expected settlement date (YYYY-MM-DD) | |
data[].quoteId |
string | Quote ID from price stream (for RFS trades, not present for OTC) | |
data[].beneficiary |
object | Third-party beneficiary details (not present for standard settlement) | |
data[].beneficiary.uuid |
string (uuid) | Beneficiary UUID | |
data[].beneficiary.name |
string | Beneficiary name | |
data[].sender |
object | Third-party sender details (not present for standard settlement) | |
data[].sender.uuid |
string (uuid) | Sender UUID | |
data[].sender.name |
string | Sender name | |
data[].networkId |
string | Settlement network identifier (not present for standard settlement) | |
data[].executedPrice |
string | Execution price with currency pair | |
data[].paymentReason |
string | Payment Reason for third party receipt/delivery trades | |
total |
integer | Total number of trades matching the filter criteria |
Error — returned with HTTP 200
Section titled “Error — returned with HTTP 200”| Field | Type | Required | Description |
|---|---|---|---|
timestamp |
string | Unix timestamp of the response (milliseconds). | |
resultCode |
string (enum) | Failure reason. — One of: INVALID_PARAMETERS, UNAUTHORISED |