Portfolio X-Ray API
Build Portfolio X-Ray APIs into your digital experience for quick investment and earnings summaries.
Request Portfolio X-Ray
Use this endpoint to generate an X-Ray for the portfolios in the request body. The response describes how each portfolio is diversified by region, sector and investment style.
Endpoint
POST /portfolioanalysis/v1/xray?langcult={langcult}
Use the base URL for your region.
| Region | Base URL |
|---|---|
| Americas | https://www.us-api.morningstar.com |
| APAC | https://www.apac-api.morningstar.com |
| EMEA | https://www.emea-api.morningstar.com |
Headers
| Header | Value |
|---|---|
Authorization | Bearer {token}. Obtain a token from the Authentication API using POST /token/oauth. Tokens are valid for 60 minutes and can be reused across requests. |
Content-Type | application/json |
Query Parameters
| Parameter | Required | Description |
|---|---|---|
langcult | Yes | The language and locale for the response: en-US, en-CA, en-AU or en-GB. Defaults to en-US. Use langcult to override the value of the Accept-Language header. |
Request Body
The request body contains the portfolios to analyze and the analysis settings. For details, see Request Structure and Configuring the Analysis.
| Property | Required | Description |
|---|---|---|
Portfolios | Yes | One or two portfolios, each with a maximum of 250 holdings. |
RequestSettings | Yes | Analysis settings. OutputCurrency is required within it. |
View | No | The predefined set of data points to return. Defaults to All. |
Config | No | The configuration preset. Defaults to Default. |
Example Request
The following request analyzes a single portfolio.
curl --request POST \
--url "https://www.us-api.morningstar.com/portfolioanalysis/v1/xray?langcult=en-US" \
--header "Authorization: Bearer {token}" \
--header "Content-Type: application/json" \
--data '{
"RequestSettings": {
"OutputCurrency": "USD",
"AnalysisDateTimePeriod": "MonthEnd",
"PortfolioPerformanceStartDate": "EarliestCommon",
"PerformanceFrequency": "Monthly",
"InitialValue": 10000,
"DisableRescale": false
},
"Portfolios": [
{
"Name": "ExamplePortfolio1",
"Currency": "USD",
"TotalValue": 50000,
"Holdings": [
{ "TradingSymbol": "SPY", "Weight": 40 },
{ "TradingSymbol": "AGG", "Weight": 30 },
{ "TradingSymbol": "QQQ", "Weight": 20 },
{ "SecurityId": "CASH%0.000", "Weight": 10 }
]
}
]
}'
Responses
| Status | Description |
|---|---|
200 | The request succeeded. The body contains an XRay array and a SecurityReference array. See Understanding the Response. |
400 | The request is invalid. The body describes each problem. See Bad request responses. |
401 | Unauthorized. The token is missing, invalid or expired. |
403 | Forbidden. |
500 | Internal server error. |
Bad Request Responses
A 400 response contains a Message and a SpecificErrorStatus array. Each entry has an ErrorCode and an ErrorMessage.
{
"Message": "The request is invalid.",
"SpecificErrorStatus": [
{
"ErrorCode": "40015",
"ErrorMessage": "Portfolio does not have any valid holdings. Invalid portfolio name: TestPortfolio1. Invalid Holdings: TradingSymbol:DODGX1."
}
]
}
When DisableRescale is true and a portfolio contains invalid or unentitled holdings, the error includes Metadata that lists each affected holding and whether its status is Invalid or Unentitled.
{
"Message": "The request is invalid.",
"SpecificErrorStatus": [
{
"ErrorCode": "40059",
"ErrorMessage": "There are holdings present in portfolio which are invalid.",
"Metadata": {
"InvalidPortfolios": [
{
"Name": "Test Portfolio",
"InvalidHoldings": [
{ "SecurityId": "FX000015JA3", "Status": "Invalid" },
{ "SecurityId": "F00000YZ48", "Status": "Unentitled" }
]
}
]
}
}
]
}
For a full list of errors and how to resolve them, see Errors and Troubleshooting.