Skip to main content
POST
Analyze Portfolio

How It Works

This endpoint uses async job processing for handling large portfolios:
  1. Submit Job: POST your portfolio data to /v1/portfolio/analyze
  2. Receive Job ID: Get a job ID and polling URL immediately
  3. Poll for Status: Check /v1/jobs/{job_id} until status is completed
  4. Get Results: The completed job response contains the full analysis
Processing typically takes 60-120 seconds depending on the date range and number of holdings.
Need a persistent portfolio that updates every day without recomputing history? Use the Portfolio Tracker endpoints instead. analyze is a one-shot, stateless computation.

Request Body

The default benchmark is ACWI.OQ (MSCI ACWI ETF). If a benchmark symbol can’t be resolved to a RIC the request fails with a clear validation error rather than silently falling back.

Portfolio Holdings Format

Each item in the portfolio array:
Weights should sum to 1.0 for each date. They will be normalized if not.

Field Selection

Use the optional fields parameter to return only specific data sections. If omitted, all fields are returned.
benchmark_prices is internal-only and is no longer a selectable fields value or part of the default response. For benchmark charting, use daily_summary.benchmark_value_base instead.

Response Fields

The completed analysis includes: In the three contribution sections, contribution_pct is each row’s contribution to the portfolio return, as a decimal: its P&L divided by initial_value (0.0353 = 3.53 percentage points). The rows sum to the portfolio’s return, and a row’s sign always matches its own P&L. analytics_version increases whenever the calculation’s output changes. If you store results, compare it with a fresh result to know when yours are out of date.

Example Response

When the job completes, GET /v1/jobs/{job_id} returns:
Response shown is abbreviated. Full response includes all fields listed above, plus detailed timeseries for allocations, drawdowns, rolling metrics, and more.

Example: Polling for Results

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Body

application/json
portfolio
PortfolioHolding · object[]
required

List of portfolio holdings with dates and weights

start_date
string | null

Analysis start date in YYYY-MM-DD format (defaults to first rebalance date)

Example:

"2024-01-01"

end_date
string | null

Analysis end date in YYYY-MM-DD format (defaults to yesterday)

Example:

"2024-11-01"

base_currency
string
default:USD

Base currency for portfolio

Example:

"USD"

benchmark
string
default:ACWI.OQ

Benchmark for comparison

Example:

"ACWI.OQ"

initial_value
number
default:10000

Initial portfolio value in base currency

Example:

10000

include_transaction_costs
boolean
default:false

Apply market-specific transaction costs during rebalancing

Example:

false

transaction_cost_config
Transaction Cost Config · object | null

Custom transaction cost rates by market. Format: {'market_name': {'buy': rate, 'sell': rate}}. If not provided, uses default rates.

Example:
fields
string[] | null

Optional list of fields to include in response. If not provided, all fields are returned. Available fields: portfolio_parameters, portfolio_input, data_quality, portfolio_summary, turnover_analysis, performance_metrics, rolling_metrics, drawdown_analysis, portfolio_scores, concentration_metrics, transactions, company_info, latest_holdings, market_allocation, sector_allocation, currency_allocation, company_contribution, sector_contribution, market_contribution, time_period_returns, monthly_returns, annual_returns, daily_summary

Example:

Response

Successful Response

Last modified on September 21, 2026