Get open positions and equity for many accounts
Equity, unrealized P&L and open positions of many trading accounts in one call, with the organization API key: each account as in GET .../equity, plus its positions list (as in GET .../positions).
Use it to catch up after a real-time stream disconnect: page through every account (or only those with open positions, openOnly=true), or read a specific set with accountId. Accounts come in account-ID order; follow pagination.nextCursor until it is null. Each page is read at its own asOf.
Requires view permission on traders. About 60 requests per minute per organization.
Example queries:
# Every account that can hold positions, 200 per page
GET /organization/trading-accounts/positions?limit=200
# Only accounts with open positions
GET /organization/trading-accounts/positions?openOnly=true&limit=200
# Specific accounts
GET /organization/trading-accounts/positions?accountId=7c9e6679-...,9d1e6679-...
curl "https://api.hyperprop.com/platform/v1/organization/trading-accounts/positions?openOnly=true&limit=200" \
-H "X-API-Key: hp_live_your_key_here"
curl --request GET \
--url https://api.hyperprop.com/platform/v1/organization/trading-accounts/positions \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.hyperprop.com/platform/v1/organization/trading-accounts/positions"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.hyperprop.com/platform/v1/organization/trading-accounts/positions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hyperprop.com/platform/v1/organization/trading-accounts/positions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.hyperprop.com/platform/v1/organization/trading-accounts/positions"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.hyperprop.com/platform/v1/organization/trading-accounts/positions")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hyperprop.com/platform/v1/organization/trading-accounts/positions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"organizationId": "<string>",
"asOf": "2026-10-30T14:41:07.118Z",
"accounts": [
{
"accountId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"accountNumber": "ACC-50K-000123",
"customerId": "crm-cust-4471",
"status": "in_progress",
"currentBalance": 50300,
"unrealizedPnl": 41,
"equity": 50341,
"initialBalance": 50000,
"highWaterMark": 50500,
"dailyStartingBalance": 50100,
"dailyPnl": 200,
"dailyPnlWithUnrealized": 241,
"totalPnl": 300,
"currentDrawdown": 159,
"lossFloorBalance": null,
"positionsVersion": 12,
"riskLimits": {
"maxLossFloor": 48500,
"maxLossFloorType": "trailing",
"trailingLocked": false,
"dailyLossFloor": 49100,
"dailyLossLimitActive": true,
"dailyLossLimitOff": false,
"profitTarget": 53000,
"estimatedClosingFees": 1.24,
"distanceToMaxLoss": 1838.76,
"distanceToDailyLoss": 1238.76
},
"positions": [
{
"positionId": "3f6c1d2e-8a4b-5c7d-9e0f-1a2b3c4d5e6f",
"contract": "MNQZ6",
"side": "long",
"quantity": 2,
"avgEntryPrice": 20000.25,
"markPrice": 20010.5,
"markedAt": "2026-10-30T14:41:07.250Z",
"unrealizedPnl": 41,
"realizedPnl": 0,
"isolatedMargin": null,
"openedAt": "2026-10-30T14:30:00.000Z",
"updatedAt": "2026-10-30T14:35:12.000Z",
"stateVersion": 12
}
]
}
],
"pagination": {
"limit": 100,
"hasMore": false,
"nextCursor": null
}
}
}{
"success": false,
"statusCode": 400,
"error": "Bad Request",
"message": "accountId accepts at most 200 IDs per request",
"code": "TOO_MANY_ACCOUNT_IDS"
}{
"success": false,
"statusCode": 401,
"error": "Unauthorized",
"message": "Authentication required",
"code": "UNAUTHORIZED"
}{
"statusCode": 403,
"error": "Forbidden",
"message": "Your role does not have view access to \"Traders & accounts\"",
"code": "INSUFFICIENT_PERMISSIONS"
}{
"success": false,
"statusCode": 404,
"error": "Not Found",
"message": "Account(s) not found in your organization: 9d1e6679-7425-40de-944b-e07fc1f90ae8",
"code": "ACCOUNT_NOT_FOUND"
}{
"success": false,
"statusCode": 429,
"error": "Too Many Requests",
"message": "Too many live state requests; retry in 12s",
"code": "RATE_LIMITED",
"retryAfterSeconds": 12
}{
"success": false,
"statusCode": 500,
"error": "Internal Server Error",
"message": "An unexpected error occurred",
"code": "INTERNAL_ERROR"
}{
"success": false,
"statusCode": 503,
"error": "Error",
"message": "Live account state is temporarily unavailable; retry shortly",
"code": "LIVE_STATE_UNAVAILABLE"
}{
"statusCode": 504,
"error": "Gateway Timeout",
"message": "The request did not complete within 25 seconds. Try again, or narrow it (for example a shorter date range).",
"code": "REQUEST_TIMEOUT"
}Authorizations
Organization API key. Format: "hp_live_{key}". Organization admins manage the key in the dashboard.
Query Parameters
Specific accounts: one account ID or a comma-separated list (max 200). Every ID must belong to your organization, otherwise 404 ACCOUNT_NOT_FOUND. status, limit and cursor do not apply.
Account statuses to include, comma-separated. Default: not_started,in_progress,inactive, every account that can hold positions.
^(not_started|in_progress|inactive|passed|failed|expired)(,(not_started|in_progress|inactive|passed|failed|expired))*$true: leave out accounts without open positions. A page can then hold fewer than limit accounts; keep following nextCursor until it is null.
Accounts per page (default 100, max 200)
1 <= x <= 200Cursor for pagination. Pass the nextCursor value from the previous response to get the next page. When using cursor, do not send offset — it will be ignored.
How it works: The cursor is an opaque string that points to the last item you received. The server uses it to efficiently fetch the next set of results without scanning previous pages.
Backwards compatible: If you don't send a cursor, offset/limit pagination works as before.
curl --request GET \
--url https://api.hyperprop.com/platform/v1/organization/trading-accounts/positions \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.hyperprop.com/platform/v1/organization/trading-accounts/positions"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.hyperprop.com/platform/v1/organization/trading-accounts/positions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hyperprop.com/platform/v1/organization/trading-accounts/positions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.hyperprop.com/platform/v1/organization/trading-accounts/positions"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.hyperprop.com/platform/v1/organization/trading-accounts/positions")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hyperprop.com/platform/v1/organization/trading-accounts/positions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"organizationId": "<string>",
"asOf": "2026-10-30T14:41:07.118Z",
"accounts": [
{
"accountId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"accountNumber": "ACC-50K-000123",
"customerId": "crm-cust-4471",
"status": "in_progress",
"currentBalance": 50300,
"unrealizedPnl": 41,
"equity": 50341,
"initialBalance": 50000,
"highWaterMark": 50500,
"dailyStartingBalance": 50100,
"dailyPnl": 200,
"dailyPnlWithUnrealized": 241,
"totalPnl": 300,
"currentDrawdown": 159,
"lossFloorBalance": null,
"positionsVersion": 12,
"riskLimits": {
"maxLossFloor": 48500,
"maxLossFloorType": "trailing",
"trailingLocked": false,
"dailyLossFloor": 49100,
"dailyLossLimitActive": true,
"dailyLossLimitOff": false,
"profitTarget": 53000,
"estimatedClosingFees": 1.24,
"distanceToMaxLoss": 1838.76,
"distanceToDailyLoss": 1238.76
},
"positions": [
{
"positionId": "3f6c1d2e-8a4b-5c7d-9e0f-1a2b3c4d5e6f",
"contract": "MNQZ6",
"side": "long",
"quantity": 2,
"avgEntryPrice": 20000.25,
"markPrice": 20010.5,
"markedAt": "2026-10-30T14:41:07.250Z",
"unrealizedPnl": 41,
"realizedPnl": 0,
"isolatedMargin": null,
"openedAt": "2026-10-30T14:30:00.000Z",
"updatedAt": "2026-10-30T14:35:12.000Z",
"stateVersion": 12
}
]
}
],
"pagination": {
"limit": 100,
"hasMore": false,
"nextCursor": null
}
}
}{
"success": false,
"statusCode": 400,
"error": "Bad Request",
"message": "accountId accepts at most 200 IDs per request",
"code": "TOO_MANY_ACCOUNT_IDS"
}{
"success": false,
"statusCode": 401,
"error": "Unauthorized",
"message": "Authentication required",
"code": "UNAUTHORIZED"
}{
"statusCode": 403,
"error": "Forbidden",
"message": "Your role does not have view access to \"Traders & accounts\"",
"code": "INSUFFICIENT_PERMISSIONS"
}{
"success": false,
"statusCode": 404,
"error": "Not Found",
"message": "Account(s) not found in your organization: 9d1e6679-7425-40de-944b-e07fc1f90ae8",
"code": "ACCOUNT_NOT_FOUND"
}{
"success": false,
"statusCode": 429,
"error": "Too Many Requests",
"message": "Too many live state requests; retry in 12s",
"code": "RATE_LIMITED",
"retryAfterSeconds": 12
}{
"success": false,
"statusCode": 500,
"error": "Internal Server Error",
"message": "An unexpected error occurred",
"code": "INTERNAL_ERROR"
}{
"success": false,
"statusCode": 503,
"error": "Error",
"message": "Live account state is temporarily unavailable; retry shortly",
"code": "LIVE_STATE_UNAVAILABLE"
}{
"statusCode": 504,
"error": "Gateway Timeout",
"message": "The request did not complete within 25 seconds. Try again, or narrow it (for example a shorter date range).",
"code": "REQUEST_TIMEOUT"
}