Getting Started with Refunds

The Refunds feature enables businesses to automate and simplify the process of issuing customer refunds. Built on Lean’s existing payout infrastructure, it allows clients to initiate refunds seamlessly. The feature automatically identifies the connected Payout account and processes a reverse transaction, refunding the payment directly to its original source

Getting access to Refunds

To use the refunds feature, you need to have access to the following services:

  • Payments: Refunds reverse customer payments processed through Lean Payments. The refunds are hence processed directly to the bank account connected with Lean while making the payment.
  • Reconciliation: Refunds are only allowed for payments that have been successfully reconciled, ensuring funds that are received in your bank account are only refunded.
  • Payouts:This enables Lean to process the refund by transferring the amount back to the customer's original payment source from the connected business account.

Ensure these features are enabled to streamline the refund process efficiently.

How does Refunds work ?

Lean's Refunds API allows you to initiate and manage refunds for payments processed through the Lean platform. The system supports:

  • Full and partial refunds for reconciled payments
  • Refunds to the source bank account
  • Status tracking through the complete refund lifecycle

Creating Refunds from the Lean Application Dashboard

  1. Navigate to the Payments tab and locate the payment you wish to refund.
  2. Ensure the payment is reconciled, as refunds cannot be initiated for unreconciled payments. Click the three-dot menu and select "Refund".
🚧

Refunds are only available for transactions that have been reconciled. This ensures users cannot initiate refunds for payments that have not yet settled in the bank.


  1. Enter the required details, such as the refund reason, transaction reference, and refund amount, then click "Initiate Refund".
  2. Click "Refund" to process the refund, triggering a payout back to the original payment source.
  1. Once the refund is confirmed , you can track the status of the refund transaction on the same screen. For more details on status please refer to Refunds lifecycle

☝️

The status of the queued refund can be tracked real-time on the same page

Details of payment status can be found in Refunds Lifecycle

Creating Refunds via Lean APIs

Lean enables programmatic refunds through a simple API. Once a refund is created, Lean sends webhook events that reflect each stage of the refund lifecycle, allowing you to track progress, update customer records, and automate internal workflows.

Refund Lifecycle

A refund moves through the following stages:

  1. Created, Lean has accepted the refund request
  2. Processing, Lean is executing the refund
  3. Processed, funds have been successfully returned to the customer

You receive a webhook at each stage so you can update your internal system records.


1. Create a Refund

To create a refund, you submit a POST request containing the original payment reference and refund details. The refund moves through several stages, each delivered to you via a webhook.

Initiate a new refund via API : POST /payouts/refunds

Example refund request body:

[
    {
        "payment_id": "dbd4dc89-f591-4152-8de7-b7d30a73d201",
        "amount": 15.34,
        "currency": "AED",
        "reason_code": "ORDER_CANCELLED",
        "description": "LAvJO#<l(M",
        "external_reference": "19hBjE",
        "status": "APPROVED"
    }
]

The “payment_id” must reference the original payment that you want to refund. Lean validates this link before processing the refund.

For the full parameter list and schemas, see the API reference doc

☝️

Reason code is mandatory


You must supply a valid reason_code. Retrieve the available list using the Get Refund Reasons endpoint shown below.

To enter the reason code in the Create Refund Request, retrieve the reason codes from GET refunds reason endpoint

Get Refund Reasons

Retrieve available reason codes for refunds: GET /payouts/refunds/reasons

Example Response:

[
    {
        "code": "CUSTOMER_REQUEST",
        "description": "Requested by the client"
    },
    {
        "code": "DUPLICATED_PAYMENT",
        "description": "Duplicated Payment"
    },
    {
        "code": "ORDER_CANCELLED",
        "description": "Service/Order Cancellation"
    },
    {
        "code": "FRAUDULENT_PAYMENT",
        "description": "Fraudulent Payment"
    }
]

Reason codes may vary by region and use case. Always fetch the latest list dynamically instead of hard coding these values.

2. Receive Refund Status

After you create a refund, Lean sends webhook events to notify you of each status update. All refund webhooks use the transaction.account

To receive these events:

• Enable the transaction.account webhook in the Dev Portal

• Inform Lean Support or your Solution Engineer so they can activate webhook delivery for your application

Refunds progress through three main stages. You will receive a webhook each time the status changes.

Step 1) Created

This status indicates that the refund request was received but is not yet being processed.

Is this a final status? No, the refund will continue to progress.

Example payload:

  {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "application_id": "app_1234567890",
    "created_at": "2025-12-03T10:30:00Z",
    "last_updated_at": "2025-12-03T10:35:00Z",
    "status": "CREATED",
    "sub_status": "AWAITING_APPROVAL",
    "failure_details": null,
    "reference": "REF-2025-001234",
    "amount": {
      "currency": "AED",
      "amount": 150.55
    },
    "post_processing_operations": [],
    "type": "REFUND",
    "credit_indicator": "DEBIT",
    "account_id": "323e4567-e89b-12d3-a456-426614174002",
    "original_payment": {
      "account_transaction_id": "423e4567-e89b-12d3-a456-426614174003",
      "payment_id": "523e4567-e89b-12d3-a456-426614174004",
      "customer_id": "623e4567-e89b-12d3-a456-426614174005"
    },
    "description": "Refund for order ORD-2025-5678"
  }

