Skip to main content

Withdraw & Deposit

Dokumen ini mendeskripsikan endpoint withdraw dan deposit (manual transfer/IDR), termasuk payload dan response sukses/gagal.

Semua response mengikuti envelope di docs/bitwewe/api-conventions.

Withdraw OTP (email)

API v1

  • Method: GET
  • Path: /api/withdraws/otp
  • Controller: App\Http\Controllers\Api\WithdrawController@requestOtp
  • Request: ApiRequest (tanpa payload)
  • Middleware: auth.xtoken, verified:api

Response sukses (200)

Mengirim OTP 4 digit ke email user.

{
"code": 200,
"title": "OK",
"message": "api.withdraw_code_sent_successfully",
"result": true
}

Withdraw coin

API v1

  • Method: POST
  • Path: /api/withdraw/withdraw-coin
  • Controller: App\Http\Controllers\Api\WithdrawController@withdrawCoin
  • Request validation: App\Http\Requests\Api\WithdrawCoinRequest
  • Middleware: auth.xtoken, verified:api

Content-Type

Karena ada residentialIdCard (optional file), endpoint ini sebaiknya dikirim sebagai multipart/form-data jika mengikutsertakan file.

Payload

Ringkasan dari WithdrawCoinRequest::rules():

FieldTipeWajibValidasi
symbolstringYarequired
amountnumberYanumeric, gt:0
toAddressstringYarequired
networkstringYarequired
otpCodestringYarequired (OTP email)
twoFACodestringYarequired (Google 2FA)
memoTypestringTidaknullable
fromAddressstringTidaknullable (dibutuhkan jika memoType diisi)
destination_tagstringTidaknullable
netkistringTidaknullable (BTC)
residentialNamestringYarequired
residentialAddressstringTidaknullable (wajib jika nilai (> 1000) USDT ekuivalen)
residentialIdCardfileTidakimage jpeg/png/jpg

Proses server (highlight)

Berdasarkan implementasi controller:

  • Jika ekuivalen nilai USDT (> 1000), maka residentialAddress wajib (api.residential_address_required).
  • Jika memoType diisi, fromAddress wajib (api.from_address_required).
  • User harus status success (KYC/identity) (api.identity_verification_are_required).
  • Ada lock setelah ganti password 24 jam (api.no_allow_to_withdraw_in_24_hours_after_changed_password).
  • Verifikasi OTP email dari Redis (api.email_otp_error).
  • Wajib 2FA bind dan kode valid (api.required_for_twofa_binding / api.two_fa_failed).
  • Ada lock 10 detik per user+symbol (api.try_again_later).
  • Validasi coin aktif (api.coin_is_inactive), saldo cukup (api.insufficient_funds).
  • Cek tidak withdraw ke alamat sendiri (berdasarkan aturan tag/network).
  • Cek daily withdrawal limit (api.exceed_system_daily_withdrawal_limit).
  • Cek fee, min/max withdraw, amount setelah fee.
  • Membuat record UserWithdrawal, lalu:
    • jika tidak butuh approve → memanggil Fireblocks withdraw
    • jika butuh approve → notifikasi admin
    • trigger Elliptic check

Response sukses (200)

{
"code": 200,
"title": "OK",
"message": "api.withdraw_apply_successful",
"result": true
}

Response gagal (contoh yang penting)

KondisiHTTPmessage
Validasi payload gagal400pesan validasi pertama
OTP email salah400api.email_otp_error
2FA tidak dibind400api.required_for_twofa_binding
2FA salah403api.two_fa_failed
Saldo tidak cukup400api.insufficient_funds
Coin inactive400api.coin_is_inactive
Daily limit terlewati400api.exceed_system_daily_withdrawal_limit

Withdraw fiat (IDR)

API v1

  • Method: POST
  • Path: /api/withdraw/withdraw-fiat
  • Controller: App\Http\Controllers\Api\WithdrawController@withdrawFiat
  • Request validation: App\Http\Requests\Api\WithdrawFiatRequest
  • Middleware: auth.xtoken, verified:api, walletStatus:WD

Payload

Ringkasan dari WithdrawFiatRequest::rules():

FieldTipeWajib
amountnumberYa
paymentMethodstringYa
bankAccountnumberYa (ID user_bank_address_id)
otpCodestringYa
twoFACodestringYa

Detail proses dan response spesifik mengikuti implementasi withdrawFiat di controller.

Deposit cash (manual transfer IDR)

API v1

  • Method: POST
  • Path: /api/deposit/cash
  • Controller: App\Http\Controllers\Api\DepositController@depositCash
  • Request validation: App\Http\Requests\Api\DepositCashRequest
  • Middleware: auth.xtoken, verified:api, grecaptcha.verify, walletStatus:DEPO

Content-Type

Wajib multipart/form-data karena ada file bukti transfer payment.

Payload

Ringkasan dari DepositCashRequest::rules():

FieldTipeWajibCatatan
amountnumberYanumeric, gt:0
paymentfileYaimage jpeg/png/jpg, max 8MB
fullNamestringYa
emailstringYaemail + regex
phonestringYaphone:countryCode
countryCodestringYarequired_with phone
dialCodestringYa
bankNamestringYa
bankNostringYa
bankCompanystringYa

Response sukses (200)

{
"code": 200,
"title": "OK",
"message": "api.cash_deposit_successful",
"result": true
}

Get digit transfer (helper untuk deposit manual)

  • Method: GET
  • Path: /api/deposit/get-digit-transfer
  • Controller: App\Http\Controllers\Api\DepositController@getDigitTransfer
  • Middleware: auth.xtoken, verified:api

Response sukses (200)

Mengembalikan digit unik untuk manual deposit (berdasarkan jumlah deposit hari ini dan env DEPOSIT_MANUAL_MAX_DIGIT):

{
"code": 200,
"title": "OK",
"message": "api.manual_deposit_digits_success",
"result": true,
"data": {
"digit": 1
}
}

Response gagal

Jika belum ada deposit hari ini:

{
"code": 400,
"title": "Bad Request",
"message": "api.manual_deposit_digits_failed",
"result": false,
"auth_required": true
}