Z Zise Developers 简体中文

Sandbox: fund your sandbox prepaid account

POST /v1/sandbox/faucet scope: merchant:read
Merchant account Requires x-idempotency-key Moves funds · Increases merchant prepaid available balance; the counterparty is custody.settled.
This endpoint moves funds

See the response table below for failure handling. Retry timeouts (504) with the same idempotency key — we may already have processed the request; use a new key after a business failure; the same key replays that failure.

Available only in the sandbox. Live credentials return 404, not 403, because this capability must not exist in production. The check is whether the merchant resolved from the token is a shadow entity, not the hostname being called.

It uses the exact production posting path, exercising funding gates, queues, low-balance thresholds, and ledger invariants. An endpoint that simply changed a balance could not verify those.

The input amount and output credited are decimal strings, such as "500.000000", unlike the fixed-point integer strings in /v1/merchant/balances. The default credit is 10000 whole units of the asset; the maximum per request is 1,000,000 units. An endpoint allowing a credit of 10^30 at once would produce limit behavior unlike production.

Idempotency: reusing the same x-idempotency-key returns the same credit with duplicated: true. In that case no new posting occurs; do not count it as another credit.

Prerequisites

  • The current token resolves to a sandbox shadow entity; live credentials always return 404.
  • The asset exists in assets and is enabled.
FieldTypeRequiredDescription
x-idempotency-key string Required UUID v4. Missing returns idempotency_key_required; an invalid format returns idempotency_key_invalid; the same key with a different body returns idempotency_key_reused.

Request Body

FieldTypeRequiredDescription
asset string Required Asset code, case-insensitive; the server converts it to uppercase. Unrecognized values return asset_not_allowed.
amount string Optional Amount to credit, a decimal string. Decimal places must not exceed the asset's ledger_scale, except that excess trailing digits are accepted if all are 0. Defaults to 10000 whole units if omitted. Must be positive.USDT(scale 6):"500.000000"

Response

200Credited. duplicated: true means an idempotency hit, with no new posting on this call.
{
  "ok": true,
  "asset": "USDT",
  "credited": "500.000000",
  "ledger_scale": 6,
  "journal_id": "jrn_01J8Z6M2K9QF3H7V0"
}
400invalid_request: body is not JSON, asset missing, or amount invalid/nonpositive. asset_not_allowed: asset is not in the catalog or is disabled. limit_exceeded: more than 1,000,000 whole units in one request; includes limit_type: single.
404Not in the sandbox environment.
409idempotency_key_reused: same key with a different body. idempotency_in_progress: the original request is still being processed.
Request
curl -X POST 'https://api.zinfra.vip/v1/sandbox/faucet' \
  -H 'x-auth-token: Bearer $TOKEN' \
  -H 'x-idempotency-key: $IDEMPOTENCY_KEY' \
  -H 'content-type: application/json' \
  -d '{
    "asset": "USDT",
    "amount": "500.000000"
  }'
const res = await fetch("https://api.zinfra.vip/v1/sandbox/faucet", {
  method: "POST",
  headers: {
    "x-auth-token": "Bearer $TOKEN",
    "x-idempotency-key": "$IDEMPOTENCY_KEY",
    "content-type": "application/json",
  },
  body: JSON.stringify({
    "asset": "USDT",
    "amount": "500.000000"
  }),
});
// Keep monetary amounts as strings, never numbers.
const data = await res.json();
import requests

res = requests.post(
    "https://api.zinfra.vip/v1/sandbox/faucet",
    headers={
        "x-auth-token": "Bearer $TOKEN",
        "x-idempotency-key": "$IDEMPOTENCY_KEY",
        "content-type": "application/json",
    },
    json={
      "asset": "USDT",
      "amount": "500.000000"
    },
)
# Use Decimal(str(...)) for amounts, not float.
data = res.json()
req, _ := http.NewRequest("POST", "https://api.zinfra.vip/v1/sandbox/faucet",
    strings.NewReader(`{
  "asset": "USDT",
  "amount": "500.000000"
}`))
req.Header.Set("x-auth-token", "Bearer $TOKEN")
req.Header.Set("x-idempotency-key", "$IDEMPOTENCY_KEY")
req.Header.Set("content-type", "application/json")
res, err := http.DefaultClient.Do(req)
// Decode amount fields as string, not float64.
HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://api.zinfra.vip/v1/sandbox/faucet"))
    .header("x-auth-token", "Bearer $TOKEN")
    .header("x-idempotency-key", "$IDEMPOTENCY_KEY")
    .header("content-type", "application/json")
    .method("POST", HttpRequest.BodyPublishers.ofString("""
{
  "asset": "USDT",
  "amount": "500.000000"
}
"""))
    .build();
// Use String / BigDecimal for amounts, not double.
$ch = curl_init('https://api.zinfra.vip/v1/sandbox/faucet');
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'x-auth-token: Bearer $TOKEN',
    'x-idempotency-key: $IDEMPOTENCY_KEY',
    'content-type: application/json',
  ],
  CURLOPT_POSTFIELDS => <<<'JSON'
{
  "asset": "USDT",
  "amount": "500.000000"
}
JSON,
]);
$res = curl_exec($ch);
// Use bcmath / strings for amounts, not floatval.
200
{
  "ok": true,
  "asset": "USDT",
  "credited": "500.000000",
  "ledger_scale": 6,
  "journal_id": "jrn_01J8Z6M2K9QF3H7V0"
}