GET/v1/partner/end_users/{external_id}/portfolios

List portfolios

Returns a cursor-paginated list of yield portfolios (jars) for the specified end user. Each item is a live snapshot of the portfolio's balance, yield earned, APY, and token metadata. Supports both Entra token + user token. In user-scoped the X-User-Token's sub claim must match external_id.

Call this to display a user's current positions. Token metadata is returned nested under a token object — see the response example below. For pagination conventions, see Pagination.

Path parameters

external_idstringrequired

Your stable identifier for the end user.

Headers

Authorizationstringrequired

Entra M2M access token. Format: Bearer <token>. See Entra authentication.

X-User-Tokenstringoptional

Partner-minted JWT for the end user. Required in user-scoped. The sub claim must equal external_id. See User authentication.

Query parameters

limitnumberoptional

Maximum number of portfolios to return. Range 1–100. Default: 25. See Pagination.

starting_afterstringoptional

Cursor for forward pagination — the portfolio_id of the last item from the previous page.

ending_beforestringoptional

Cursor for backward pagination — the portfolio_id of the first item from the current page.

Example request

const baseUrl = process.env.YIELDFORCE_API_BASE_URL ?? 'https://yieldforce.io/api';
 
const res = await fetch(`${baseUrl}/v1/partner/end_users/alice-bunq-id/portfolios`, {
  headers: {
    Authorization: `Bearer ${entraToken}`,
    'X-User-Token': partnerJwt,
  },
});
const data = await res.json();

Response

200 Paginated list of portfolio snapshots

{
  "data": [
    {
      "portfolio_id": "jar_01HZ4KXQM5E8WRTYN3P7VBJD6F",
      "name": "USDC vault on Base",
      "description": null,
      "protocol": "morpho",
      "chain_id": "84532",
      "market_address": "0x6A0935DEF442D92c3456FBb38B888375F022C646",
      "token": {
        "symbol": "USDC",
        "address": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
        "decimals": 6
      },
      "deposited": "10000000",
      "yield_earned": "42000",
      "yield_earned_realized": "0",
      "total_balance": "10042000",
      "total_gross_yield_earned": "42000",
      "total_fees_paid": "0",
      "apy_snapshot": 0.063,
      "compounding_enabled": true,
      "last_synced_at": "2026-05-20T09:55:00.000Z",
      "created_at": "2026-05-19T10:00:00.000Z",
      "updated_at": "2026-05-20T09:55:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null,
  "prev_cursor": null
}

Token metadata is nested, not flat

The portfolio response uses a nested token: { symbol, address, decimals } object — not flat fields like token_symbol / token_address / token_decimals. All amounts (deposited, yield_earned, total_balance, etc.) are strings representing values in token minor units (e.g. USDC uses 6 decimals, so "10000000" = 10 USDC).

Errors

401 token_missing — No Authorization: Bearer header on the request.

401 invalid_entra_token — Token is expired, malformed, or has an unexpected audience.

401 invalid_user_token — The X-User-Token failed signature verification or is expired.

403 sub_url_mismatch — The sub claim in X-User-Token does not match external_id in the URL.

404 end_user_not_found — No user with this external_id exists in your tenant.