Skip to main content
This quickstart walks through listing available yield sources, creating a Portfolio Wallet, waiting for it to activate, funding it via its deposit addresses, checking balances, and withdrawing.

Prerequisites

Set your base URL and API token once, then reuse them for every request. Use sandbox while you build, then switch to production by swapping the base URL. The endpoint structure stays the same, but sandbox uses explicit testnet chain keys such as ethereum_sepolia.
cURL

Conventions

  • JSON field names are camelCase.
  • Enum-like string values (for example status, type, and webhook event/eventTypes) are lower_snake_case.
    • Example: payoutLeg.status = pending_customer_approval

1. List available yield sources

Fetch the yield sources you can allocate to. Each yield source has a stable id you will use as yieldSourceId when creating a wallet.
cURL
The response contains the catalog in its data array. Note each source’s id and apyBps to decide your allocation.

2. Create a portfolio wallet

Create a Portfolio Wallet by passing strategy.allocations with your chosen yield allocation. Allocation percentages must sum to 100.
cURL
The v2 request shape uses token-keyed allocation groups with yieldSourceId and pct. Wallet creation is asynchronous. The POST response returns immediately with status: "creating" and the wallet id, but depositAddresses are not yet available — they are populated once provisioning completes. Save the wallet id for the remaining steps:
cURL

3. Wait for the wallet to activate

Poll GET /v2/wallets/{id} every 1-2 seconds until status === "idle". Only then are depositAddresses populated. If status === "failed", inspect failureReason and retry creation with a new requestId. See Polling → Poll until wallet is active for a ready-to-paste snippet in cURL, Node, and Python.

4. Deposit actual funds

Once the wallet is active, grab the chain-specific deposit address from the poll response and send a stablecoin transfer from your custody to that address.
Plain

5. Await Deposit Confirmation

Deposits are detected on-chain and then processed. You can track the latest deposit status either by polling the deposits endpoints or by subscribing to webhooks. Poll (REST):
  • List deposits for a wallet: GET /v2/wallets/{id}/deposits
  • Fetch a single deposit: GET /v2/wallets/{id}/deposits/{depositId}
Example:
cURL
Webhook events:
  • portfolio_wallet.deposit.status_changed
Possible deposit statuses (deposit.status):
  • processing
  • completed
  • failed

6. Fetch the updated balance

Fetch the wallet to see current balances after the deposit is processed. Key fields in the response:
  • balance.totalUsd — total wallet value across positions, cash, and accrued yield
  • balance.withdrawableUsd — conservative amount the customer can withdraw now
  • balance.reservedUsd — customer-owned value currently reserved by active withdrawals or rebalances
  • balance.earnedUsd — lifetime yield earned since wallet creation
  • positions[] — current cash, bridge, and yield-source balances. Yield-source positions include target allocations.
cURL

7. Withdraw (including the signing flow)

Ground uses Turnkey to manage signing flows, but you do not need a relationship with Turnkey to sign approvals.
Initiate a withdrawal. If approval is required, a payout leg and its external payout step enter pending_customer_approval; complete the approval in Ground Portal or through the Ground Turnkey approval endpoints.
cURL
Save the id from the response (this is the withdrawal id used for status checks):
cURL
Customer approvals are completed in Ground Portal or through the Ground Turnkey approval endpoints: fetch GET /v2/turnkey/activities/pending, request POST /v2/turnkey/activity-approval-request, stamp the returned payload locally, then submit POST /v2/turnkey/activities/{activityId}/vote. See Transaction Approvals for verification checks and approval patterns.

8. Await Withdrawal Confirmation

After approval (if required), the withdrawal is kicked off automatically. You can track the latest withdrawal status either by polling the withdrawal endpoint or by subscribing to webhooks. Poll (REST):
cURL
Webhook events:
  • portfolio_wallet.rebalance.status_changed (cash deployment and strategy adjustment progress)
  • portfolio_wallet.withdrawal.status_changed
  • portfolio_wallet.withdrawal.payout.status_changed (per-leg payouts)
Possible withdrawal statuses (withdrawal.status):
  • processing
  • partially_completed
  • completed
  • failed
  • cancelled
Possible payout leg statuses (withdrawal.payoutLegs[].status) and payout step states (withdrawal.payoutLegs[].steps[].state):
  • processing
  • created
  • pending_customer_approval
  • completed
  • failed
  • cancelled
Webhook payout and rebalance payloads include per-step workflow metadata such as name, chain, state, txKind, stepKind, protocolType, and sequenceRole. txHash is included when a broadcast transaction hash is available. For more detail, see Transaction Approvals and the API Reference withdrawal endpoints.