Skip to main content
POST
/
v1
/
trpc
/
v2.*
tRPC v2 Portfolio API
curl --request POST \
  --url 'https://api.glider.fi/v1/trpc/v2.*' \
  --header 'X-API-KEY: <api-key>'
The v2 tRPC namespace is the canonical API surface for agent and CLI consumers.
  • Base endpoint: POST /v1/trpc
  • Namespace: v2.*
  • Auth:
    • Wallet session for v2.portfolio.create.* and v2.portfolio.permission.refresh.*
    • Wallet session for v2.portfolio.scheduledFunctions.*
    • Wallet session or API key for other v2.portfolio.*, v2.executions.*, and deprecated v2.operations.*
    • For API key calls, owner is resolved from canonical API key metadata/KMS linkage. x-glider-owner-address is optional and must match canonical owner when provided.
    • Public rate-limited access for v2.public.* non-owner read surfaces

Procedure Groups

  • v2.portfolio.*
    • list, listByOwnerDbV2, get, status
    • vaults.list
    • performance.get, performance.series, performance.assetMetrics
    • activity.list
    • recipients.list
    • deposit.instructions
    • create.prepare, create.confirm
    • permission.status, permission.refresh.prepare, permission.refresh.confirm
    • archive, unarchive
    • updates.list, updates.get, updates.preview, updates.create, updates.submit, updates.supersede
    • approvals.list, approvals.get, approvals.decide
    • runs.list, runs.get
    • events.list, events.stream
    • context.list, context.get
    • agents.list, agents.get
    • actions.submit
    • policy.evaluate, policy.scheduleAdvisory
    • schedule.get, schedule.create, schedule.update, schedule.setFromText, schedule.pause, schedule.archive, schedule.resume, schedule.runNow
    • scheduledFunctions.list, scheduledFunctions.create, scheduledFunctions.delete (beta/private rollout; not exposed in the webapp by default)
  • v2.executions.*
    • get, detail, result, list, stream
  • v2.operations.* (deprecated)
    • legacy compatibility reads
  • v2.agentAuth.*
    • createApiKey
  • v2.public.*
    • portfolio.list, portfolio.listByIds, portfolio.get
    • portfolio.vaults.list
    • portfolio.schedule.get
    • account.profile.get
    • account.assets.list
    • account.performance.series
    • account.performance.overview

Performance Series Response Shape

v2.portfolio.performance.series and v2.public.account.performance.series return a unified response containing historical TWR series, pre-computed stats per timeframe, and a live value snapshot:
{
  "series": [
    {
      "ts": "2026-03-24T00:00:00.000Z",
      "eventType": null,
      "tvlUsd": "1234.56",
      "amount": "0.00",
      "growthFactor": "1.05",
      "cumulativeTwrPct": "5.00",
      "isLive": false
    }
  ],
  "stats": {
    "DAY": { "absoluteChangeUsd": "12.34", "twrPct": "1.05" },
    "WEEK": { "absoluteChangeUsd": "45.67", "twrPct": "3.21" },
    "MONTH": { "absoluteChangeUsd": "123.45", "twrPct": "8.90" },
    "YEAR": { "absoluteChangeUsd": "456.78", "twrPct": "25.00" },
    "ALL": { "absoluteChangeUsd": "789.01", "twrPct": "42.00" }
  },
  "live": {
    "value": "1234.56",
    "assets": [
      {
        "assetId": "asset-db-id",
        "symbol": "USDC",
        "valueUsd": "500.00"
      }
    ]
  }
}
  • series[] may include a trailing isLive: true point representing the current live valuation.
  • stats is keyed by PerformanceChartResolution (DAY, WEEK, MONTH, YEAR, ALL).
  • live contains the real-time portfolio value and per-asset breakdown. live.assets is present on v2.portfolio.performance.series but omitted from the account-level endpoint.
  • Responses are cached in Redis with a 30s TTL.

Execution Handle

Long-running actions return a canonical execution envelope:
{
  "operationId": "rebalance:<portfolioId>:<runId>",
  "portfolioId": "<portfolio-id>",
  "kind": "rebalance",
  "state": "accepted",
  "createdAt": "2026-02-27T00:00:00.000Z",
  "updatedAt": "2026-02-27T00:00:00.000Z",
  "refs": {
    "workflowId": "<workflow-id>",
    "runId": "<run-id>"
  }
}
v2.portfolio.actions.submit also includes additive execution guidance:
  • nextSteps.poll -> v2.executions.get
  • nextSteps.stream -> v2.executions.stream
  • nextRecommendedCommands with ready-to-copy polling/stream commands

