Skip to content

Preview First Deposit

Read-only dry-run for the card-open first deposit. It computes exactly what /card/apply would charge for a given first_deposit_amount — the fee on the excess, the amount credited to the card, and the total wallet freeze — without opening a card, writing anything, or freezing funds.

Use it to render a "what you'll pay" breakdown before the customer confirms, so the numbers match the real open 1:1.

What is the first deposit?

The card config defines a base initial deposit (base_amount) that is credited 1:1 with no fee. A merchant may top this up by sending a larger first_deposit_amount on apply; the part above the base (the excess) is charged a recharge-style fee, and the remainder is credited to the card 1:1 (USDT/USD, no FX). The final first deposit sent to the provider is always an integer.

The config may additionally set a minimum first deposit (min_first_deposit_amount, always ≥ base_amount): the total first_deposit_amount must be at least that value, while only the base part stays fee-free. Example: base_amount=10, min_first_deposit_amount=500 → the customer must deposit at least 500, of which 10 is fee-free and 490 is charged the recharge fee.

Endpoint

ItemValue
MethodPOST
Path/api/v1/openapi/card/first_deposit/preview
AuthHMAC
IdempotencyNot required (read-only)

Request Fields

FieldTypeRequiredDescription
header_idstringhdr_<id> (List Card Headers)
package_idstringpkg_<id> (List Card Configs)
first_deposit_amountstringoptionalTotal first deposit, non-negative integer, in the pay/recharge asset unit (e.g. USDT). Empty = use the config base. Must be >= min_first_deposit_amount (which is itself >= base_amount); when the minimum is above the base, an empty value is rejected with first_recharge_below_min. Scientific notation, decimals, and signs are rejected.

Example Request

json
{
  "header_id": "hdr_119",
  "package_id": "pkg_33",
  "first_deposit_amount": "16"
}

Response Fields

Always 200 (graceful)

This endpoint returns 200 even when the amount is not submittable. Read is_valid to decide whether apply would succeed, and invalid_reason for the stable reason code. Only malformed IDs, an unsupported card type, or a server fault return non-200.

FieldTypeDescription
package_idstringEcho, pkg_<id>
card_typestringLowercase business code, e.g. virtual_v
currencystringCard currency (e.g. USD)
pay_asset_symbolstringPay/recharge asset symbol (e.g. USDT)
open_card_feestring (decimal)Open-card fee (pay asset)
base_amountstring (decimal)Base initial deposit — credited 1:1, no fee
min_first_deposit_amountstring (decimal)Effective minimum total first deposit (max(base_amount, package/header minimum)), base included. first_deposit_amount must be ≥ this; when it is above base_amount the empty default (base) is rejected
request_amountstring (decimal)The total first deposit being evaluated
excess_amountstring (decimal)Excess above base (request_amount − base_amount)
excess_fee_amountstring (decimal)Fee charged on the excess (fee asset)
excess_fee_asset_symbolstringFee asset symbol (omitted when no excess)
excess_settle_amountstring (decimal)Excess after fee, before integer rounding
excess_card_amountstring (decimal)Excess actually credited to the card (after rounding)
exchange_ratestringCompatibility field; USDT/USD is 1:1, always empty
first_recharge_cardstring (decimal)Total credited to the card (base + excess credited); integer
total_freezestring (decimal)Total wallet freeze in the pay asset (open_card_fee + amount credited + excess fee + deposit when deposit_in_total_freeze=true); rounding remainder is not charged
deposit_requiredboolWhether this application will freeze a card-open deposit (same gate decision as /card/apply: mode 2 always; mode 3 only when KYC is not yet passed; mode 4 after KYC passes)
deposit_amountstring (decimal)Deposit amount in the deposit asset; "0" when no deposit
deposit_asset_symbolstringDeposit asset symbol (e.g. USDT / USD); empty when no deposit
deposit_refund_daysintDays after card closure before the deposit refund can be requested (0 = enters refund review right after closure)
deposit_in_total_freezebooltrue = deposit asset equals the pay asset and the deposit is already included in total_freeze; false = not included (no deposit, or a different asset — show it separately)
deposit_wallet_balancestring (decimal)Available balance of the deposit asset; "0" when no deposit
deposit_wallet_balance_sufficientboolWhether the deposit freeze would succeed, simulated in the real apply order (open fee + first deposit first, then deposit; USDT topped up 1:1 from USD); always true when no deposit
fee_typeintRecharge fee type: 1=fixed 2=percent 3=mixed
fee_ratestringRate (percent / mixed); omitted otherwise
fee_fixedstringFixed fee (fixed / mixed); omitted otherwise
min_recharge_amountstring (decimal)Config min recharge (display)
max_recharge_amountstring (decimal)Config max recharge — the excess is capped by this
wallet_balancestring (decimal)Your account's available balance in the pay asset
wallet_balance_sufficientboolWhether the balance (incl. USD 1:1 top-up) covers total_freeze
usd_balancestring (decimal)Your USD balance (used only for the USDT→USD 1:1 top-up check)
will_use_usdboolWhether the USD 1:1 top-up would be used
usd_neededstring (decimal)USD amount that would be drawn via the top-up
is_validboolWhether apply would be accepted with this amount
invalid_reasonstringStable reason code when is_valid=false (omitted when valid)
warningsstring[]Optional advisory codes

