Withdrawals

Withdrawals

A single withdrawal passes through your system twice:

  1. Auto-validation — the moment a user submits a withdrawal, AbstraPay calls your WITHDRAW_REQUEST webhook synchronously (before anything is created) so your backend can approve/deny based on the user's balance. A denial stops it immediately.
  2. Manual approval — if your backend approved it, the request lands in your management panel at PENDING for an admin to finalize.

Flow

user requests withdrawal
   → WITHDRAW_REQUEST webhook   (you validate balance/limits — approve or deny in real time)
   → status PENDING, shown in your management panel
   → you start processing        (PATCH status: PENDING → PROCESSING)
   → you finalize                (PATCH status: PROCESSING → COMPLETED / REJECTED)
   → on COMPLETED: on-chain payout, then WITHDRAW_COMPLETE webhook → you debit the user

1. Request — initiated from the widget/session (POST /withdraw/direct-transfer with sid, destination address, cryptoCurrencyCode, fiatCurrencyCode, chainId, and an amount as either cryptoAmount or fiatAmount).

2. WITHDRAW_REQUEST webhook (synchronous gate) — AbstraPay calls you and waits. Validate the user's balance/limits and respond:

  • Approve → { "error": 0, "description": "ok" }
  • Deny → { "error": <code>, "description": "..." } (see error codes below)

A denial stops the withdrawal immediately.

3. Manual approval (management panel) — approved requests sit at PENDING. Your admin reviews and finalizes them in the AbstraPay management panel (see Management Panel) — no integration work needed on your side. The finalize is a two-step state machine: a request must first move PENDING → PROCESSING, then PROCESSING → COMPLETED (or REJECTED). You cannot jump straight from PENDING to COMPLETED. Under the hood the panel makes two calls:

# Step 1 — claim the request for processing
curl -X PATCH https://api.abstrapay.com/admin/withdrawals/<id>/status \
  -H "Authorization: Bearer <ADMIN_TOKEN>" -H "Content-Type: application/json" \
  -d '{ "status": "PROCESSING", "adminNote": "reviewing" }'
 
# Step 2 — finalize (COMPLETED or REJECTED)
curl -X PATCH https://api.abstrapay.com/admin/withdrawals/<id>/status \
  -H "Authorization: Bearer <ADMIN_TOKEN>" -H "Content-Type: application/json" \
  -d '{ "status": "COMPLETED", "adminNote": "approved" }'

statusPROCESSING · COMPLETED · REJECTED. Note: <ADMIN_TOKEN> is a panel admin login token, not your OPERATOR_SECRET_KEY — these admin endpoints use a separate dashboard login.

4. Payout — on COMPLETED, AbstraPay transfers the funds on-chain to the recipient, then sends a WITHDRAW_COMPLETE webhook → debit the user.

Statuses

PENDINGPROCESSINGCOMPLETED · or REJECTED. Also CANCELLED (superseded by a newer request / session cancelled) and EXPIRED (left unactioned too long).

WITHDRAW_REQUEST response codes

codemeaning
0approve
1declined by operator
2insufficient balance
3temporarily unavailable
4user not eligible
5daily limit exceeded
6amount too low
7amount too high
8verification required
9account suspended