Step 2) Processing

This status indicates that the refund has been approved and is now actively being processed by Lean and the receiving bank.

Is this a final status? No, the refund will move to the final Processed state.

Example payload:

  {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "application_id": "app_1234567890",
    "created_at": "2025-12-03T10:30:00Z",
    "last_updated_at": "2025-12-03T10:35:00Z",
    "status": "PROCESSING",
    "sub_status": "ACCEPTED",
    "failure_details": null,
    "reference": "REF-2025-001234",
    "amount": {
      "currency": "AED",
      "amount": 150.55
    },
    "post_processing_operations": [],
    "type": "REFUND",
    "credit_indicator": "DEBIT",
    "account_id": "323e4567-e89b-12d3-a456-426614174002",
    "original_payment": {
      "account_transaction_id": "423e4567-e89b-12d3-a456-426614174003",
      "payment_id": "523e4567-e89b-12d3-a456-426614174004",
      "customer_id": "623e4567-e89b-12d3-a456-426614174005"
    },
    "description": "Refund for order ORD-2025-5678"
  }

Step 3A) Processed

This status confirms that the refund has been completed and the customer has been credited. No further action is required.

Is this a final status? Yes, this is the final refund state.

Example payload:

  {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "application_id": "app_1234567890",
    "created_at": "2025-12-03T10:30:00Z",
    "last_updated_at": "2025-12-03T10:35:00Z",
    "status": "PROCESSED",
    "sub_status": null,
    "failure_details": null,
    "reference": "REF-2025-001234",
    "amount": {
      "currency": "AED",
      "amount": 150.55
    },
    "post_processing_operations": [],
    "type": "REFUND",
    "credit_indicator": "DEBIT",
    "account_id": "323e4567-e89b-12d3-a456-426614174002",
    "original_payment": {
      "account_transaction_id": "423e4567-e89b-12d3-a456-426614174003",
      "payment_id": "523e4567-e89b-12d3-a456-426614174004",
      "customer_id": "623e4567-e89b-12d3-a456-426614174005"
    },
    "description": "Refund for order ORD-2025-5678"
  }

Step 3B) Failed

Refund encountered issue and couldn’t be processed. Failure details should be visible in failure_details object.

Is this status final? Yes.

Example payload:

  {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "application_id": "app_1234567890",
    "created_at": "2025-12-03T10:30:00Z",
    "last_updated_at": "2025-12-03T10:35:00Z",
    "status": "FAILED",
    "sub_status": null,
    "failure_details": {
      "code": "BANK_ISSUE",
      "details": "Your bank is currently experiencing technical problems. Please try again later."
    },
    "reference": "REF-2025-001234",
    "amount": {
      "currency": "AED",
      "amount": 150.55
    },
    "post_processing_operations": [],
    "type": "REFUND",
    "credit_indicator": "DEBIT",
    "account_id": "323e4567-e89b-12d3-a456-426614174002",
    "original_payment": {
      "account_transaction_id": "423e4567-e89b-12d3-a456-426614174003",
      "payment_id": "523e4567-e89b-12d3-a456-426614174004",
      "customer_id": "623e4567-e89b-12d3-a456-426614174005"
    },
    "description": "Refund for order ORD-2025-5678"
  }

Common Issues

  • Missing reason_code, Ensure you are passing a valid code from the Get Refund Reasons endpoint
  • Webhooks not received, Confirm transaction.account type is enabled in the Dev Portal
  • Refund stuck in Created, Your workflow may require approval, or the original payment may not be eligible for refund

Properties explanation

  • id - unique ID for a refund, equivalent of refund_id
  • application_id - ID of your application
  • created_at - time of creation of refund in Dubai timezone
  • last_udpated_at - time of last update of refund in Dubai timezone
  • status - one of following: CREATED, PROCESSING, PROCESSED, FAILED
  • sub_status - optional of following: AWAITING_APPROVAL, ACCEPTED, PENDING
  • failure_details object containing following, it’s non null only when status is FAILED:
  • code - error code
  • details - error description
  • reference - bank transaction reference, ID returned by the bank
  • amount - object containing following:
    • currency - currency of refund transaction
    • amount - value of refund transaction
  • account_id - Lean provided account ID from which refund was initiated
  • original_payment object referencing to the original payment for which transaction was created, containing:
    • account_transaction_id - unique ID which will point the original reconciled transaction
    • payment_id - original payment ID
    • customer_id - customer which made original payment
  • description - description provided by client which was passed to the bank