Core entities
My Prop Journal's API exposes several core entities that represent your trading data:
1. Trade Groups
A trade group represents a complete trade from entry to exit. Each trade contains:
- Entry and exit prices, dates, and times
- Overall P&L calculations (gross and net)
- Position size and direction (long/short)
- Status (win/loss/breakeven/open)
- Associated executions (fills)
2. Executions
Executions are individual buy/sell orders that make up a trade. Each execution includes:
- Side (buy/sell)
- Price and quantity
- Timestamp
- Commission/fees
- Execution type (scale_in, scale_out, full)
A single trade can have multiple executions (e.g., scaling in/out of positions).
3. Accounts
Trading accounts represent your prop firm or retail broker accounts. Fields include:
- Account type (prop or retail)
- Firm/broker name
- Account number
- Balance or current value
- Status (for prop accounts)
4. Playbooks
Playbooks are collections of trading strategies and rules. Each playbook contains:
- Name and description
- Entry criteria (conditions to enter trades)
- Exit criteria (conditions to exit trades)
- Associated strategies
5. Strategies
Strategies are specific trading approaches within playbooks. Each strategy has:
- Name and description
- Parent playbook reference
- Creation timestamp
6. Future entities (not yet in API)
These entities exist in the product but are not yet exposed via API:
- Trade writeups — Post-trade analysis and notes
- Report cards — Daily trading performance reviews
- Chart books — Saved chart screenshots and annotations
Entity relationships
Understanding how entities relate helps you build effective integrations:
Trade hierarchy
Account
└─ Trade Group
├─ Execution 1 (entry)
├─ Execution 2 (scale in)
├─ Execution 3 (scale out)
└─ Execution 4 (exit)
Example query pattern:
// Get all trades for a specific account
const trades = await fetch(
`${BASE_URL}/trades?account_id=${accountId}`,
{ headers: { Authorization: `Bearer ${API_KEY}` } }
);
// Each trade includes its executions
trades.data.forEach(trade => {
console.log(`Trade ${trade.symbol}: ${trade.executions.length} fills`);
});
Playbook hierarchy
Playbook
├─ Entry Criteria
│ ├─ Criterion 1
│ └─ Criterion 2
├─ Exit Criteria
│ ├─ Criterion 1
│ └─ Criterion 2
└─ Strategies
├─ Strategy 1
└─ Strategy 2
Example query pattern:
# Get playbooks with all nested data
playbooks = get_playbooks()
for playbook in playbooks['data']:
print(f"\n{playbook['name']}")
print(f" Entry rules: {len(playbook['entry_criteria'])}")
print(f" Exit rules: {len(playbook['exit_criteria'])}")
print(f" Strategies: {len(playbook['strategies'])}")
Data ownership and isolation
User-scoped data
All API operations are automatically scoped to the authenticated user:
- Users can only access their own data
- Cross-user queries return empty results or 404 errors
- Isolation is enforced at the database level
Example:
// User A's API key
const userA_key = "mpj_user_a_key";
// User B's API key
const userB_key = "mpj_user_b_key";
// User A creates a trade
const trade = await createTrade(tradeData, userA_key);
console.log(`Created trade: ${trade.data.id}`);
// User B tries to access User A's trade
const response = await fetch(
`${BASE_URL}/trades/${trade.data.id}`,
{ headers: { Authorization: `Bearer ${userB_key}` } }
);
// Returns 404 - trade doesn't "exist" for User B
console.log(response.status); // 404
ID formats
All entity IDs are UUIDs (version 4):
- Format:
a1b2c3d4-e5f6-7890-1234-567890abcdef - Globally unique
- Safe to use in URLs and JSON
Field types and formats
Dates and times
- Dates: ISO 8601 date format (
YYYY-MM-DD) - Times: 24-hour format (
HH:MM:SS) - Timestamps: ISO 8601 with timezone (
2024-01-15T10:30:00Z)
Examples:
{
"entry_date": "2024-01-15",
"entry_time": "10:30:00",
"created_at": "2024-01-15T10:30:00Z"
}
Monetary values
- Type: Number (float)
- Precision: Up to 2 decimal places for currencies
- Format: No currency symbols, just numeric values
Examples:
{
"entry_price": 245.50,
"net_pnl": 158.25,
"balance": 150000.00
}
Enumerations
Several fields use predefined string values:
Trade side:
"long"— Buy/long position"short"— Sell/short position
Trade status:
"win"— Profitable trade"loss"— Losing trade"breakeven"— Zero P&L"open"— Trade still in progress
Account type:
"prop"— Prop trading firm account"retail"— Retail broker account
Execution side:
"buy"— Buy order"sell"— Sell order
Complete example: Trade object
Here's a fully-annotated trade object showing all fields and their types:
{
"id": "fd07b82a-164c-4c24-885a-7f4db54dab62", // UUID
"account_id": "f1588e0d-93fd-4a76-b876-b0753f93bc09", // UUID (foreign key)
"symbol": "NQ", // string
"side": "short", // enum: "long" | "short"
"quantity": 1, // number (integer)
"entry_price": 29298, // number (float)
"exit_price": 29290, // number (float) | null
"entry_time": "10:17:54", // string (HH:MM:SS)
"exit_time": "10:18:29", // string (HH:MM:SS) | null
"gross_pnl": 160, // number (float)
"net_pnl": 158, // number (float)
"total_commission": 2, // number (float)
"status": "win", // enum: "win" | "loss" | "breakeven" | "open"
"entry_date": "2026-02-05", // string (YYYY-MM-DD)
"exit_date": "2026-02-05", // string (YYYY-MM-DD) | null
"asset_class": "futures", // string
"created_at": "2026-02-05T15:17:54+00:00", // string (ISO 8601)
"updated_at": "2026-02-05T15:18:29+00:00", // string (ISO 8601)
"executions": [ // array of execution objects
{
"id": "1ed21bd6-8ea2-42d0-b16e-142f9484ecb9", // UUID
"side": "sell", // enum: "buy" | "sell"
"price": 29298, // number (float)
"quantity": 1, // number (integer)
"commission": 1, // number (float)
"execution_time": "10:17:54", // string (HH:MM:SS)
"execution_type": "scale_in", // string
"execution_timestamp": "2026-02-05T15:17:54+00:00" // string (ISO 8601)
}
]
}
Working with nested data
Accessing executions
// Get trades and analyze execution patterns
const trades = await getTrades();
trades.data.forEach(trade => {
const numExecutions = trade.executions.length;
const avgPrice = trade.executions.reduce((sum, exec) =>
sum + exec.price, 0) / numExecutions;
console.log(`${trade.symbol}: ${numExecutions} fills, avg price: ${avgPrice}`);
});
Filtering by nested properties
# Find all trades with more than 3 executions
trades = get_trades(limit=100)
complex_trades = [
trade for trade in trades['data']
if len(trade['executions']) > 3
]
print(f"Found {len(complex_trades)} trades with 3+ executions")