curl --request POST \
--url https://sandbox.groundtech.co/v2/wallets \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"requestId": "a1b2c3d4-0000-4000-8000-000000000001",
"label": "Corporate Treasury",
"autoRebalance": true,
"strategy": {
"allocations": {
"usdc": [
{
"yieldSourceId": "cash",
"pct": 20
},
{
"yieldSourceId": "morpho-gauntlet-usdc",
"pct": 80
}
],
"usdt": [
{
"yieldSourceId": "cash",
"pct": 100
}
]
}
}
}
'import requests
url = "https://sandbox.groundtech.co/v2/wallets"
payload = {
"requestId": "a1b2c3d4-0000-4000-8000-000000000001",
"label": "Corporate Treasury",
"autoRebalance": True,
"strategy": { "allocations": {
"usdc": [
{
"yieldSourceId": "cash",
"pct": 20
},
{
"yieldSourceId": "morpho-gauntlet-usdc",
"pct": 80
}
],
"usdt": [
{
"yieldSourceId": "cash",
"pct": 100
}
]
} }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
requestId: 'a1b2c3d4-0000-4000-8000-000000000001',
label: 'Corporate Treasury',
autoRebalance: true,
strategy: {
allocations: {
usdc: [
{yieldSourceId: 'cash', pct: 20},
{yieldSourceId: 'morpho-gauntlet-usdc', pct: 80}
],
usdt: [{yieldSourceId: 'cash', pct: 100}]
}
}
})
};
fetch('https://sandbox.groundtech.co/v2/wallets', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sandbox.groundtech.co/v2/wallets",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'requestId' => 'a1b2c3d4-0000-4000-8000-000000000001',
'label' => 'Corporate Treasury',
'autoRebalance' => true,
'strategy' => [
'allocations' => [
'usdc' => [
[
'yieldSourceId' => 'cash',
'pct' => 20
],
[
'yieldSourceId' => 'morpho-gauntlet-usdc',
'pct' => 80
]
],
'usdt' => [
[
'yieldSourceId' => 'cash',
'pct' => 100
]
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://sandbox.groundtech.co/v2/wallets"
payload := strings.NewReader("{\n \"requestId\": \"a1b2c3d4-0000-4000-8000-000000000001\",\n \"label\": \"Corporate Treasury\",\n \"autoRebalance\": true,\n \"strategy\": {\n \"allocations\": {\n \"usdc\": [\n {\n \"yieldSourceId\": \"cash\",\n \"pct\": 20\n },\n {\n \"yieldSourceId\": \"morpho-gauntlet-usdc\",\n \"pct\": 80\n }\n ],\n \"usdt\": [\n {\n \"yieldSourceId\": \"cash\",\n \"pct\": 100\n }\n ]\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://sandbox.groundtech.co/v2/wallets")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"requestId\": \"a1b2c3d4-0000-4000-8000-000000000001\",\n \"label\": \"Corporate Treasury\",\n \"autoRebalance\": true,\n \"strategy\": {\n \"allocations\": {\n \"usdc\": [\n {\n \"yieldSourceId\": \"cash\",\n \"pct\": 20\n },\n {\n \"yieldSourceId\": \"morpho-gauntlet-usdc\",\n \"pct\": 80\n }\n ],\n \"usdt\": [\n {\n \"yieldSourceId\": \"cash\",\n \"pct\": 100\n }\n ]\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sandbox.groundtech.co/v2/wallets")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"requestId\": \"a1b2c3d4-0000-4000-8000-000000000001\",\n \"label\": \"Corporate Treasury\",\n \"autoRebalance\": true,\n \"strategy\": {\n \"allocations\": {\n \"usdc\": [\n {\n \"yieldSourceId\": \"cash\",\n \"pct\": 20\n },\n {\n \"yieldSourceId\": \"morpho-gauntlet-usdc\",\n \"pct\": 80\n }\n ],\n \"usdt\": [\n {\n \"yieldSourceId\": \"cash\",\n \"pct\": 100\n }\n ]\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "b1c2d3e4-0000-4000-8000-000000000001",
"autoRebalance": true,
"label": "Corporate Treasury",
"createdAt": "2025-09-01T00:00:00Z",
"status": "creating",
"failureReason": null,
"depositAddresses": {},
"balance": {
"totalUsd": "0.000000",
"withdrawableUsd": "0.000000",
"reservedUsd": "0.000000",
"earnedUsd": "0.000000"
},
"positions": [
{
"id": "cash:usdc",
"kind": "cash",
"label": "USDC",
"allocationGroup": "usdc",
"token": "usdc",
"valueUsd": "0.000000",
"pct": 20
},
{
"id": "morpho-gauntlet-usdc",
"kind": "yield_source",
"label": "Morpho Gauntlet USDC Prime",
"chain": "ethereum",
"token": "usdc",
"allocationGroup": "usdc",
"valueUsd": "0.000000",
"withdrawableUsd": "0.000000",
"pct": 80
}
],
"strategyAllocations": {
"usdc": [
{
"yieldSourceId": "cash",
"targetWeightBps": 2000,
"token": "usdc"
},
{
"yieldSourceId": "morpho-gauntlet-usdc",
"targetWeightBps": 8000,
"chain": "ethereum",
"token": "usdc",
"allocationGroup": "usdc"
}
],
"usdt": [
{
"yieldSourceId": "cash",
"targetWeightBps": 10000,
"token": "usdt",
"chain": "ethereum",
"allocationGroup": "usdt"
}
],
"usdt:tron": [
{
"yieldSourceId": "cash",
"targetWeightBps": 10000,
"token": "usdt",
"chain": "tron",
"allocationGroup": "usdt:tron"
}
]
}
}Create a portfolio wallet
Creates a wallet that either invests deposits automatically or keeps them in cash. Reusing requestId returns the same wallet.
curl --request POST \
--url https://sandbox.groundtech.co/v2/wallets \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"requestId": "a1b2c3d4-0000-4000-8000-000000000001",
"label": "Corporate Treasury",
"autoRebalance": true,
"strategy": {
"allocations": {
"usdc": [
{
"yieldSourceId": "cash",
"pct": 20
},
{
"yieldSourceId": "morpho-gauntlet-usdc",
"pct": 80
}
],
"usdt": [
{
"yieldSourceId": "cash",
"pct": 100
}
]
}
}
}
'import requests
url = "https://sandbox.groundtech.co/v2/wallets"
payload = {
"requestId": "a1b2c3d4-0000-4000-8000-000000000001",
"label": "Corporate Treasury",
"autoRebalance": True,
"strategy": { "allocations": {
"usdc": [
{
"yieldSourceId": "cash",
"pct": 20
},
{
"yieldSourceId": "morpho-gauntlet-usdc",
"pct": 80
}
],
"usdt": [
{
"yieldSourceId": "cash",
"pct": 100
}
]
} }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
requestId: 'a1b2c3d4-0000-4000-8000-000000000001',
label: 'Corporate Treasury',
autoRebalance: true,
strategy: {
allocations: {
usdc: [
{yieldSourceId: 'cash', pct: 20},
{yieldSourceId: 'morpho-gauntlet-usdc', pct: 80}
],
usdt: [{yieldSourceId: 'cash', pct: 100}]
}
}
})
};
fetch('https://sandbox.groundtech.co/v2/wallets', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sandbox.groundtech.co/v2/wallets",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'requestId' => 'a1b2c3d4-0000-4000-8000-000000000001',
'label' => 'Corporate Treasury',
'autoRebalance' => true,
'strategy' => [
'allocations' => [
'usdc' => [
[
'yieldSourceId' => 'cash',
'pct' => 20
],
[
'yieldSourceId' => 'morpho-gauntlet-usdc',
'pct' => 80
]
],
'usdt' => [
[
'yieldSourceId' => 'cash',
'pct' => 100
]
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://sandbox.groundtech.co/v2/wallets"
payload := strings.NewReader("{\n \"requestId\": \"a1b2c3d4-0000-4000-8000-000000000001\",\n \"label\": \"Corporate Treasury\",\n \"autoRebalance\": true,\n \"strategy\": {\n \"allocations\": {\n \"usdc\": [\n {\n \"yieldSourceId\": \"cash\",\n \"pct\": 20\n },\n {\n \"yieldSourceId\": \"morpho-gauntlet-usdc\",\n \"pct\": 80\n }\n ],\n \"usdt\": [\n {\n \"yieldSourceId\": \"cash\",\n \"pct\": 100\n }\n ]\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://sandbox.groundtech.co/v2/wallets")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"requestId\": \"a1b2c3d4-0000-4000-8000-000000000001\",\n \"label\": \"Corporate Treasury\",\n \"autoRebalance\": true,\n \"strategy\": {\n \"allocations\": {\n \"usdc\": [\n {\n \"yieldSourceId\": \"cash\",\n \"pct\": 20\n },\n {\n \"yieldSourceId\": \"morpho-gauntlet-usdc\",\n \"pct\": 80\n }\n ],\n \"usdt\": [\n {\n \"yieldSourceId\": \"cash\",\n \"pct\": 100\n }\n ]\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sandbox.groundtech.co/v2/wallets")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"requestId\": \"a1b2c3d4-0000-4000-8000-000000000001\",\n \"label\": \"Corporate Treasury\",\n \"autoRebalance\": true,\n \"strategy\": {\n \"allocations\": {\n \"usdc\": [\n {\n \"yieldSourceId\": \"cash\",\n \"pct\": 20\n },\n {\n \"yieldSourceId\": \"morpho-gauntlet-usdc\",\n \"pct\": 80\n }\n ],\n \"usdt\": [\n {\n \"yieldSourceId\": \"cash\",\n \"pct\": 100\n }\n ]\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "b1c2d3e4-0000-4000-8000-000000000001",
"autoRebalance": true,
"label": "Corporate Treasury",
"createdAt": "2025-09-01T00:00:00Z",
"status": "creating",
"failureReason": null,
"depositAddresses": {},
"balance": {
"totalUsd": "0.000000",
"withdrawableUsd": "0.000000",
"reservedUsd": "0.000000",
"earnedUsd": "0.000000"
},
"positions": [
{
"id": "cash:usdc",
"kind": "cash",
"label": "USDC",
"allocationGroup": "usdc",
"token": "usdc",
"valueUsd": "0.000000",
"pct": 20
},
{
"id": "morpho-gauntlet-usdc",
"kind": "yield_source",
"label": "Morpho Gauntlet USDC Prime",
"chain": "ethereum",
"token": "usdc",
"allocationGroup": "usdc",
"valueUsd": "0.000000",
"withdrawableUsd": "0.000000",
"pct": 80
}
],
"strategyAllocations": {
"usdc": [
{
"yieldSourceId": "cash",
"targetWeightBps": 2000,
"token": "usdc"
},
{
"yieldSourceId": "morpho-gauntlet-usdc",
"targetWeightBps": 8000,
"chain": "ethereum",
"token": "usdc",
"allocationGroup": "usdc"
}
],
"usdt": [
{
"yieldSourceId": "cash",
"targetWeightBps": 10000,
"token": "usdt",
"chain": "ethereum",
"allocationGroup": "usdt"
}
],
"usdt:tron": [
{
"yieldSourceId": "cash",
"targetWeightBps": 10000,
"token": "usdt",
"chain": "tron",
"allocationGroup": "usdt:tron"
}
]
}
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
Response
Wallet returned. New wallets may still be provisioning with status: creating.
Whether Ground automatically deploys deposits and maintains the wallet's percentage targets.
Compact wallet lifecycle and active-workflow status.
creating, idle, withdrawal_active, rebalance_active, withdrawal_and_rebalance_active, failed Deposit addresses keyed by chain. Sandbox wallets use ethereum_sepolia and solana_devnet, plus tron_shasta and stellar_testnet; production wallets use arbitrum, base, ethereum, polygon, and solana, plus tron and stellar. New wallets prepare Stellar automatically in the background; only ready addresses are returned. Production wallets also prepare tempo (USDC.e); its address is returned only after setup and deposit monitoring are ready. The Tempo address can differ from the Ethereum address. Tempo is not available in sandbox.
Show child attributes
Show child attributes
{
"arbitrum": "0xAbC1230000000000000000000000000000000001",
"base": "0xAbC1230000000000000000000000000000000001",
"ethereum": "0xAbC1230000000000000000000000000000000001",
"polygon": "0xAbC1230000000000000000000000000000000001",
"solana": "7vFgKxM3bP4oEFbqkPmA5E2rYJ8HqKz8abc1",
"stellar": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF",
"tron": "TBXSw8fM4jpQkGc6zZjsVABFpVN7UvXPdV"
}
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Percentage targets when automatic rebalancing is enabled. Always null when it is disabled.
Show child attributes
Show child attributes