This page documents public GET routes: /health and portfolio endpoints under /api/v1/portfolios/ (list, summary, detail, alerts, performance). Use the sections below
for paths, parameters, example curls, and sample responses.
Paths in this guide. Examples use public routes under /api/v1/portfolios/demo/; the JSON you see here matches the portfolio resources you access in production on the routes and base URL issued with your credentials. Contact us for API onboarding.
Authentication
Authorization: Bearer <access_token>. Partners receive short-lived access tokens (OAuth
2.0–style client credentials) scoped to their integration; send the header on every portfolio request. Missing,
expired, or invalid tokens return 401.
{"portfolio_id":"c293a410-0ffd-4c43-9599-f0e253d03d4c","name":"JANUARY 2026","description":"Tuesday 2026-01-06","total_capital":1000000.0,"allocated_capital":995405.91,"remaining_capital":4594.09,"position_count":30,"created_at":"2026-01-06T12:00:00","updated_at":"2026-04-07T20:44:40.993000","currency":"USD","trace_id":"c6ebe64a-a502-485d-b6e4-c4f3efd87388","risk_settings":{"max_risk_per_trade":0.08,"max_portfolio_risk":0.35,"max_position_size":0.1,"max_positions":30,"allocation_strategy":"EQUAL_WEIGHT","reward_multiplier":1.5,"half_kelly":false},"risk_quiz_answers":{"conc":"med","vol":"comfortable","horizon":"gt5","dd":"high","goal":"balanced","pref":"balanced"},"suggested_preset":{"description":"Equal Weight Strategy","preset":"equal_moderate"},"settings":{"portfolio_daily_notification_email":false,"portfolio_symbols_checker_email":false,"ares_automated_trade":false,"ares_trade_notification_email":true,"artemis_daily_trade_picks_email":false,"ares_daily_trade_limit":1,"ares_agent_slots":[{"agent_id":"agent-1","label":"","ares_allowed_trade_days":["mon","tue","wed","thu","fri"],"ares_daily_buy_limit":1,"ares_daily_sell_limit":1,"ares_min_cash_balance_pct":0.0,"ares_allow_sell_unrealized_gain_bullish":true,"ares_allow_sell_unrealized_loss_bullish":true,"ares_sell_at_price_target":true,"ares_sell_at_stop_price":true,"ares_sell_on_bearish":true,"ares_sell_on_weakness":true,"ares_buy_early_stage_bullish":true,"ares_sell_unrealized_loss_over_pct":15,"ares_sell_unrealized_gain_over_pct":15,"ares_daily_cash_trade_limit":1,"ares_daily_swap_trade_limit":1},{"agent_id":"agent-2","label":"","ares_allowed_trade_days":["mon","tue","wed","thu","fri"],"ares_daily_buy_limit":1,"ares_daily_sell_limit":1,"ares_min_cash_balance_pct":0.0,"ares_allow_sell_unrealized_gain_bullish":true,"ares_allow_sell_unrealized_loss_bullish":true,"ares_sell_at_price_target":true,"ares_sell_at_stop_price":true,"ares_sell_on_bearish":true,"ares_sell_on_weakness":true,"ares_buy_early_stage_bullish":true,"ares_sell_unrealized_loss_over_pct":15,"ares_sell_unrealized_gain_over_pct":15,"ares_daily_cash_trade_limit":1,"ares_daily_swap_trade_limit":1},{"agent_id":"agent-3","label":"","ares_allowed_trade_days":["mon","tue","wed","thu","fri"],"ares_daily_buy_limit":1,"ares_daily_sell_limit":1,"ares_min_cash_balance_pct":0.0,"ares_allow_sell_unrealized_gain_bullish":true,"ares_allow_sell_unrealized_loss_bullish":true,"ares_sell_at_price_target":true,"ares_sell_at_stop_price":true,"ares_sell_on_bearish":true,"ares_sell_on_weakness":true,"ares_buy_early_stage_bullish":true,"ares_sell_unrealized_loss_over_pct":15,"ares_sell_unrealized_gain_over_pct":15,"ares_daily_cash_trade_limit":1,"ares_daily_swap_trade_limit":1}],"ares_active_agent_slot":0},"allocations":[{"symbol":"SEMR","company_name":"SEMrush Holdings, Inc.","sector":"Technology","industry":"Software - Application","shares":2803.0,"entry_price":11.890000343322754,"position_type":"LONG","position_value":33495.84946537018,"target_price":11.956666628519693,"stage":"Stage 2","signal":"BUY","stage_strength":"VERY_STRONG","percent_of_account":0.033328,"risk_reward_ratio":2.0,"confidence":0.7,"signal_confidence":null,"signal_reason":null,"bb_width":null,"atr":null,"atr_percent":null,"volatility_trend":null,"is_high_volatility":null,"volatility_stop_loss_levels":null,"historical_volatility":0.07139543112366513,"support_levels":[{"price":11.770000457763672}],"resistance_levels":[{"price":11.956666628519693}],"stop_loss":11.830499811172485,"risk_amount":333.2767096233368,"current_price":11.949999809265137,"exit_price":null,"close_price":11.949999809265137,"unrealized_gain":168.17850303649902,"realized_gain":null,"is_open":true,"allocation_percentage":0.031494550971571514},{"symbol":"AXTI","company_name":"AXT Inc","sector":"Technology","industry":"Semiconductor Equipment & Materials","shares":2016.0,"entry_price":16.530000686645508,"position_type":"LONG","position_value":91647.35815429688,"target_price":85.68285805838448,"stage":"STAGE 2","signal":"BUY","stage_strength":"VERY_STRONG","percent_of_account":0.033324,"risk_reward_ratio":2.0,"confidence":0.8687026923578792,"signal_confidence":null,"signal_reason":null,"bb_width":null,"atr":null,"atr_percent":null,"volatility_trend":null,"is_high_volatility":null,"volatility_stop_loss_levels":null,"historical_volatility":11.64339433689066,"support_levels":[],"resistance_levels":[],"stop_loss":25.34856959751674,"risk_amount":9676.80615234375,"current_price":45.459999084472656,"exit_price":null,"close_price":45.459999084472656,"unrealized_gain":58322.87677001953,"realized_gain":null,"is_open":true,"allocation_percentage":0.0861716433191068}],"open_position_count":30,"closed_position_count":0,"user_uid":"sDufHrVuzvfM4ya4Or2ebH35Pv03","days_change":1947.5350875854492,"total_current_value":1068138.3677261735,"total_days":92,"start_date":"2026-01-06","total_return_percent":6.81,"spy_return_percent":-4.45,"spy_outperformance":11.26,"total_unrealized_pnl":68138.35366038358,"total_realized_pnl":0.0,"clio_config_hash":null,"clio_run_id":null,"top_movers":[{"symbol":"AXTI","company_name":"AXT Inc","shares":2016.0,"position_value":91647.35815429688,"stage":"STAGE 2","signal":"BUY","stage_strength":"VERY_STRONG","percent_of_account":0.09164735815429688,"current_price":45.459999084472656,"unrealized_gain":58322.87677001953,"unrealized_gain_percent":175.02,"days_change":3.47,"days_change_percent":8.26},{"symbol":"NRGV","company_name":"Energy Vault Holdings, Inc.","shares":6680.0,"position_value":20106.799936294556,"stage":"Stage 3","signal":"SELL","stage_strength":"MODERATE","percent_of_account":0.020106799936294557,"current_price":3.009999990463257,"unrealized_gain":-13226.39853477478,"unrealized_gain_percent":-39.68,"days_change":-0.14,"days_change_percent":-4.44},{"symbol":"WDC","company_name":"Western Digital Corporation","shares":172.0,"position_value":53657.11853027344,"stage":"STAGE 2","signal":"BUY","stage_strength":"VERY_STRONG","percent_of_account":0.05365711853027344,"current_price":311.9599914550781,"unrealized_gain":20390.25408935547,"unrealized_gain_percent":61.29,"days_change":7.81,"days_change_percent":2.57},{"symbol":"ASTS","company_name":"AST SpaceMobile, Inc.","shares":366.0,"position_value":33880.619888305664,"stage":"Stage 3","signal":"HOLD","stage_strength":"MODERATE","percent_of_account":0.033880619888305666,"current_price":92.56999969482422,"unrealized_gain":611.2193298339844,"unrealized_gain_percent":1.84,"days_change":-2.24,"days_change_percent":-2.36},{"symbol":"RKLB","company_name":"Rocket Lab Corporation","shares":428.0,"position_value":28384.959869384766,"stage":"Stage 2","signal":"BUY","stage_strength":"STRONG","percent_of_account":0.028384959869384767,"current_price":66.31999969482422,"unrealized_gain":-4896.321044921875,"unrealized_gain_percent":-14.71,"days_change":-1.35,"days_change_percent":-1.99},{"symbol":"SATS","company_name":"EchoStar Corporation","shares":302.0,"position_value":37680.538986206055,"stage":"STAGE 2","signal":"BUY","stage_strength":"VERY_STRONG","percent_of_account":0.037680538986206054,"current_price":124.7699966430664,"unrealized_gain":4369.938064575195,"unrealized_gain_percent":13.12,"days_change":-2.18,"days_change_percent":-1.72},{"symbol":"SKYT","company_name":"SkyWater Technology, Inc.","shares":1324.0,"position_value":37164.679595947266,"stage":"Stage 2","signal":"BUY","stage_strength":"VERY_STRONG","percent_of_account":0.03716467959594726,"current_price":28.06999969482422,"unrealized_gain":3852.839797973633,"unrealized_gain_percent":11.57,"days_change":-0.47,"days_change_percent":-1.65},{"symbol":"ODFL","company_name":"Old Dominion Freight Line, Inc.","shares":203.0,"position_value":40382.788513183594,"stage":"Stage 2","signal":"BUY","stage_strength":"VERY_STRONG","percent_of_account":0.040382788513183596,"current_price":198.92999267578125,"unrealized_gain":7090.788513183594,"unrealized_gain_percent":21.3,"days_change":-3.25,"days_change_percent":-1.61},{"symbol":"BCH","company_name":"Banco De Chile","shares":833.0,"position_value":30221.238983154297,"stage":"Stage 2","signal":"BUY","stage_strength":"VERY_STRONG","percent_of_account":0.0302212389831543,"current_price":36.279998779296875,"unrealized_gain":-3082.1006355285645,"unrealized_gain_percent":-9.25,"days_change":-0.59,"days_change_percent":-1.6}],"_sample_note":"allocations truncated to 2 rows for docs; full API response has more."}
export ATLAS_API="${ATLAS_API:-https://atlas-api.trinitytrade.io}"
curl -sS "$ATLAS_API/api/v1/portfolios/demo/c293a410-0ffd-4c43-9599-f0e253d03d4c"
# Swap id: copy portfolio_id from GET .../list if this example id is stale.
Response
GET
Get Portfolio Alerts
/api/v1/portfolios/{portfolio_id}/alerts
Aggregated alerts for open positions in the given portfolio (priorities, thresholds, messages).
Daily time series of total portfolio value. See PortfolioPerformanceResponse below for how to read success, data, and metadata. Optional start_date and end_date (YYYY-MM-DD) may be accepted; when the server returns a precomputed series, filter client-side if you need a shorter window.
One element of the JSON array from GET/api/v1/portfolios/demo/list. Atlas validates with List[PortfolioResponsePublic]; user_uid is excluded from public
JSON (the sample response on this page may still show legacy mock fields).
Show full field reference (table)
Field
Type
Description
portfolio_id
string
Unique portfolio identifier.
name
string
Portfolio name.
description
string or null
Optional description.
total_capital
number
Total available capital.
allocated_capital
number
Capital allocated to open positions.
remaining_capital
number
Unallocated cash.
position_count
integer
Number of positions.
created_at
string (datetime)
Creation timestamp.
currency
string
Currency code (e.g. USD).
trace_id
string
Request correlation id for logs.
PortfolioSummaryResponsePublic
One element of the JSON array from GET/api/v1/portfolios/demo/list/summary (proxied through IRIS in the try-it panel). user_uid is omitted from public JSON. Nested top_holdings and top_movers rows follow PositionSummaryForList.
Show full field reference (tables)
Summary object
Field
Type
Description
portfolio_id
string
Unique portfolio identifier.
name
string
Portfolio name.
description
string or null
Optional description.
total_capital
number
Total capital.
allocated_capital
number
Allocated capital.
remaining_capital
number
Remaining cash.
position_count
integer
Position count.
created_at
string (datetime)
Created at.
updated_at
string or null
Last Firestore update.
currency
string
Currency code.
top_holdings
array
Top positions by value (PositionSummaryForList).
top_movers
array
Top open positions by absolute daily % move.
total_current_value
number
Aggregate current market value.
total_unrealized_pnl
number
Unrealized P&L on open positions.
total_realized_pnl
number
Realized P&L on closed positions.
days_change
number
Portfolio value change vs prior day.
alerts_count
integer
Active alerts for this portfolio.
urgent_alerts / high_alerts / medium_alerts
integer
Counts by priority band.
trade_picks_count
integer
Positions with BUY signals.
unrealized_gains_count / unrealized_loss_count
integer
Open winners / losers.
total_return_percent
number or null
Total return % since inception when benchmark data is available.
spy_return_percent
number or null
SPY return over the same window.
spy_outperformance
number or null
Portfolio return minus SPY (percentage points).
PositionSummaryForList
Field
Type
Description
symbol
string
Ticker.
company_name
string or null
Issuer name when known.
shares
number
Share quantity.
position_value
number
Position market value.
stage
string or null
Weinstein-style stage label.
signal
string or null
BUY / SELL / HOLD style signal.
stage_strength
string or null
Strength of the stage.
percent_of_account
number or null
Fraction of account in this name.
current_price
number or null
Latest price used in the summary.
unrealized_gain
number or null
Unrealized dollar P&L.
unrealized_gain_percent
number or null
Unrealized P&L vs cost.
days_change
number or null
Dollar change per share vs prior close.
days_change_percent
number or null
Percent change vs prior close.
DetailedPortfolioResponse
Body of GET/api/v1/portfolios/demo/{portfolio_id} for authenticated-style
detail. Public demo responses use DetailedPortfolioResponseAnonymousDemo: user_uid, risk_quiz_answers, suggested_preset, days_change, clio_*, and settings are omitted;
allocations and top_movers are truncated (e.g. two allocation rows);
each allocation uses PositionDetailAnonymousDemo (signal / volatility-heavy fields omitted
from JSON).
Authenticated detail may also include user_uid, risk_quiz_answers, suggested_preset, settings, days_change, clio_config_hash, clio_run_id, and full PositionDetail objects with Athena / volatility fields.
PositionDetail (demo allocation keys)
Demo JSON keeps the trading snapshot without signal objects / ATR / BB width / volatility stop trees. Typical keys
include symbol, company_name, sector, industry, shares, entry_price, position_type, position_value, target_price, stage, stage_strength, percent_of_account, historical_volatility, support_levels, resistance_levels, stop_loss, risk_amount, current_price, unrealized_gain, is_open, allocation_percentage, and related price metadata. See PositionDetail / PositionDetailAnonymousDemo in Atlas for the authoritative list.
PortfolioAlertsResponse
Body of GET/api/v1/portfolios/demo/{portfolio_id}/alerts (
response_model=PortfolioAlertsResponse).
Successful GET/api/v1/portfolios/demo/{portfolio_id}/performance
returns a JSON object (cached Firestore performance doc or an on-demand calculation). Authenticated portfolio routes
use the same envelope; missing cache surfaces 404 instead of an empty series.
Show performance field reference (prose + lists)
A successful response is a JSON object with three top-level fields you should rely on in integrations:
success — boolean. When true, the payload is usable.
data — array of daily points in chronological order (one entry per calendar day in the
series). Each point is an object with short keys to keep payloads small:
d — the calendar date as an integer in YYYYMMDD form (e.g. 20260407 means 2026-04-07). To convert for chart labels: year =
Math.floor(d / 10000), month =
Math.floor((d % 10000) / 100), day =
d % 100 (zero-pad month and day if needed).
v — total portfolio value on that date in the portfolio currency (USD in the demo
examples), rounded to two decimal places. It represents the combined notion of cash plus valued positions
for that day as modeled by the API; use it as the y-axis for a performance chart.
metadata — summary aligned with the series:
start_date / end_date — inclusive span of the series
(ISO YYYY-MM-DD strings).
initial_value — baseline capital used with total_return_percent.
current_value — should match the v on the last day in data.
total_return_percent — overall return for the window vs initial_value.
total_days — calendar length of the window (useful for age or labeling). Additional
metadata keys may appear from time to time; treat unknown keys as optional.
Building charts and metrics. Plot d (decoded to dates) on the x-axis and v on the y-axis. You can derive day-over-day change from consecutive v
values, or cumulative return vs the baseline with ((v / initial_value) - 1) * 100 using initial_value from metadata. Non-trading days may repeat the last mark; that is expected for a daily series.
Authenticated portfolio routes use the same response shape; if performance is not ready yet, the API returns 404 instead of an empty series.