logo
POST/api/v1/withdraw/execute

Withdrawal

Initiates a fund transfer from a merchant's Beqelal account to a customer's Financial Institution account.

When to Use

Use this endpoint when a merchant wants to perform an actual withdraw — transferring funds directly from Beqelal into a customer's Financial Institution account via API integration (no checkout page involved).

Authentication

Requires the following headers:

app-id: Your application identifier (from Merchant Portal → Integration → APP ID)
api-key: Your secret API key (from Account Management → Generate API Key → API Keys)

Request Parameters

bankstringRequired

Institution ID of the recipient Financial Institution (inst_id)

accountstringRequired

Customer's Financial Institution account number

amountnumberRequired

Amount to be transferred (in ETB)

trace_numbernumberRequired

Merchant's own transaction reference (must be unique)

callback_urlstring (url)Optional

If provided, overrides the portal-configured webhook URL for this transaction. If not provided, the portal-configured webhook URL will be used.

reasonstring (url)Optional

Reason for the withdrawal

Processing Flow

  • Checks if the merchant's account is active and has sufficient balance
  • Validates the destination Financial Institution and account_no
  • Ensures the transaction complies with minimum balance and transaction limits
  • The system calculates applicable service charges and taxes
  • Total debited amount = amount + fee + VAT (15% of fee) + disaster risk (5% of fee)
  • Funds are deducted from the merchant's Beqelal account
  • The customer's Financial Institution account is credited

Response

Returns JSON containing:

  • Unique Beqelal transaction reference (reference_id)
  • Recipient name from the Financial Institution
  • Financial Institution name and acronym
  • Transaction amount, fees, and remaining balance (balance)
  • Status: PROCESSED if transfer is successful

Notes

  • This endpoint triggers an actual withdraw, not just validation
  • Funds are debited from Beqelal and credited to the Financial Institution account
  • All amounts are in ETB
  • Enforces minimum/maximum limits and balance thresholds

Error Handling

Returns 400 Bad Request for:

  • Inactive or invalid customer account
  • Insufficient balance or transaction rule violation
  • Missing or invalid request fields
  • Real-time query failure to the Financial Institution

Code Examples

Request
curl -X POST "{base_url}/api/v1/withdraw/execute" \
  -H "Content-Type: application/json" \
  -H "app-id: YOUR_APP_ID" \
  -H "api-key: YOUR_API_KEY" \
  -d '{
  "bank": "404050",
  "account": "251911000000",
  "callback_url": "https://example.et/",
  "amount": 100,
  "trace_number": "70RNVPO548",
  "reason": "withdrawal to customer"
}'

Success Responses

This API can return two types of successful responses, both with status_code = 200, but with different meanings.

200 - Payout completed successfully

When the response status is PROCESSED, it means:

  • The payout was successfully completed
  • Funds have been credited to the destination bank account
  • The operation was handled synchronously
  • No further callback/webhook will be sent
Final State Response
{
  "id": "4G2710H78P",
  "bank": "404050",
  "account": "251911000000",
  "amount": 100,
  "fee": 0,
  "trace_number": "70RNV744444PO548",
  "bbf": 8578.23,
  "balance": 940,
  "process": "Withdraw",
  "description": "Withdraw to bank",
  "updated_at": "2025-07-02T23:39:34.821806",
  "status": "PROCESSED",
  "status_code": 200,
  "message": "SUCCESS",
  "detail": "Operation Completed Successfully",
  "reason": ""
}
200 - Request submitted, processing

When the response status is PENDING, it means:

  • The payout request was successfully submitted
  • The payout is still being processed
  • The final payout status will be sent later via callback/webhook
  • The funds are not yet confirmed as credited to the bank
Pending State Response
{
  "id": "4G2710H78P",
  "bank": "404050",
  "account": "251911000000",
  "amount": 100,
  "fee": 0,
  "trace_number": "70RNV744444PO548",
  "bbf": 8578.23,
  "balance": 940,
  "process": "Withdraw",
  "description": "Withdraw to bank",
  "updated_at": "2025-07-02T23:39:34.821806",
  "status": "PENDING",
  "status_code": 200,
  "message": "SUCCESS",
  "detail": "Operation Completed Successfully",
  "reason": ""
}

Webhooks

If a webhook URL is configured (portal setting or callback_url from original request), Beqelal sends the result back as a POST request with the following format:

HTTP Headers
Content-Type: application/json
User-Agent: Beqelal-Webhook/1.0
X-Webhook-Signature: <HMAC_SHA256_SIGNATURE> (if webhook secret configured)
X-Webhook-Timestamp: <UNIX_TIMESTAMP> (if webhook secret configured)
Webhook Payload
{
  "reference": "BEQELAL_REF_123",
  "trace_number": "MERCHANT_REF_456",
  "status": "PROCESSED",
  "amount": 100.0,
  "timestamp": 1695123456
}
reference: Beqelal's reference number
trace_number: Merchant's own transaction reference
status: Can be 'PROCESSED' (success) or 'FAILED' (failure)
amount: Transaction amount
timestamp: Unix timestamp when the webhook was sent

If you have configured a webhook secret, verify the X-Webhook-Signature header using HMAC SHA256. See the webhook test endpoint documentation for details.

Beqelal will automatically retry failed webhook deliveries up to 3 times with a 1-second delay between attempts.

Quick Comparison

StatusMeaningFinal?Callback/Webhook
PROCESSEDPayout completed successfullyYesNo
PENDINGRequest accepted, processingNoYes
400 - Duplicate trace number
Example Value
{
  "error": {
    "status": "FAILED",
    "status_code": "439",
    "message": "TRACE_NUMBER",
    "detail": "trace number must be unique"
  }
}
479 - Unauthorized IP
Example Value
{
  "error": {
    "status": "FAILED",
    "status_code": "479",
    "message": "UNAUTHORIZED_IP_ACCESS",
    "detail": "Unauthorized IP address access."
  }
}