English
Move Assets Between Accounts
An offline payment is an internal transfer from the customer's USER account to the merchant's BUSINESS payment account.
Check the customer balance
bash
wallet_request GET "/accounts/$USER_ACCOUNT_ID/balances/$ASSET_TYPE_ID" | jqVerify available_amount_raw is sufficient for the order amount before submitting the payment.
Create a unique payment request
client_request_id must be unique across internal transfers and external withdrawals. Generate one ID per order and never reuse it for another operation.
Persist the generated PAYMENT_REQUEST_ID with the order ID, accounts, asset, and amount before sending the request. When recovering the same order, use the stored ID rather than running the ID-generation code again. Add PAYMENT_WITHDRAWAL_ID after receiving the response.
bash
export PAYMENT_AMOUNT='1.00'
export PAYMENT_REQUEST_ID="payment-$(node -e 'process.stdout.write(require("crypto").randomUUID())')"
payment_body="$(jq -nc \
--argjson from_account_id "$USER_ACCOUNT_ID" \
--argjson to_account_id "$PAYMENT_ACCOUNT_ID" \
--argjson asset_type_id "$ASSET_TYPE_ID" \
--arg amount "$PAYMENT_AMOUNT" \
--arg client_request_id "$PAYMENT_REQUEST_ID" \
'{from_account_id:$from_account_id,to_account_id:$to_account_id,asset_type_id:$asset_type_id,amount:$amount,client_request_id:$client_request_id}')"
payment_response="$(wallet_request POST '/withdrawals/internal' "$payment_body")"
printf '%s\n' "$payment_response" | jq
export PAYMENT_WITHDRAWAL_ID="$(printf '%s' "$payment_response" | jq -r '.data.withdrawal_id')"Store both PAYMENT_REQUEST_ID and PAYMENT_WITHDRAWAL_ID with the order. Despite the endpoint name, this record represents the internal movement used as the payment.
Do not infer success from the create response
The returned ID proves that a transaction record exists. Confirm its state before marking the order as paid.
bash
wallet_request GET "/withdrawals/$PAYMENT_WITHDRAWAL_ID" | jqThe success condition for this internal payment is:
success: truerequest_type: "INTERNAL"status: "COMPLETED"user_status: "COMPLETED"
Next: Record payment results.