Quote the fee for a deposit or withdrawal (indicative)
const url = 'https://example.com/v2/fees/quote';const options = { method: 'POST', headers: {'X-CowriePay-Key': '<X-CowriePay-Key>', 'Content-Type': 'application/json'}, body: '{"direction":"deposit","chain":"TRON","asset":"USDT_TRON","amount":"50","mode":"charge"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/v2/fees/quote \ --header 'Content-Type: application/json' \ --header 'X-CowriePay-Key: <X-CowriePay-Key>' \ --data '{ "direction": "deposit", "chain": "TRON", "asset": "USDT_TRON", "amount": "50", "mode": "charge" }'Returns the effective fee, gross and net for a deposit or withdrawal, using the same engine as settlement (tiers, per-workspace overrides, per-chain minimum fee), so a preview matches what is actually charged. The network (mainnet/testnet) is taken from your API key, never from the request.
mode controls the meaning of amount:
-
charge(default):amountis the gross (what the customer sends / what is debited). The responsenetis what you receive. -
gross_up:amountis the net you want to receive. The responsegrossis what the customer must send / what is debited so you net that amount.
Quotes are indicative, the binding fee is computed at settlement (a fee tier can change with your 30-day volume, and an override can expire). For valid input the endpoint always returns 200; an amount too small to leave a positive net is reported as viable: false with an AMOUNT_TOO_SMALL warning, not an error. Read-only, a READ key is sufficient.
Authorizations
Section titled “Authorizations”Request Bodyrequired
Section titled “Request Bodyrequired”object
Base protocol. Network derives from the API key.
Positive decimal in whole asset units (trailing zeros optional; “50” == “50.000000”). In charge mode = gross; in gross_up mode = desired net.
Example
50Responses
Section titled “Responses”Fee quote computed.
Indicative fee quote. All monetary fields are decimal strings (6 dp). The object is open, clients should ignore unknown fields (new fields/warning codes are additive).
object
Full resolved chain (network from the API key).
Echo of the requested amount.
Amount sent by the customer / debited from balance.
CowriePay fee.
Amount you receive / the recipient gets. null when not viable.
Fee / gross, the realised rate (higher than applied_rate when the minimum fee dominates).
Percentage rate used (“0” for withdrawals).
Minimum fee (deposit) or flat fee (withdrawal) used.
Which rule produced the fee.
True when a per-workspace fee override was used.
Fee tier used (null when an override applied).
object
False when the fee is >= the amount (nothing would be credited/sent).
Always true, the binding fee is computed at settlement.
Open list of advisory codes. Known codes: BELOW_SWEEP_MINIMUM, MIN_FEE_DOMINATES, AMOUNT_TOO_SMALL, OVERRIDE_EXPIRES_SOON. Treat unknown codes leniently.
object
Example
{ "direction": "deposit", "chain": "TRON_MAINNET", "asset": "USDT_TRON", "mode": "charge", "fee_basis": "percentage"}Validation error (bad direction/chain/asset/mode, or asset not supported on chain)
object
Human-readable message, for display/logging. Do NOT branch on this text.
Stable, machine-readable error code, branch on this, not the message. Common values: VALIDATION_ERROR, INVALID_JSON, PAYLOAD_TOO_LARGE, MISSING_AUTH_HEADERS, INVALID_SIGNATURE, TIMESTAMP_EXPIRED, REPLAY_DETECTED, INVALID_API_KEY, IP_NOT_ALLOWED, API_KEY_EXPIRED, WORKSPACE_INACTIVE, INSUFFICIENT_SCOPE, NOT_FOUND, CONFLICT, UNPROCESSABLE, INSUFFICIENT_BALANCE, INVALID_DESTINATION_ADDRESS, DESTINATION_IS_INTERNAL, CHAIN_NOT_ENABLED, FAUCET_ONLY_SANDBOX, FAUCET_ADDRESS_NOT_FOUND, FAUCET_INVALID_ASSET, FAUCET_AMOUNT_OVER_CAP, FAUCET_RATE_LIMITED, FAUCET_TOO_MANY_ITEMS, FAUCET_DUPLICATE_ASSET, FAUCET_NATIVE_REQUIRES_DEPOSIT, FAUCET_NATIVE_BUDGET_EXCEEDED, FAUCET_DISPENSER_EXHAUSTED, WITHDRAWAL_NOT_CANCELLABLE, IDEMPOTENCY_CONFLICT, IDEMPOTENCY_MISMATCH, IDEMPOTENCY_KEY_INVALID, FEATURE_NOT_AVAILABLE, RATE_LIMITED, DATABASE_ERROR, INTERNAL_ERROR, UNAUTHORIZED, FORBIDDEN, UNSUPPORTED_MEDIA_TYPE, WITHDRAWALS_FROZEN, WORKSPACE_NOT_FOUND, SYSTEM_WORKSPACE_PROTECTED, FAUCET_INVALID_AMOUNT, FAUCET_NO_ASSETS, FAUCET_NOT_SANDBOX.
Most failures do NOT carry a business code. 326 throw sites raise a generic one (VALIDATION_ERROR, NOT_FOUND, UNPROCESSABLE, UNAUTHORIZED, CONFLICT, FORBIDDEN) against 46 named public codes, so a generic code is the common case and a named one is the exception. Branch on code; treat error as human text that may be reworded. The full catalogue, with causes and next steps, is the Error codes guide.
Example
{ "error": "Insufficient balance. Available: 10.000000, Requested: 50.000000", "code": "INSUFFICIENT_BALANCE"}Invalid or revoked API key / HMAC signature mismatch
object
Human-readable message, for display/logging. Do NOT branch on this text.
Stable, machine-readable error code, branch on this, not the message. Common values: VALIDATION_ERROR, INVALID_JSON, PAYLOAD_TOO_LARGE, MISSING_AUTH_HEADERS, INVALID_SIGNATURE, TIMESTAMP_EXPIRED, REPLAY_DETECTED, INVALID_API_KEY, IP_NOT_ALLOWED, API_KEY_EXPIRED, WORKSPACE_INACTIVE, INSUFFICIENT_SCOPE, NOT_FOUND, CONFLICT, UNPROCESSABLE, INSUFFICIENT_BALANCE, INVALID_DESTINATION_ADDRESS, DESTINATION_IS_INTERNAL, CHAIN_NOT_ENABLED, FAUCET_ONLY_SANDBOX, FAUCET_ADDRESS_NOT_FOUND, FAUCET_INVALID_ASSET, FAUCET_AMOUNT_OVER_CAP, FAUCET_RATE_LIMITED, FAUCET_TOO_MANY_ITEMS, FAUCET_DUPLICATE_ASSET, FAUCET_NATIVE_REQUIRES_DEPOSIT, FAUCET_NATIVE_BUDGET_EXCEEDED, FAUCET_DISPENSER_EXHAUSTED, WITHDRAWAL_NOT_CANCELLABLE, IDEMPOTENCY_CONFLICT, IDEMPOTENCY_MISMATCH, IDEMPOTENCY_KEY_INVALID, FEATURE_NOT_AVAILABLE, RATE_LIMITED, DATABASE_ERROR, INTERNAL_ERROR, UNAUTHORIZED, FORBIDDEN, UNSUPPORTED_MEDIA_TYPE, WITHDRAWALS_FROZEN, WORKSPACE_NOT_FOUND, SYSTEM_WORKSPACE_PROTECTED, FAUCET_INVALID_AMOUNT, FAUCET_NO_ASSETS, FAUCET_NOT_SANDBOX.
Most failures do NOT carry a business code. 326 throw sites raise a generic one (VALIDATION_ERROR, NOT_FOUND, UNPROCESSABLE, UNAUTHORIZED, CONFLICT, FORBIDDEN) against 46 named public codes, so a generic code is the common case and a named one is the exception. Branch on code; treat error as human text that may be reworded. The full catalogue, with causes and next steps, is the Error codes guide.
Example
{ "error": "Insufficient balance. Available: 10.000000, Requested: 50.000000", "code": "INSUFFICIENT_BALANCE"}Rate limit exceeded
object
Human-readable message, for display/logging. Do NOT branch on this text.
Stable, machine-readable error code, branch on this, not the message. Common values: VALIDATION_ERROR, INVALID_JSON, PAYLOAD_TOO_LARGE, MISSING_AUTH_HEADERS, INVALID_SIGNATURE, TIMESTAMP_EXPIRED, REPLAY_DETECTED, INVALID_API_KEY, IP_NOT_ALLOWED, API_KEY_EXPIRED, WORKSPACE_INACTIVE, INSUFFICIENT_SCOPE, NOT_FOUND, CONFLICT, UNPROCESSABLE, INSUFFICIENT_BALANCE, INVALID_DESTINATION_ADDRESS, DESTINATION_IS_INTERNAL, CHAIN_NOT_ENABLED, FAUCET_ONLY_SANDBOX, FAUCET_ADDRESS_NOT_FOUND, FAUCET_INVALID_ASSET, FAUCET_AMOUNT_OVER_CAP, FAUCET_RATE_LIMITED, FAUCET_TOO_MANY_ITEMS, FAUCET_DUPLICATE_ASSET, FAUCET_NATIVE_REQUIRES_DEPOSIT, FAUCET_NATIVE_BUDGET_EXCEEDED, FAUCET_DISPENSER_EXHAUSTED, WITHDRAWAL_NOT_CANCELLABLE, IDEMPOTENCY_CONFLICT, IDEMPOTENCY_MISMATCH, IDEMPOTENCY_KEY_INVALID, FEATURE_NOT_AVAILABLE, RATE_LIMITED, DATABASE_ERROR, INTERNAL_ERROR, UNAUTHORIZED, FORBIDDEN, UNSUPPORTED_MEDIA_TYPE, WITHDRAWALS_FROZEN, WORKSPACE_NOT_FOUND, SYSTEM_WORKSPACE_PROTECTED, FAUCET_INVALID_AMOUNT, FAUCET_NO_ASSETS, FAUCET_NOT_SANDBOX.
Most failures do NOT carry a business code. 326 throw sites raise a generic one (VALIDATION_ERROR, NOT_FOUND, UNPROCESSABLE, UNAUTHORIZED, CONFLICT, FORBIDDEN) against 46 named public codes, so a generic code is the common case and a named one is the exception. Branch on code; treat error as human text that may be reworded. The full catalogue, with causes and next steps, is the Error codes guide.
Example
{ "error": "Insufficient balance. Available: 10.000000, Requested: 50.000000", "code": "INSUFFICIENT_BALANCE"}