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.

RegionBase URL
Americashttps://www.us-api.morningstar.com
APAChttps://www.apac-api.morningstar.com
EMEAhttps://www.emea-api.morningstar.com

Headers

HeaderValue
AuthorizationBearer {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-Typeapplication/json

Query Parameters

ParameterRequiredDescription
langcultYesThe 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.

PropertyRequiredDescription
PortfoliosYesOne or two portfolios, each with a maximum of 250 holdings.
RequestSettingsYesAnalysis settings. OutputCurrency is required within it.
ViewNoThe predefined set of data points to return. Defaults to All.
ConfigNoThe 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

StatusDescription
200The request succeeded. The body contains an XRay array and a SecurityReference array. See Understanding the Response.
400The request is invalid. The body describes each problem. See Bad request responses.
401Unauthorized. The token is missing, invalid or expired.
403Forbidden.
500Internal 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.