Execution Detail

Use v2.executions.get for a lightweight summary handle, v2.executions.detail for the persisted execution narrative, and v2.executions.result for raw terminal machine output. v2.executions.detail returns:
  • operation: the canonical execution handle
  • summary: the current headline, phase, and terminal reason when available
  • timeline: curated execution events suitable for user-facing progress UIs or agents
  • graph: optional rebalance observer graph metadata for richer visualizations

Execution Stream

v2.executions.stream is the canonical typed realtime surface for first-party web clients. It replays ordered canonical execution events and then switches to live tail delivery. Each event uses this envelope:
{
  "streamId": "execution:op_123",
  "eventId": "1743163201000-0",
  "sequence": 17,
  "ts": "2026-03-28T15:10:00.000Z",
  "kind": "execution.timeline_appended",
  "operationId": "op_123",
  "cursor": "1743163201000-0",
  "payload": {}
}
  • Resume is supported with cursor. SSE reconnects also use the same opaque cursor via Last-Event-ID.
  • v2.executions.get and v2.executions.detail remain the snapshot and hydration APIs.
  • GET /v1/executions/:operationId/stream exposes the same canonical event log over SSE for CLIs, API integrators, and future chat surfaces.

Retired/Legacy Mapping

  • sessionKeys.getPortfolioSignableMessage -> v2.portfolio.create.prepare
  • sessionKeys.createPortfolioWithSignature -> v2.portfolio.create.confirm
  • sessionKeys.refreshSessionKeyMessage* -> v2.portfolio.permission.refresh.prepare
  • sessionKeys.refreshSessionKeyWithSignature -> v2.portfolio.permission.refresh.confirm
  • strategyInstances.getStrategyInstancesOwnedByAddress -> v2.portfolio.list
  • authenticated dashboard owner-list hydration -> v2.portfolio.listByOwnerDbV2
  • strategyInstances.getStrategyInstance -> v2.portfolio.get
  • strategyInstances.archiveStrategyInstance -> v2.portfolio.archive
  • strategyInstances.unarchiveStrategyInstance -> v2.portfolio.unarchive
  • strategyInstances.getUnifiedPortfolioHistory -> v2.portfolio.activity.list (kind="history")
  • strategyInstances.getStrategyPerformanceMultipleTimeframes -> v2.portfolio.performance.get (timeframes)
  • strategyInstances.getNetDepositsAndWithdrawals -> v2.portfolio.performance.get (netFlows)
  • strategyInstances.getStrategyPerformanceSeries -> v2.portfolio.performance.series
  • dashboard asset analytics -> v2.portfolio.performance.assetMetrics
  • strategyInstances.getStrategyInstanceVaultsOwnedByAddress -> v2.portfolio.recipients.list
  • strategyInstances.getStrategyInstancesOwnedByAddress (public profile view) -> v2.public.portfolio.list
  • curated public portfolio-card hydration -> v2.public.portfolio.listByIds
  • strategyInstances.getStrategyInstance (unowned read) -> v2.public.portfolio.get
  • vaults.getVaultsPortfolioDataForStrategyInstance (unowned read) -> v2.public.portfolio.vaults.list
  • schedules.getStrategyInstanceSchedule (unowned read) -> v2.public.portfolio.schedule.get
  • user profile hydration aggregate -> v2.public.account.profile.get
  • strategyInstances.getAllAssetsAcrossWalletStrategies (public profile aggregate) -> v2.public.account.assets.list
  • strategyInstances.getAccountPerformanceOverview (public profile aggregate) -> v2.public.account.performance.overview
  • strategyInstances.getAccountPerformanceSeries (public profile aggregate) -> v2.public.account.performance.series
  • rebalance.execute -> v2.portfolio.actions.submit (kind="rebalance")
  • withdrawAndDeposits.process* -> v2.portfolio.actions.submit (kind="withdraw")
  • bridge.processBridgeRequest -> v2.portfolio.actions.submit (kind="bridge")
  • executeLifiQuote.execute -> v2.portfolio.actions.submit (kind="swap")
  • backend-quoted LiFi swap execution -> v2.portfolio.actions.submit (kind="swap_backend_quote")
  • schedules.* -> v2.portfolio.schedule.*
  • user-approved scheduled functions -> v2.portfolio.scheduledFunctions.*
  • rebalance.getStatus / workflows.* / temporal.* / bridge.getBridgeStatus / executeLifiQuote.getStatus -> v2.executions.get / v2.executions.detail / v2.executions.result / v2.executions.stream

