Installment Tracker

Handle the installment_tracker object in webhook events and process approved, pending, and rejected installment decisions.

Use the installment_tracker object to track the issuer bank's decision for an installment request.

Installment Tracker Webhook

The installment_tracker object is returned in installment.tracker.approved and installment.tracker.rejected webhook payloads. Your webhook handler should read data.installment_tracker.status to identify the current installment decision and decide how to update the order.

Store the tracker status against the related order in your system so your operations, support, or fulfillment teams can track the installment lifecycle.

Event Fields

FieldTypeDescription
event_typestringThe webhook event name. For installment tracker updates, this is installment.tracker.approved or installment.tracker.rejected.
dataobjectThe order payload associated with the installment update.
data.installment_trackerobject | nullThe installment tracker object. It can be null when no installment tracker is available for the order.
data.installment_tracker.idstringUnique identifier for the installment tracker.
data.installment_tracker.statusstringThe issuer bank's installment decision. Use this value to identify whether the installment is approved, pending, or rejected.
data.installment_tracker.messagestring | nullRejection reason when the status is R. This is usually null when the status is A or P.

Installment Status Values

The data.installment_tracker.status field can contain one of these values:

ValueStatusDescription
AApprovedThe issuer bank approved the installment request.
PPendingThe installment request is still waiting for a final decision.
RRejectedThe issuer bank rejected the installment request. Check message for the rejection reason.

Installment Tracker Object Examples

Approved Installment

"installment_tracker": {
  "id": "70414",
  "status": "A",
  "message": null
}

Rejected Installment

"installment_tracker": {
  "id": "70321",
  "status": "R",
  "message": "Error Message"
}

Pending Installment

"installment_tracker": {
  "id": "70321",
  "status": "P",
  "message": null
}
💡

Check the status field to determine your next action: process the order on A, retry or wait on P, and surface the message to your support team on R.

Example Payload

The webhook payload includes the order or transaction payload in data. The sample below uses dummy data and shows an installment.tracker.approved event where status is A.

{
  "event_type": "installment.tracker.approved",
  "data": {
    "id": "order_123456789",
    "ref_id": "merchant-order-1001",
    "status": "success",
    "type": "PRODUCTION",
    "amount": "250.00000",
    "discount": "25.00000",
    "shipping": "15.00000",
    "taxes": "10.00000",
    "total_amount": "250.00",
    "payment_amount": "250.00",
    "refunded_amount": "0.00",
    "fees": "0.00000",
    "amwal_fee": "2.50",
    "amwal_tax_vat": "0.38",
    "convenience_fee": "0.00",
    "merchant_payout": "247.12",
    "payment_method": "Card",
    "payment_option": "Installment",
    "paymentBrand": "VISA",
    "funding_method": "credit",
    "card_type": "CREDIT",
    "card_last_4_digits": "1234",
    "card_payment_brand": "VISA",
    "issuer": "Demo Bank",
    "card_bank_issuer": "demo bank",
    "created_at": "2026-04-28T20:41:00.356051+03:00",
    "merchant_id": "merchant_123456789",
    "merchant_business_name": "Demo Store",
    "merchant_country_code": "SA",
    "store_domain": "https://demo-store.example.com",
    "client_email": "[email protected]",
    "client_first_name": "Example",
    "client_last_name": "Customer",
    "client_phone_number": "+966500000000",
    "installment_status": "approved",
    "installment_duration": 3,
    "installment_fee": "0.00",
    "installment_fee_vat": "0.00",
    "installment_tracker": {
      "id": "tracker_12345",
      "status": "A",
      "message": null
    },
    "address_details": {
      "city": "Riyadh",
      "state": "Riyadh Province",
      "country": "SA",
      "street1": "Example Street",
      "postcode": "12345",
      "first_name": "Example",
      "last_name": "Customer",
      "email": "[email protected]"
    },
    "shipping_details": {
      "id": "standard_shipping:1",
      "tax": 1.5,
      "label": "Standard shipping",
      "price": 15
    },
    "is_refundable": true,
    "refund_tracker": null,
    "order_details": null,
    "failure_reason": null
  }
}

Use the exact data.installment_tracker.status value from the payload when updating the order in your system. Other fields in data provide transaction, customer, merchant, payment, shipping, and installment context that you can store for reconciliation or support workflows.

Handle installment tracker updates

Use the installment_tracker object in your installment tracker webhook handler to decide whether to fulfill the order, wait for another update, or escalate the rejection reason.

async function handleInstallmentTrackerEvent(webhook) {
  try {
    const installmentTracker = webhook?.data?.installment_tracker;

    if (!installmentTracker) {
      console.log('No installment tracker found for this event.');
      return { status: 'ignored' };
    }

    const { id, status, message } = installmentTracker;

    switch (status) {
      case 'A':
        // Mark the order as ready for fulfillment after the issuer bank approves the installment request.
        console.log(`Installment approved for tracker ${id}`);
        return { status: 'approved', tracker_id: id };

      case 'P':
        // Keep the order in a waiting state until Amwal sends the next update.
        console.log(`Installment pending for tracker ${id}`);
        return { status: 'pending', tracker_id: id };

      case 'R':
        // Record the rejection reason so your operations or support team can review it.
        console.error(`Installment rejected for tracker ${id}: ${message || 'No rejection message provided'}`);
        return {
          status: 'rejected',
          tracker_id: id,
          message: message || 'No rejection message provided'
        };

      default:
        console.warn(`Unknown installment status for tracker ${id}: ${status}`);
        return { status: 'unknown', tracker_id: id, raw_status: status };
    }
  } catch (error) {
    console.error('Failed to process installment tracker:', error.message);
    return { status: 'error', message: error.message };
  }
}

const webhookPayloads = [
  {
    event_type: 'installment.tracker.approved',
    data: {
      installment_tracker: {
        id: '70414',
        status: 'A',
        message: null
      }
    }
  },
  {
    event_type: 'installment.tracker.approved',
    data: {
      installment_tracker: {
        id: '70321',
        status: 'P',
        message: null
      }
    }
  },
  {
    event_type: 'installment.tracker.rejected',
    data: {
      installment_tracker: {
        id: '70322',
        status: 'R',
        message: 'Issuer bank rejected the installment request'
      }
    }
  },
  {
    event_type: 'installment.tracker.approved',
    data: {}
  }
];

async function runExamples() {
  for (const payload of webhookPayloads) {
    const result = await handleInstallmentTrackerEvent(payload);
    console.log('Processing result:', result);
  }
}

runExamples();

Expected output:

Installment approved for tracker 70414
Processing result: { status: 'approved', tracker_id: '70414' }
Installment pending for tracker 70321
Processing result: { status: 'pending', tracker_id: '70321' }
Installment rejected for tracker 70322: Issuer bank rejected the installment request
Processing result: {
  status: 'rejected',
  tracker_id: '70322',
  message: 'Issuer bank rejected the installment request'
}
No installment tracker found for this event.
Processing result: { status: 'ignored' }

Recommended Processing

When you receive an installment tracker update:

  • Treat data.installment_tracker.status as the source of truth for the installment decision.
  • Support the A, P, and R status values in your order management system.
  • Store message and notify your support or operations team when the installment tracker status is R.
  • Keep the original webhook payload for audit and reconciliation.