Skip to main content

Overview

Building a complete investment experience requires combining data from two sources:
  1. Universe Configuration API — Static metadata (names, descriptions, asset classes, collections)
  2. Investment Products API — Live trading data (prices, trading status, returns)
This guide explains how to fetch, combine, and use this data effectively.
The Universe Configuration runs on a separate edge network for performance, while Investment Products provides real-time data from the main B2B API.

Step-by-step integration

1

Fetch universe configuration

Retrieve the static universe configuration.
const CONFIG_BASE = 'https://{TENANT}-staging.wealthyhood.workers.dev';

async function getUniverseConfig() {
const res = await fetch(`${CONFIG_BASE}/b2b/app-config`, {
headers: { 'Accept': 'application/json' }
});
if (!res.ok) throw new Error(`Config fetch failed: ${res.status}`);
return res.json();
}

2

Fetch investment products

Retrieve live trading data from the Investment Products API.
const API_BASE = 'https://api.wealthyhood.com';

async function getInvestmentProducts({ token }) {
const res = await fetch(`${API_BASE}/investment-products`, {
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
if (!res.ok) throw new Error(`Products fetch failed: ${res.status}`);
return res.json();
}

Unlike universe configuration, investment products should be fetched more frequently to ensure price data is current.
3

Combine the data

Merge universe metadata with live trading data using the asset key (e.g. equities_apple) as the join field.
4

Use discovery data for curation

The universe config includes curated collections for discovery screens.
function getDiscoveryData(universeConfig, combinedAssets) {
  const { discovery } = universeConfig;
  const assetMap = new Map(combinedAssets.map((a) => [a.key, a]));

  return {
    // Top movers with live price data
    topMovers: {
      best: discovery.topMovers.best
        .map((m) => ({
          ...assetMap.get(m.asset),
          returnPercentage: m.returnPercentage
        }))
      worst: discovery.topMovers.worst
        .map((m) => ({
          ...assetMap.get(m.asset),
          returnPercentage: m.returnPercentage
        }))
    },

    // Popular assets
    popular: discovery.popularAssetsSection.map((key) => assetMap.get(key)),

    // Themed collections
    collections: Object.entries(discovery.collections)
      .map(([key, collection]) => ({
        key,
        label: collection.label,
        emoji: collection.emoji,
        assets: collection.assets.map((assetKey) => assetMap.get(assetKey))
      }))
      .filter((c) => c.assets.length > 0)
  };
}

Common use cases

Filter by asset class

function getAssetsByClass(combinedAssets, assetClass) {
  return combinedAssets.filter((a) => a.assetClass === assetClass && a.listed);
}

// Get all listed equities (stocks)
const stocks = getAssetsByClass(assets, "equities");

// Get all listed ETFs
const etfs = combinedAssets.filter((a) => a.category === "etf" && a.listed);

// Get all commodities
const commodities = getAssetsByClass(assets, "commodities");

Filter by sector

function getAssetsBySector(combinedAssets, sector) {
  return combinedAssets.filter((a) => a.sector === sector && a.listed);
}

// Get all technology stocks
const techStocks = getAssetsBySector(assets, "technology");

// Get all healthcare stocks
const healthcareStocks = getAssetsBySector(assets, "healthcare");

Search assets

function searchAssets(combinedAssets, query) {
  const q = query.toLowerCase().trim();
  if (!q) return [];

  return combinedAssets.filter(
    (a) =>
      a.listed &&
      (a.name.toLowerCase().includes(q) ||
        a.isin.toLowerCase().includes(q) ||
        a.formalTicker?.toLowerCase().includes(q) ||
        a.searchTerms?.some((term) => term.toLowerCase().includes(q)))
  );
}

// Search for "tech" returns Apple, Microsoft, NVIDIA, etc.
const results = searchAssets(combinedAssets, "tech");

Get assets by provider

function getAssetsByProvider(combinedAssets, providerKey) {
  return combinedAssets.filter((a) => a.provider === providerKey && a.listed);
}

// Get all Vanguard ETFs
const vanguardETFs = getAssetsByProvider(assets, "vanguard");

// Get all iShares ETFs
const isharesETFs = getAssetsByProvider(assets, "ishares");

Get ready-made portfolios

function getReadyMadePortfolios(universeConfig, combinedAssets) {
  const { discovery } = universeConfig;
  const assetMap = new Map(combinedAssets.map((a) => [a.key, a]));

  return discovery.readyMadePortfolios.map((key) => assetMap.get(key));
}

// Get LifeStrategy portfolios
const portfolios = getReadyMadePortfolios(config, assets);

See also