Example Response (valid)

json
{
  "code": 200,
  "message": "OK",
  "data": {
    "package_id": "pkg_33",
    "card_type": "virtual_v",
    "currency": "USD",
    "pay_asset_symbol": "USDT",
    "open_card_fee": "1.000000000000000000",
    "base_amount": "10",
    "min_first_deposit_amount": "10",
    "request_amount": "16",
    "excess_amount": "6",
    "excess_fee_amount": "1.22",
    "excess_fee_asset_symbol": "USDT",
    "excess_settle_amount": "4.78",
    "excess_card_amount": "4",
    "first_recharge_card": "14",
    "total_freeze": "16.22",
    "deposit_required": false,
    "deposit_amount": "0",
    "deposit_asset_symbol": "",
    "deposit_refund_days": 0,
    "deposit_in_total_freeze": false,
    "deposit_wallet_balance": "0",
    "deposit_wallet_balance_sufficient": true,
    "fee_type": 3,
    "fee_rate": "0.020000",
    "fee_fixed": "1.100000000000000000",
    "min_recharge_amount": "10.000000000000000000",
    "max_recharge_amount": "100.000000000000000000",
    "wallet_balance": "70.82999088",
    "wallet_balance_sufficient": true,
    "usd_balance": "0",
    "will_use_usd": false,
    "usd_needed": "0",
    "is_valid": true
  }
}

In this example a 16 first deposit on a base=10 config keeps 10 free (1:1), and the 6 excess is charged a 1.22 fee, leaving 4 credited — so the card receives 14 and the wallet is frozen 16.22.

Example Response (not submittable)

json
{
  "code": 200,
  "message": "OK",
  "data": {
    "package_id": "pkg_33",
    "card_type": "virtual_v",
    "is_valid": false,
    "invalid_reason": "first_recharge_exceeds_max",
    "base_amount": "10",
    "min_first_deposit_amount": "10",
    "request_amount": "9999",
    "max_recharge_amount": "100.000000000000000000"
  }
}

invalid_reason Codes

is_valid=false is paired with one of these stable codes (same keys returned as message_key by apply):

invalid_reasonMeaning
invalid_first_deposit_amountNot a plain non-negative integer (decimals / signs / scientific notation / too many digits)
first_recharge_below_baseAmount below base_amount
first_recharge_below_minAmount below min_first_deposit_amount (also returned when first_deposit_amount is omitted and the minimum is above the base)
first_recharge_exceeds_maxExcess exceeds max_recharge_amount
first_recharge_limit_exceededExcess exceeds the account's recharge limit
first_recharge_asset_mismatchOpen-fee asset ≠ recharge asset; custom excess unsupported for this config
first_recharge_excess_too_smallAfter fee + integer rounding nothing reaches the card; increase the amount
insufficient_balanceWallet (incl. USD top-up) can't cover total_freeze
kyc_requiredKYC is a hard gate for this card and the account has not passed it (same rejection /card/apply would return)
card_deposit_config_invalidThe gate mode requires a deposit but the deposit is not fully configured on the platform side; nobody can open this card until it is fixed
card_deposit_insufficient_balanceBalance of the deposit asset can't cover deposit_amount (only when the deposit asset differs from the pay asset)
bank_card_config_not_foundPackage inactive / not found
bank_card_header_not_foundHeader inactive / not found

Common Errors

Non-200 responses (malformed input / unsupported type / server fault):

HTTPmessage_keyDescription
400openapi_invalid_header_idheader_id missing / wrong prefix / not found
400openapi_invalid_package_idpackage_id missing / wrong prefix
400openapi_card_type_not_supportedHeader's card type not in the virtual range
400account_manager_bind_required / account_manager_unavailable / account_manager_open_disabledAccount-manager-controlled header your account cannot apply for (same rule as apply)
401openapi_invalid_credentialsAuth failure
500openapi_first_deposit_preview_failedServer error

Notes

  • Numbers match apply exactly. The preview shares the open-card computation, so total_freeze / first_recharge_card are the same values apply will charge for the same first_deposit_amount.
  • No money moves. This call freezes nothing and writes nothing; safe to call as often as needed (subject to rate limits).
  • wallet_balance is your own account balance — no other party's data is exposed.
  • The excess fee uses the same recharge fee formula as Create Recharge; the formula is also available per package via List Card Configs.

Released under MIT-equivalent terms.