Funding a Client Balance
Request an ephemeral DLT deposit address with POST /client/balance/fund, send the asset, and Movmint credits your prefunded balance after settlement and compliance screening.
Overview
Funding is a two-part flow: request a deposit address, then send the asset to it. POST /client/balance/fund returns an ephemeral DLT deposit address for a given asset and network. When your deposit is detected it is recorded to pending_balance; once it confirms on-chain and clears TRM screening, it moves to available_balance.
POST https://api.sandbox.movmint.io/client/balance/fund
Authorization: Bearer <access_token>
x-idempotency-key: <uuid>
Content-Type: application/json
sequenceDiagram
participant App as Your Application
participant API as Movmint
participant Chain as DLT Network
App->>API: POST /client/balance/fund (asset, network)
API-->>App: deposit_address + client_account_id + expires_at
App->>Chain: Send asset to deposit_address
Chain-->>API: Deposit detected -> pending_balance
Note over API: Confirm on-chain + TRM screening
API-->>App: Settled -> available_balance
Request
| Field | Required | Description |
|---|---|---|
asset | yes | Asset/currency code to fund (e.g., USDC, EURC, BTC, ETH). |
network | yes | DLT network for the deposit: ethereum, base, solana, bitcoin, or sanddollar. |
The asset/network pairing must be valid (e.g., USDC on ethereum) and covered by an active Product subscription.
Code examples
cURL
curl -X POST https://api.sandbox.movmint.io/client/balance/fund \
-H "Authorization: Bearer <access_token>" \
-H "x-idempotency-key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"asset": "USDC", "network": "ethereum"}'Go
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"github.com/google/uuid"
)
const baseURL = "https://api.sandbox.movmint.io"
func main() {
token := "<access_token>"
payload, _ := json.Marshal(map[string]string{"asset": "USDC", "network": "ethereum"})
req, _ := http.NewRequest(http.MethodPost, baseURL+"/client/balance/fund", bytes.NewReader(payload))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("x-idempotency-key", uuid.NewString())
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
log.Fatalf("fund request failed (%d): %s", resp.StatusCode, body)
}
fmt.Println(string(body))
}TypeScript
import { randomUUID } from "crypto";
const BASE_URL = "https://api.sandbox.movmint.io";
async function requestFundingAddress(token: string, asset: string, network: string) {
const res = await fetch(`${BASE_URL}/client/balance/fund`, {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"x-idempotency-key": randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify({ asset, network }),
});
if (!res.ok) {
throw new Error(`Fund request failed (${res.status}): ${await res.text()}`);
}
return res.json();
}
console.log(await requestFundingAddress("<access_token>", "USDC", "ethereum"));Java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.UUID;
public class FundBalance {
private static final String BASE_URL = "https://api.sandbox.movmint.io";
public static void main(String[] args) throws Exception {
String token = "<access_token>";
String payload = "{\"asset\": \"USDC\", \"network\": \"ethereum\"}";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/client/balance/fund"))
.header("Authorization", "Bearer " + token)
.header("x-idempotency-key", UUID.randomUUID().toString())
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new RuntimeException("Fund request failed (" + response.statusCode()
+ "): " + response.body());
}
System.out.println(response.body());
}
}Rust
use serde_json::json;
use uuid::Uuid;
const BASE_URL: &str = "https://api.sandbox.movmint.io";
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let token = "<access_token>";
let client = reqwest::Client::new();
let resp = client
.post(format!("{BASE_URL}/client/balance/fund"))
.bearer_auth(token)
.header("x-idempotency-key", Uuid::new_v4().to_string())
.json(&json!({ "asset": "USDC", "network": "ethereum" }))
.send()
.await?;
if !resp.status().is_success() {
let status = resp.status();
return Err(format!("fund request failed ({status}): {}", resp.text().await?).into());
}
let data: serde_json::Value = resp.json().await?;
println!("{}", serde_json::to_string_pretty(&data)?);
Ok(())
}Python
import uuid
import requests
BASE_URL = "https://api.sandbox.movmint.io"
def request_funding_address(token: str, asset: str, network: str) -> dict:
resp = requests.post(
f"{BASE_URL}/client/balance/fund",
headers={
"Authorization": f"Bearer {token}",
"x-idempotency-key": str(uuid.uuid4()),
"Content-Type": "application/json",
},
json={"asset": asset, "network": network},
timeout=30,
)
resp.raise_for_status()
return resp.json()
print(request_funding_address("<access_token>", "USDC", "ethereum"))Example response (200)
200){
"client_account_id": "9f1c2d3e-4b5a-6789-abcd-ef0123456789",
"ledger_account": "cl_acmecorp_funds_USDC",
"asset": "USDC",
"network": "ethereum",
"deposit_address": "0xabc123def4567890abc123def4567890abc12345",
"expires_at": "2026-06-24T13:04:30Z"
}| Field | Description |
|---|---|
client_account_id | The balance account that will be credited. Use it with Get Balances and Get Transactions. |
ledger_account | The underlying ledger account name (cl_{CLIENTNAME}_funds_{ASSET}). |
asset / network | Echo of the requested asset and network. |
deposit_address | The ephemeral address to send the asset to. |
expires_at | After this time the address is no longer monitored — request a new one. |
After you send funds
- Send the asset to
deposit_addresson the specifiednetworkbeforeexpires_at. - Detection →
pending_balance. Once the deposit is seen on-chain, the amount appears inpending_balance. - Settlement →
available_balance. After on-chain confirmation and a clean TRM screening, funds move toavailable_balanceand become usable as aCLIENT_BALANCEsource.
Screening and minimumsAll funding deposits are screened by TRM Labs before settlement; a flagged deposit is held for compliance review and not credited. Deposits below a configured per-asset minimum may also be held. Send from addresses you control and meet the minimum to avoid holds.
Error responses
| HTTP | Cause |
|---|---|
400 | Invalid request — e.g., an unsupported asset/network pairing. |
402 | No active Product subscription covers the requested asset. |
500 | Internal server error — retry with backoff. |
Next steps
Check your balance with Get Balances, then use client_account_id as a CLIENT_BALANCE source or target in a Quote.
Updated 2 months ago
