curl --request POST \
--url https://sandbox.groundtech.co/v2/wallets/{id}/withdrawal-preview \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"destinationChain": "arbitrum",
"amountUsd": 50,
"token": "usdc",
"partnerFeeAmountUsd": 0.5,
"partnerFeeRecipientAddress": "0x1111111111111111111111111111111111111111"
}
'import requests
url = "https://sandbox.groundtech.co/v2/wallets/{id}/withdrawal-preview"
payload = {
"destinationChain": "arbitrum",
"amountUsd": 50,
"token": "usdc",
"partnerFeeAmountUsd": 0.5,
"partnerFeeRecipientAddress": "0x1111111111111111111111111111111111111111"
}
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({
destinationChain: 'arbitrum',
amountUsd: 50,
token: 'usdc',
partnerFeeAmountUsd: 0.5,
partnerFeeRecipientAddress: '0x1111111111111111111111111111111111111111'
})
};
fetch('https://sandbox.groundtech.co/v2/wallets/{id}/withdrawal-preview', 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/{id}/withdrawal-preview",
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([
'destinationChain' => 'arbitrum',
'amountUsd' => 50,
'token' => 'usdc',
'partnerFeeAmountUsd' => 0.5,
'partnerFeeRecipientAddress' => '0x1111111111111111111111111111111111111111'
]),
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/{id}/withdrawal-preview"
payload := strings.NewReader("{\n \"destinationChain\": \"arbitrum\",\n \"amountUsd\": 50,\n \"token\": \"usdc\",\n \"partnerFeeAmountUsd\": 0.5,\n \"partnerFeeRecipientAddress\": \"0x1111111111111111111111111111111111111111\"\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/{id}/withdrawal-preview")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"destinationChain\": \"arbitrum\",\n \"amountUsd\": 50,\n \"token\": \"usdc\",\n \"partnerFeeAmountUsd\": 0.5,\n \"partnerFeeRecipientAddress\": \"0x1111111111111111111111111111111111111111\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sandbox.groundtech.co/v2/wallets/{id}/withdrawal-preview")
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 \"destinationChain\": \"arbitrum\",\n \"amountUsd\": 50,\n \"token\": \"usdc\",\n \"partnerFeeAmountUsd\": 0.5,\n \"partnerFeeRecipientAddress\": \"0x1111111111111111111111111111111111111111\"\n}"
response = http.request(request)
puts response.read_body{
"amountRequestedUsd": "50.000000",
"feeUsd": "0.001000",
"partnerFeeUsd": "0.500000",
"amountToReceiveUsd": "49.499000",
"withdrawableUsd": "1000.000000",
"totalUsdAfterWithdrawal": "950.000000",
"processingEstimate": {
"basis": "elapsed_seconds",
"typicalMinDuration": "PT21M",
"typicalMaxDuration": "PT21M"
}
}{
"error": "Unauthenticated request",
"message": "Missing or invalid bearer token"
}{
"error": "Wallet not found",
"code": "wallet_not_found"
}{
"error": "Requested amount exceeds available balance for this destination",
"code": "insufficient_funds",
"amountRequestedUsd": "50.000000",
"balance": {
"totalUsd": "800.000000",
"withdrawableUsd": "700.000000",
"reservedUsd": "100.000000"
}
}{
"error": "Rate limit exceeded",
"code": "rate_limited"
}{
"error": "Internal server error",
"code": "internal_error"
}Preview a withdrawal
Shows how much can be withdrawn and checks an optional amount, destination, token, and set of source positions.
curl --request POST \
--url https://sandbox.groundtech.co/v2/wallets/{id}/withdrawal-preview \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"destinationChain": "arbitrum",
"amountUsd": 50,
"token": "usdc",
"partnerFeeAmountUsd": 0.5,
"partnerFeeRecipientAddress": "0x1111111111111111111111111111111111111111"
}
'import requests
url = "https://sandbox.groundtech.co/v2/wallets/{id}/withdrawal-preview"
payload = {
"destinationChain": "arbitrum",
"amountUsd": 50,
"token": "usdc",
"partnerFeeAmountUsd": 0.5,
"partnerFeeRecipientAddress": "0x1111111111111111111111111111111111111111"
}
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({
destinationChain: 'arbitrum',
amountUsd: 50,
token: 'usdc',
partnerFeeAmountUsd: 0.5,
partnerFeeRecipientAddress: '0x1111111111111111111111111111111111111111'
})
};
fetch('https://sandbox.groundtech.co/v2/wallets/{id}/withdrawal-preview', 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/{id}/withdrawal-preview",
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([
'destinationChain' => 'arbitrum',
'amountUsd' => 50,
'token' => 'usdc',
'partnerFeeAmountUsd' => 0.5,
'partnerFeeRecipientAddress' => '0x1111111111111111111111111111111111111111'
]),
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/{id}/withdrawal-preview"
payload := strings.NewReader("{\n \"destinationChain\": \"arbitrum\",\n \"amountUsd\": 50,\n \"token\": \"usdc\",\n \"partnerFeeAmountUsd\": 0.5,\n \"partnerFeeRecipientAddress\": \"0x1111111111111111111111111111111111111111\"\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/{id}/withdrawal-preview")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"destinationChain\": \"arbitrum\",\n \"amountUsd\": 50,\n \"token\": \"usdc\",\n \"partnerFeeAmountUsd\": 0.5,\n \"partnerFeeRecipientAddress\": \"0x1111111111111111111111111111111111111111\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sandbox.groundtech.co/v2/wallets/{id}/withdrawal-preview")
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 \"destinationChain\": \"arbitrum\",\n \"amountUsd\": 50,\n \"token\": \"usdc\",\n \"partnerFeeAmountUsd\": 0.5,\n \"partnerFeeRecipientAddress\": \"0x1111111111111111111111111111111111111111\"\n}"
response = http.request(request)
puts response.read_body{
"amountRequestedUsd": "50.000000",
"feeUsd": "0.001000",
"partnerFeeUsd": "0.500000",
"amountToReceiveUsd": "49.499000",
"withdrawableUsd": "1000.000000",
"totalUsdAfterWithdrawal": "950.000000",
"processingEstimate": {
"basis": "elapsed_seconds",
"typicalMinDuration": "PT21M",
"typicalMaxDuration": "PT21M"
}
}{
"error": "Unauthenticated request",
"message": "Missing or invalid bearer token"
}{
"error": "Wallet not found",
"code": "wallet_not_found"
}{
"error": "Requested amount exceeds available balance for this destination",
"code": "insufficient_funds",
"amountRequestedUsd": "50.000000",
"balance": {
"totalUsd": "800.000000",
"withdrawableUsd": "700.000000",
"reservedUsd": "100.000000"
}
}{
"error": "Rate limit exceeded",
"code": "rate_limited"
}{
"error": "Internal server error",
"code": "internal_error"
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Path Parameters
Wallet ID
Body
Target chain for the withdrawal. Use ethereum_sepolia or solana_devnet for sandbox testing.
arbitrum, base, ethereum, ethereum_sepolia, polygon, solana, solana_devnet Stablecoin lane used to validate, fund, rebalance, and withdraw an allocation independently from other token lanes.
usdc, usdt Gross wallet value to withdraw before execution fees. If omitted, the preview uses the maximum gross withdrawable amount.
Optional exact gross source split when automatic rebalancing is disabled. Omit it to let Ground select sources automatically.
1Show child attributes
Show child attributes
Partner-calculated fee for an EVM USDC or USDT withdrawal. Must be positive, smaller than amountUsd when provided, have at most 6 decimal places, and be supplied with partnerFeeRecipientAddress.
x > 0EVM address that receives the partner fee. Must be supplied with partnerFeeAmountUsd.
Response
Withdrawal preview
Gross wallet value evaluated by this preview. Equals the requested amount, or the resolved maximum gross withdrawable amount when amountUsd was omitted.
Estimated execution fee deducted from the gross requested amount, including yield source protocol exit fees.
Partner fee deducted from the gross requested amount.
Estimated net amount to be sent to the destination after execution and partner fees are deducted from the gross requested amount.
Maximum gross wallet value that can safely start a new withdrawal for this destination right now.
Estimated wallet total after the gross requested amount is removed.
- Option 1
- Option 2
Show child attributes
Show child attributes