Compatibility Notes

  • Selected legacy namespaces remain mounted for backwards compatibility.
  • Retired procedure paths are intentionally removed from legacy routers (for example rebalance.execute and migrated schedules.* write mutations), and should be treated as v2.portfolio.*-only.
  • New agent/CLI integrations should target only v2.*.
  • v2 keeps external language portfolio-first (portfolioId), even when internal implementations still use strategy-instance identifiers.
  • v2.executions.list reads from the persisted execution narrative store for rebalance, swap, withdraw, and bridge.
  • v2.executions.detail reads the persisted execution narrative store and adds timeline plus optional graph metadata.
  • v2.executions.stream replays and tails the canonical execution event log rather than synthesizing updates from repeated detail polling in the normal path.
  • v2.operations.* remains mounted temporarily as a deprecated, best-effort surface only.
  • v2.portfolio.status is resilient: permission/session data still returns if rebalance status source is unavailable; rebalance is null and degraded.rebalanceUnavailable=true.
  • v2.portfolio.status includes additive semantic convergence metadata for owner UIs:
    • state: awaiting_review | queued | moving | blocked | aligned | failed
    • summary: portfolio-level explanation of the highest-priority outstanding condition
    • approvalId?, proposalId?, runId?, targetId?, targetType?, executionStatus?, updatedAt: optional references for detail surfaces
  • v2.portfolio.updates.* is the desired-state composer surface for webapp-v2:
    • preview derives semantic before/after state without mutating live strategy definitions
    • create writes a draft revision
    • submit(mode="review") promotes that revision to pending_review
    • submit(mode="apply_now") accepts the revision and syncs it through blueprint versioning for runtime parity
    • get returns PORTFOLIO_UPDATE_NOT_FOUND when the revision is missing; it does not return a nullable success payload
    • update rows expose additive revision metadata so owner surfaces can reason about desired-state history
    • update status includes dismissed for review declines
  • v2.portfolio.approvals.* is the canonical owner-facing approval surface:
    • approval targets are semantic (portfolio_update or copilot_proposal)
    • decide is the canonical owner decision entrypoint
    • older v2.copilot.* approval paths remain compatibility surfaces
  • v2.portfolio.runs.* exposes semantic convergence/execution rows projected from desired-state apply, copilot execution, and rebalance runtime sources.
  • v2.portfolio.events.* exposes stored semantic control-plane history:
    • list returns canonical timeline events and paginates with an opaque cursor derived from (createdAt,id)
    • stream provides polling-backed internal event streaming for owner surfaces and can resume from the last opaque cursor
  • semantic control-plane reads are now pure db-v2 reads by default; operational read repair remains available only behind PORTFOLIO_CONTROL_PLANE_ENABLE_READ_REPAIR
  • v2.portfolio.context.* exposes immutable context snapshots referenced by approvals, runs, and events.
  • v2.portfolio.agents.* exposes portfolio-scoped automated principals and their allowed scopes.
  • Permission UIs should prefer v2.portfolio.permission.status (session keys + evm agent only) for lighter polling.
  • Portfolio identity payloads add canonical_strategy_blueprint_id:
    • v2.portfolio.list returns it on each portfolio row.
    • v2.portfolio.get and v2.public.portfolio.get return it on the nested blueprint object.
    • Consumers can use it to route portfolio viewers to the canonical strategy page for unchanged forks.
  • Dashboard migration contracts:
    • v2.portfolio.listByOwnerDbV2 is the db-v2-backed authenticated owner-list route used by the webapp dashboard shell.
    • Each row includes id, archived, created_at, owner_address, owner_account_index, blueprint_name, blueprint_description, is_public, primary_chain_id, updated_at, and vault_addresses.
    • v2.portfolio.performance.series is now a typed envelope, not a raw array:
      • series: historical/accounting performance points
      • stats: backend-computed DAY | WEEK | MONTH | YEAR | ALL metrics with absoluteChangeUsd and twrPct
      • live: current value plus normalized live.assets
    • live.assets uses frontend-facing asset IDs directly and includes:
      • assetId, optional dbAssetId, symbol, decimals, priceUsd, valueUsd, liveBalanceFormatted, liveBalanceRaw, vaultAddress
    • v2.portfolio.performance.assetMetrics augments live assets with db-v2 analytics:
      • assetId, optional dbAssetId, marketValueUsd, netInvestedUsd, pnlUsd, priceUsd, priceMissing, asOf
  • Schedule APIs are manual-first and optional:
    • new/forked/mirrored portfolios do not auto-create a rebalance schedule.
    • v2.portfolio.schedule.get adds scheduleStatus (active | paused | disabled | archived | null).
    • archived schedules are returned as non-active compatibility payloads (scheduleExists=false, scheduleId=null, scheduleData=null) while still reporting scheduleStatus="archived".
    • archived schedules are terminal: v2.portfolio.schedule.create, v2.portfolio.schedule.update, and v2.portfolio.schedule.setFromText return SCHEDULE_ARCHIVED and do not reactivate automation.
    • v2.portfolio.schedule.runNow includes additive operation identifiers: accepted, runId, and operationId.
  • Scheduled swap APIs are UTC-anchored:
    • v2.portfolio.scheduledFunctions.* is currently in beta/private rollout and is hidden in the webapp unless the recurring-swaps UI feature flag is enabled for the user.
    • v2.portfolio.scheduledFunctions.create supports additive schedule input for functionKey="recurring_swap": hourly, or { frequency: "daily" | "weekly", hourUtc, day? }.
    • The server translates that input into persisted intervalMs/startAt/endAt.
    • hourUtc and weekly day are interpreted in UTC; local DST shifts are not preserved.
  • Policy APIs are authoritative backend preflight surfaces:
    • v2.portfolio.policy.evaluate is the canonical machine-facing evaluator for rebalance, schedule, swap, and withdraw.
    • v2.portfolio.policy.scheduleAdvisory is a convenience wrapper over the same schedule evaluation path.
    • Observed portfolio facts for public policy evaluation come from backend resolvers, not caller-supplied exposure snapshots.
    • Public swap and withdraw policy evaluation uses chainIds to derive request exposure. Raw requestExposure remains accepted temporarily for wire compatibility, but is ignored.
    • Public rebalance, schedule, and scheduleAdvisory still accept legacy currentExposure / plannedExposure fields for compatibility, but those fields are ignored immediately.
    • Public withdraw policy evaluation also ignores legacy raw portfolioTotalUsd and isFullWithdraw inputs; the backend derives those facts authoritatively when available.
    • Decision payloads preserve status, allowed, primaryBlockingReason, reasons, remainingConditions, and nextEligibleAt, and now also include:
      • authoritative
      • facts
      • ruleResults
    • primaryBlockingReason and each entry in reasons[] now also include:
      • policyId
      • category
      • policySetId when the reason came from a chain-scoped policy set
    • ruleResults[] now includes:
      • reasonCodes
      • policyIds
      • reasonCode remains as the first/primary code for backward compatibility.
    • facts[].status distinguishes present, missing, stale, and synthetic.
    • facts[].origin distinguishes backend-loaded facts (server), backend-derived request facts (derived), and caller-supplied fallback/hypothetical facts (client).
    • authoritative=true only means the triggered policy rules had sufficient trusted backend facts; missing, stale, synthetic-only, or client-sourced required facts downgrade the decision to non-authoritative.
    • Backend primary-chain resolution is authoritative: service loaders win over caller fallback hints, and fallbackPrimaryChainId is treated as a compatibility hint rather than the source of truth.
    • remainingConditions[] may include market_available for Ondo-backed rebalance and swap decisions, carrying the blocked asset IDs, symbols, availability type (closed or halted), and nextOpenAt when Ondo provides a reopen time.
    • Omitting schedule input on the schedule policy endpoints returns the backend default cadence instead of a denial.
    • Schedule defaults are resolved through a backend chain-policy-set catalog. The generic non-ETH baseline is the current Base-mainnet policy shape, while Ethereum remains stricter because of gas-cost-driven limits.
    • Multi-chain policy-set selection now prefers the authoritative primary chain over catalog order. If multiple supported policy sets match and the primary chain cannot disambiguate them, evaluation defers instead of picking one arbitrarily.
    • Configured-but-unsupported chain policy sets fail closed with a blocking denial rather than silently inheriting the generic non-ETH baseline.

