Skip to content

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" | jq

Verify 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" | jq

The success condition for this internal payment is:

  • success: true
  • request_type: "INTERNAL"
  • status: "COMPLETED"
  • user_status: "COMPLETED"

Next: Record payment results.

OOLIN is a digital asset operations infrastructure product by BPMG.