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():
| Field | Tipe | Wajib | Validasi |
|---|---|---|---|
symbol | string | Ya | required |
amount | number | Ya | numeric, gt:0 |
toAddress | string | Ya | required |
network | string | Ya | required |
otpCode | string | Ya | required (OTP email) |
twoFACode | string | Ya | required (Google 2FA) |
memoType | string | Tidak | nullable |
fromAddress | string | Tidak | nullable (dibutuhkan jika memoType diisi) |
destination_tag | string | Tidak | nullable |
netki | string | Tidak | nullable (BTC) |
residentialName | string | Ya | required |
residentialAddress | string | Tidak | nullable (wajib jika nilai (> 1000) USDT ekuivalen) |
residentialIdCard | file | Tidak | image jpeg/png/jpg |
Proses server (highlight)
Berdasarkan implementasi controller:
- Jika ekuivalen nilai USDT (> 1000), maka
residentialAddresswajib (api.residential_address_required). - Jika
memoTypediisi,fromAddresswajib (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)
| Kondisi | HTTP | message |
|---|---|---|
| Validasi payload gagal | 400 | pesan validasi pertama |
| OTP email salah | 400 | api.email_otp_error |
| 2FA tidak dibind | 400 | api.required_for_twofa_binding |
| 2FA salah | 403 | api.two_fa_failed |
| Saldo tidak cukup | 400 | api.insufficient_funds |
| Coin inactive | 400 | api.coin_is_inactive |
| Daily limit terlewati | 400 | api.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():
| Field | Tipe | Wajib |
|---|---|---|
amount | number | Ya |
paymentMethod | string | Ya |
bankAccount | number | Ya (ID user_bank_address_id) |
otpCode | string | Ya |
twoFACode | string | Ya |
Detail proses dan response spesifik mengikuti implementasi
withdrawFiatdi 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():
| Field | Tipe | Wajib | Catatan |
|---|---|---|---|
amount | number | Ya | numeric, gt:0 |
payment | file | Ya | image jpeg/png/jpg, max 8MB |
fullName | string | Ya | |
email | string | Ya | email + regex |
phone | string | Ya | phone:countryCode |
countryCode | string | Ya | required_with phone |
dialCode | string | Ya | |
bankName | string | Ya | |
bankNo | string | Ya | |
bankCompany | string | Ya |
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
}