ETH Mainnet Product Limits (Effective March 2, 2026)

For portfolios where primary_chain_id = "1":
  • Rebalance cooldown: max once every 24 hours.
    • error: REBALANCE_ETH_MAINNET_COOLDOWN_ACTIVE
  • Schedule constraints:
    • interval cadence only,
    • interval must be >= 24h,
    • default interval on schedule creation is 24h.
    • errors: SCHEDULE_ETH_MAINNET_INTERVAL_TOO_SHORT, SCHEDULE_ETH_MAINNET_INTERVAL_ONLY
  • Withdraw constraints:
    • minimum selected withdraw amount $10,
    • if portfolio total is below $10, only full-balance withdraw is allowed.
    • errors: WITHDRAW_ETH_MAINNET_BELOW_MINIMUM, WITHDRAW_ETH_MAINNET_FULL_REQUIRED_UNDER_MINIMUM
  • Swap-like actions (kind="swap" and kind="swap_backend_quote"):
    • minimum notional $10,
    • error: LIFI_ETH_MAINNET_BELOW_MINIMUM_TRADE
  • v2.portfolio.scheduledFunctions.* is currently allowlisted to functionKey="recurring_swap" only.
  • As of March 10, 2026, recurring_swap is intentionally narrow: buy a token with USDC or sell a token to USDC.

