Skip to main content
This guide explains all the statuses you’ll encounter when working with payments, disbursements, and remittances in Yabetoo.

Payment Intent Statuses

A Payment Intent goes through several statuses during its lifecycle:
StatusDescriptionNext Steps
pendingIntent created, waiting for confirmationConfirm the payment with customer details
processingPayment being processed by Mobile Money providerWait for completion
succeededPayment completed successfullyFulfill the order
failedPayment failedCheck error reason, allow retry

Status Flow

Checkout Session Statuses

StatusDescription
openSession created, waiting for customer
completeCustomer completed the payment
expiredSession expired without payment

Disbursement Statuses

Disbursements (payouts to customers) have the following statuses:
StatusDescription
pendingDisbursement created, queued for processing
processingBeing sent to the recipient
succeededMoney successfully sent to recipient
failedDisbursement failed

Remittance Statuses

Remittances (transfers) follow the same pattern:
StatusDescription
pendingTransfer queued
processingTransfer in progress
succeededTransfer completed
failedTransfer failed

Handling Different Statuses

Successful Payments

When a payment reaches succeeded:
if (payment.status === "succeeded") {
  // 1. Update your database
  await updateOrderStatus(orderId, "paid");

  // 2. Send confirmation to customer
  await sendConfirmationEmail(customer.email);

  // 3. Trigger fulfillment
  await fulfillOrder(orderId);
}

Failed Payments

When a payment fails, check the failure_message:
if (payment.status === "failed") {
  const reason = payment.failure_message;

  switch (reason) {
    case "LOW_BALANCE":
      // Ask customer to top up
      showMessage("Insufficient balance. Please top up your Mobile Money account.");
      break;
    case "APPROVAL_REJECTED":
      // Customer rejected the payment
      showMessage("Payment was cancelled. Please try again.");
      break;
    case "TIMEOUT":
      // Customer didn't respond
      showMessage("Payment timed out. Please try again.");
      break;
    default:
      showMessage("Payment failed. Please try again or use a different number.");
  }
}

Processing Payments

While a payment is processing:
if (payment.status === "processing") {
  // Show a waiting state to the user
  showMessage("Waiting for payment confirmation...");

  // The customer should receive a notification on their phone
  // Don't allow duplicate submissions
  disablePayButton();
}

Failure Messages

When a payment fails, the failure_message field provides details:
MessageDescriptionRecommended Action
INTERNAL_PROCESSING_ERRORSystem errorRetry later
APPROVAL_REJECTEDCustomer rejectedAsk to retry
EXPIREDRequest expiredCreate new intent
TIMEOUTNo response from customerAsk to retry
PAYER_NOT_FOUNDInvalid phone numberVerify number
PAYEE_NOT_ALLOWED_TO_RECEIVERecipient cannot receiveContact support
NOT_ALLOWEDTransaction blockedContact support
LOW_BALANCEInsufficient fundsCustomer should top up

Webhook Events by Status

StatusWebhook Event
succeededintent.completed
succeeded (disbursement)disbursement.completed

Best Practices

  1. Always handle all statuses - Don’t assume payments will always succeed
  2. Use webhooks for reliability - Don’t rely only on synchronous responses
  3. Log status changes - Keep a history for debugging and support
  4. Show clear messages - Help users understand what happened and what to do next
  5. Implement retry logic - Allow customers to retry failed payments
For testing different statuses, use the test numbers in the sandbox environment.