Poll until wallet is ready
After creating a wallet, pollGET /v2/wallets/{id} every 1-2 seconds until status !== "creating":
cURL
while true; do
STATUS=$(curl -s "$BASE_URL/v2/wallets/$WALLET_ID" \
-H "Authorization: Bearer $GROUND_API_KEY" | jq -r .status)
if [ "$STATUS" = "idle" ] || [ "$STATUS" = "failed" ]; then break; fi
sleep 1.5
done
async function waitUntilReady(walletId, apiToken) {
while (true) {
const res = await fetch(`${BASE_URL}/v2/wallets/${walletId}`, {
headers: { Authorization: `Bearer ${apiToken}` },
});
const wallet = await res.json();
if (wallet.status === "idle") return wallet;
if (wallet.status === "failed") {
throw new Error(`wallet ${walletId} failed: ${wallet.failureReason}`);
}
await new Promise((r) => setTimeout(r, 1500));
}
}
import time, requests
def wait_until_ready(wallet_id, api_token):
while True:
r = requests.get(
f"{BASE_URL}/v2/wallets/{wallet_id}",
headers={"Authorization": f"Bearer {api_token}"},
)
wallet = r.json()
if wallet["status"] == "idle":
return wallet
if wallet["status"] == "failed":
raise RuntimeError(f"wallet {wallet_id} failed: {wallet['failureReason']}")
time.sleep(1.5)
List wallets
cURL
curl -X GET "$BASE_URL/v2/wallets?limit=25" \
-H "Authorization: Bearer $GROUND_API_KEY"
const res = await fetch(`${BASE_URL}/v2/wallets?limit=25`, {
headers: { Authorization: `Bearer ${GROUND_API_KEY}` },
});
console.log(await res.json());
import requests
res = requests.get(
f"{BASE_URL}/v2/wallets?limit=25",
headers={"Authorization": f"Bearer {GROUND_API_KEY}"},
)
print(res.json())
cURL
curl -X GET "$BASE_URL/v2/wallets?limit=25&cursor=$NEXT_CURSOR" \
-H "Authorization: Bearer $GROUND_API_KEY"
const res = await fetch(`${BASE_URL}/v2/wallets?limit=25&cursor=${NEXT_CURSOR}`, {
headers: { Authorization: `Bearer ${GROUND_API_KEY}` },
});
console.log(await res.json());
import requests
res = requests.get(
f"{BASE_URL}/v2/wallets?limit=25&cursor={NEXT_CURSOR}",
headers={"Authorization": f"Bearer {GROUND_API_KEY}"},
)
print(res.json())
Get a single wallet
cURL
curl -X GET "$BASE_URL/v2/wallets/$WALLET_ID" \
-H "Authorization: Bearer $GROUND_API_KEY"
const res = await fetch(`${BASE_URL}/v2/wallets/${WALLET_ID}`, {
headers: { Authorization: `Bearer ${GROUND_API_KEY}` },
});
console.log(await res.json());
import requests
res = requests.get(
f"{BASE_URL}/v2/wallets/{WALLET_ID}",
headers={"Authorization": f"Bearer {GROUND_API_KEY}"},
)
print(res.json())
List deposits
cURL
curl -X GET "$BASE_URL/v2/wallets/$WALLET_ID/deposits?limit=50" \
-H "Authorization: Bearer $GROUND_API_KEY"
const res = await fetch(`${BASE_URL}/v2/wallets/${WALLET_ID}/deposits?limit=50`, {
headers: { Authorization: `Bearer ${GROUND_API_KEY}` },
});
console.log(await res.json());
import requests
res = requests.get(
f"{BASE_URL}/v2/wallets/{WALLET_ID}/deposits?limit=50",
headers={"Authorization": f"Bearer {GROUND_API_KEY}"},
)
print(res.json())
Activity feed
The activity endpoint provides a unified, reverse-chronological feed of customer-visible deposits, withdrawals, and rebalances. Usescope=all for organization-wide activity, or pass one or more walletId parameters to filter to specific wallets.
cURL
curl -X GET "$BASE_URL/v2/activity?walletId=$WALLET_ID&limit=20" \
-H "Authorization: Bearer $GROUND_API_KEY"
const res = await fetch(`${BASE_URL}/v2/activity?walletId=${WALLET_ID}&limit=20`, {
headers: { Authorization: `Bearer ${GROUND_API_KEY}` },
});
console.log(await res.json());
import requests
res = requests.get(
f"{BASE_URL}/v2/activity?walletId={WALLET_ID}&limit=20",
headers={"Authorization": f"Bearer {GROUND_API_KEY}"},
)
print(res.json())
| Param | Description |
|---|---|
limit | Max items per page. Runtime clamps invalid, missing, and oversized values into the supported 1-100 range. |
cursor | Opaque cursor from nextCursor for pagination |
walletId | Optional repeatable wallet ID filter. |
scope | Optional all for organization-wide activity. |
type | Optional type filter: deposit, withdrawal, or rebalance |
status | Optional comma-separated status filter: created, processing, completed, partially_completed, failed, cancelled, or all |
startAt | Optional inclusive ISO-8601 UTC lower bound for activity timestamps. |
endAt | Optional exclusive ISO-8601 UTC upper bound for activity timestamps. |
curl -X GET "$BASE_URL/v2/activity?walletId=$WALLET_ID&status=created,processing&limit=20" \
-H "Authorization: Bearer $GROUND_API_KEY"
{
"data": [
{
"id": "8f9720c1-2679-4d56-afc3-9b18edb83ce2",
"type": "deposit",
"status": "completed",
"amountUsd": "5000.000000",
"timestamp": "2026-02-05T09:40:00.000Z",
"deposit": {
"id": "8f9720c1-2679-4d56-afc3-9b18edb83ce2",
"amount": "5000.000000",
"token": "usdc",
"chain": "ethereum",
"fromAddress": "0xfeed00000000000000000000000000000000beef",
"txHash": "0xabc123...",
"status": "completed",
"createdAt": "2026-02-05T09:40:00.000Z",
"completedAt": "2026-02-05T09:41:15.000Z"
}
},
{
"id": "11b17950-1f5c-4d36-8f0d-0f3d1d0c6a45",
"type": "withdrawal",
"status": "processing",
"amountUsd": "65000.000000",
"timestamp": "2026-02-05T11:00:00.000Z",
"withdrawal": {
"id": "11b17950-1f5c-4d36-8f0d-0f3d1d0c6a45",
"amountRequestedUsd": "65000.000000",
"amountPaidUsd": null,
"feeUsd": "0.000000",
"destinationChain": "ethereum",
"destinationAddress": "0x76F8fc6667E239f83a547d4e16225d6a34f6FA22",
"destinationToken": "usdc",
"status": "processing",
"legsCompleted": 0,
"legsTotal": 1,
"payoutLegs": [
{
"status": "pending_customer_approval",
"amountUsd": "65000.000000",
"from": { "kind": "yield_source", "id": "syrup-usdc", "label": "Syrup USDC" },
"to": { "kind": "external_payout", "id": "external_payout:ethereum:usdc", "label": "External payout (Ethereum)" },
"startedAt": "2026-02-05T11:00:00.000Z",
"completedAt": null,
"stepsCompleted": 1,
"stepsTotal": 2,
"steps": [
{
"name": "Redeeming from Syrup USDC",
"stepKind": "yield_source_redeem",
"sequenceRole": "yield_redeem",
"protocolType": "syrup",
"stepOrdinal": 0,
"chain": "ethereum",
"txKind": "yield_source_redeem",
"state": "completed",
"startedAt": "2026-02-05T11:01:00.000Z",
"completedAt": "2026-02-05T11:02:00.000Z",
"cancelledAt": null
},
{
"name": "Sending payout",
"stepKind": "external_payout_transfer",
"sequenceRole": "external_payout_transfer",
"protocolType": "external_payout",
"stepOrdinal": 1,
"chain": "ethereum",
"txKind": "external_payout_transfer",
"state": "pending_customer_approval",
"startedAt": "2026-02-05T11:03:00.000Z",
"completedAt": null,
"cancelledAt": null
}
]
}
],
"failureReason": null,
"createdAt": "2026-02-05T11:00:00.000Z",
"completedAt": null
}
},
{
"id": "449f9ed4-b924-4a2d-9b18-e372cc5c4d65",
"type": "rebalance",
"status": "created",
"amountUsd": "12000.000000",
"timestamp": "2026-02-05T12:00:00.000Z",
"rebalance": {
"id": "449f9ed4-b924-4a2d-9b18-e372cc5c4d65",
"status": "created",
"createdAt": "2026-02-05T12:00:00.000Z",
"updatedAt": "2026-02-05T12:00:00.000Z",
"startedAt": "2026-02-05T12:00:00.000Z",
"completedAt": null,
"legsCompleted": 0,
"legsTotal": 1,
"amountUsd": "12000.000000",
"rebalanceLegs": [
{
"status": "created",
"amountUsd": "12000.000000",
"from": { "kind": "cash", "id": "cash:base:usdc", "label": "Cash (Base)" },
"to": { "kind": "yield_source", "id": "morpho-gauntlet-usdc", "label": "Morpho Gauntlet USDC Prime" },
"startedAt": "2026-02-05T12:00:00.000Z",
"completedAt": null,
"stepsCompleted": 0,
"stepsTotal": 1,
"steps": [
{
"name": "Depositing into Morpho Gauntlet USDC Prime",
"stepKind": "yield_source_deposit",
"sequenceRole": "yield_deposit",
"protocolType": "morpho",
"stepOrdinal": 0,
"chain": "ethereum",
"txKind": "yield_source_deposit",
"state": "created",
"startedAt": null,
"completedAt": null,
"cancelledAt": null
}
]
}
],
"failureReason": null
}
}
],
"nextCursor": null
}
nextCursor as cursor to fetch the next page. See API
Conventions for the list envelope.
| Field | Description |
|---|---|
data | Activity items for the current page. |
data[].id | Unique ID for the activity parent |
data[].type | "deposit", "withdrawal", or "rebalance" |
data[].status | Public status: created, processing, completed, failed, or cancelled |
data[].amountUsd | Amount as a fixed-precision decimal string (6 decimal places) |
data[].timestamp | ISO-8601 timestamp of when the activity occurred |
data[].deposit | Present for deposit rows |
data[].withdrawal | Present for withdrawal rows |
data[].rebalance | Present for rebalance rows |
nextCursor | Opaque cursor for the next page, or null |
List withdrawals
Filter by status to monitor in-flight withdrawals:cURL
curl -X GET "$BASE_URL/v2/wallets/$WALLET_ID/withdrawals?status=processing&limit=50" \
-H "Authorization: Bearer $GROUND_API_KEY"
const res = await fetch(
`${BASE_URL}/v2/wallets/${WALLET_ID}/withdrawals?status=processing&limit=50`,
{ headers: { Authorization: `Bearer ${GROUND_API_KEY}` } },
);
console.log(await res.json());
import requests
res = requests.get(
f"{BASE_URL}/v2/wallets/{WALLET_ID}/withdrawals",
params={"status": ["processing"], "limit": 50},
headers={"Authorization": f"Bearer {GROUND_API_KEY}"},
)
print(res.json())