Public Read Surface Notes

  • v2.public.portfolio.list, v2.public.portfolio.listByIds, v2.public.portfolio.get, v2.public.portfolio.vaults.list, v2.public.portfolio.schedule.get, v2.public.portfolio.performance.*, and v2.public.portfolio.activity.list do not currently enforce is_public.
    • These routes currently only return PORTFOLIO_NOT_FOUND when the portfolio does not exist.
  • v2.public.portfolio.listByIds is the lightweight multi-card hydration route for curated public portfolio pages.
    • Input: portfolioIds[] with up to 50 ids.
    • Output: results keyed by portfolio id.
    • Missing or unreadable ids return null for that entry instead of failing the whole batch.
  • v2.public.account.profile.get is the canonical user-profile hydration endpoint used by /user/:userId.
    • It returns the user-page aggregate header value, Investing Account snapshot, and profile portfolio cards/table payload in one response.
    • The profile payload is intentionally user-page-specific and is not currently filtered by is_public.
    • User-profile schedule rendering is db-v2-only: portfolios without a v2 schedule row surface as manual/unscheduled.
  • v2.public.account.assets.list, v2.public.account.performance.series, and v2.public.account.performance.overview are owner-scoped aggregates with no per-portfolio visibility check.

Agent Auth Notes

  • v2.agentAuth.createApiKey keeps ownerAddress optional for compatibility.
  • If ownerAddress is provided, it must match the authenticated wallet address.
  • API key metadata persists the canonical wallet owner; mismatches are rejected.

Webapp Migration Status

As of February 28, 2026, the webapp is migrating in phases:
  • Migrated to v2.* in owner-authenticated flows:
    • portfolio create/confirm and permission refresh
    • owner portfolio list/get/archive
    • desired-state composer preview/draft/review/apply via v2.portfolio.updates.*
    • owner schedule get/create/update/setFromText/pause/resume/runNow
    • bridge submit via v2.portfolio.actions.submit
    • withdraw/transfer submit via v2.portfolio.actions.submit
    • swap submit via v2.portfolio.actions.submit (kind="swap")
    • backend-quoted swap submit via v2.portfolio.actions.submit (kind="swap_backend_quote")
    • unified history via v2.portfolio.activity.list
    • rebalance runtime status reads via v2.portfolio.status
    • execution polling via v2.executions.get in migrated withdraw/transfer/swap paths
  • Soft deprecation logging is enabled for selected migrated v1 procedures.
  • Migrated to v2.public.* in non-owner/public flows:
    • user profile hydration via v2.public.account.profile.get
    • competition row vault data + schedule reads

Deferred v1 Allowlist

The following remain on v1 in this phase by design:
  • Operation/status exceptions with no clean parity signal yet:
    • withdraw-as-target-asset (ETH/USDC) is unsupported and rejected client-side (legacy backend path is also unsupported)
  • Public/unowned reads that conflict with v2 owner-auth requirements:
    • public profile and competition views
    • OG routes and legacy routes reading arbitrary user portfolio data
  • Analytics endpoints without v2 parity:
    • chart/account/competitor/backtest-style strategyInstances.*
  • schedules.getSchedulesForMultipleStrategies (no v2 equivalent yet)