Skip to main content

Overview

This guide explains how to submit buy or sell orders for assets in a user’s portfolio using the Investment Orders endpoint POST /investments/orders.
All order operations require M2M authentication with a bearer token and the x-user-id header to specify which user’s orders to manage.

Key differences between order types

  • Buy orders: Specify amount (monetary value to invest). You must verify the user has sufficient cash balance before submitting.
  • Sell orders: Specify quantity (asset units to sell). You must verify the user has sufficient holdings before submitting.

Prerequisites

  • Access to API endpoints
  • M2M bearer token with required scopes
  • x-user-id header (user identifier, MongoDB ObjectId format)

Buy order flow

Use this flow to purchase an asset for a user’s portfolio.
1

Verify available cash

Before submitting a buy order, retrieve the user’s cash balance to ensure sufficient funds are available.Call GET /cash to retrieve the available cash balance across all currencies.
const BASE = 'https://api.wealthyhood.com';

async function getCashBalance({ token, userId }) {
  const res = await fetch(`${BASE}/cash`, {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${token}`,
      'x-user-id': userId,
      'Accept': 'application/json'
    }
  });
  if (!res.ok) throw new Error(`Failed to get cash: ${res.status}`);
  return res.json();
}
Compare the available cash balance in the target currency with the intended purchase amount before proceeding.
2

Build the buy order request

Create an order request with the asset ISIN and the monetary amount to invest.
{
  "side": "buy",
  "isin": "US0378331005",
  "amount": 25.5
}
For buy orders, you must specify amount (not quantity). The system will calculate the quantity based on the current price.
3

Submit the buy order

Call POST /investments/orders with optional query params:
  • paymentMethod: cash (default) or gift
  • executeEtfOrdersInRealtime: true only for users enabled for real-time ETF execution
const BASE = 'https://api.wealthyhood.com';

async function submitBuyOrder({ token, userId, isin, amount, paymentMethod = 'cash', executeEtfOrdersInRealtime }) {
  const url = new URL(`${BASE}/investments/orders`);
  if (paymentMethod) url.searchParams.set('paymentMethod', paymentMethod);
  if (typeof executeEtfOrdersInRealtime === 'boolean') {
    url.searchParams.set('executeEtfOrdersInRealtime', String(executeEtfOrdersInRealtime));
  }

  const res = await fetch(url.toString(), {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'x-user-id': userId,
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      side: 'buy',
      isin,
      amount
    })
  });
  if (!res.ok) throw new Error(`Order failed: ${res.status}`);
  return res.json();
}
Use executeEtfOrdersInRealtime=true only for eligible users and only for ETFs.
4

Render the transaction in UI

The response is an AssetTransaction with display-ready fields such as displayAmount, displayQuantity, executionWindow, fees, and nested orders.
  • Show execution window: Use executionWindow.type (e.g., real-time or market-hours) and expectedExecutionDate when provided.
  • Show fees: Display fees.commission.amount, fees.fx.amount, etc., when present.
  • Show order summary: From orders[0], read isin, side, status, and displayQuantity.
Successful submission returns HTTP 200 with a populated transaction object.

Sell order flow

Use this flow to sell an asset from a user’s portfolio.
1

Verify portfolio holdings

Before submitting a sell order, retrieve the user’s portfolio holdings to ensure sufficient quantity of the asset is available.Call GET /portfolios/{id} to retrieve holdings with asset details and quantities.
const BASE = 'https://api.wealthyhood.com';

async function getPortfolioHoldings({ token, userId, portfolioId }) {
  const res = await fetch(`${BASE}/portfolios/${portfolioId}`, {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${token}`,
      'x-user-id': userId,
      'Accept': 'application/json'
    }
  });
  if (!res.ok) throw new Error(`Failed to get holdings: ${res.status}`);
  return res.json();
}
Verify that the portfolio holdings contain sufficient quantity of the asset (by ISIN) before proceeding with the sell order.
2

Build the sell order request

Create an order request with the asset ISIN and the quantity to sell.
{
  "side": "sell",
  "isin": "IE00B4L5Y983",
  "quantity": 1.25
}
For sell orders, you must specify quantity (not amount). The quantity must not exceed the user’s current holdings.
3

Submit the sell order

Call POST /investments/orders with optional query params:
  • paymentMethod: cash (default) or gift
  • executeEtfOrdersInRealtime: true only for users enabled for real-time ETF execution
const BASE = 'https://api.wealthyhood.com';

async function submitSellOrder({ token, userId, isin, quantity, paymentMethod = 'cash', executeEtfOrdersInRealtime }) {
  const url = new URL(`${BASE}/investments/orders`);
  if (paymentMethod) url.searchParams.set('paymentMethod', paymentMethod);
  if (typeof executeEtfOrdersInRealtime === 'boolean') {
    url.searchParams.set('executeEtfOrdersInRealtime', String(executeEtfOrdersInRealtime));
  }

  const res = await fetch(url.toString(), {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'x-user-id': userId,
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      side: 'sell',
      isin,
      quantity
    })
  });
  if (!res.ok) throw new Error(`Order failed: ${res.status}`);
  return res.json();
}
Aggregated sell orders for ETFs are rejected for real-time-enabled users.
4

Render the transaction in UI

The response is an AssetTransaction with display-ready fields such as displayAmount, displayQuantity, executionWindow, fees, and nested orders.
  • Show execution window: Use executionWindow.type (e.g., real-time or market-hours) and expectedExecutionDate when provided.
  • Show fees: Display fees.commission.amount, fees.fx.amount, etc., when present.
  • Show order summary: From orders[0], read isin, side, status, and displayQuantity.
Successful submission returns HTTP 200 with a populated transaction object.

Error handling

  • 400 Bad Request: Validation or business rule violation (e.g., invalid amount, missing required field, invalid ISIN).
  • 401/403: Authentication/authorization failures.
  • 404 Not Found: Portfolio or related resource not found.

See also

  • API Reference → Order Execution → POST /investments/orders
  • API Reference → Cash → GET /cash
  • API Reference → Portfolio → GET /portfolios/{id}