Developer

Partner Docs

Merchant Docs

Common Refund Scenarios

This guide provides practical examples for processing refunds using Banked's API. It covers the primary refund methods and demonstrates how to handle common use cases like full and partial refunds.

Prerequisite: Before initiating a refund, ensure the original payment (pay-in) has a status of SENT.

This guide will walk you through these key scenarios:

  1. Understanding Refund Types: Mandate vs. Account to Account refunds.
  2. Mandate Refund Scenarios: Full and partial refunds using a mandate token.
  3. Account to Account Refund Scenarios: Full and partial refunds from a funded float account.
  4. Retrieving Refund Status: How to check the status of a refund.

When to Use Each Refund Type

Choose the right refund type based on the original payment method and the information you have available.

Best for: Business or company accounts that support PayTo enabled bank accounts. To find out if your account is eligible for mandate refunds please contact support@banked.com

  • Uses NPP payment rails for real-time refunds
  • Requires pre-established refund mandate (set up by Banked Support)
  • Works with any eligible merchant account type
  • Instant refund processing via a preconfigured customisable mandate
  • Setup is fast, simple and customisable

Refund mandates are created during merchant onboarding and can only be created or modified by authorized Banked personnel. Contact Banked Support to set up or modify your refund mandate.

Mandate Refund Scenarios

These scenarios outline how to process a full or partial mandate refund for a 'Pay by Bank' pay-in.

Scenario 1. Create a Full Mandate Refund

Use Case: A customer paid 10.00 AUD for an item using a 'Pay by Bank' pay-in and has returned it for a full refund. Implementation Strategy: To initiate a mandate refund, use the refund mandate token provided during onboarding. Populate the original_payin_information field with the transaction ID of the original pay-in. To refund the full transaction amount, leave the amount field blank (null).

Example Request:

json
POST /v3/refunds
{
  "amount": 10, // Leave blank for full refund
  "original_payin_information": {
    "id": "82a649c5-af14-474a-997a-b25b0d3f45be"
  },
  "processing_method": {
    "method_type": "MANDATE",
    "mandate": {
      "token": "a6017842-1a01-4cc1-9d5e-d66ef0094685"
    }
  }
}

Example Response:

json
{
  "amount": 10, 
  "created_at": "2025-05-22T10:38:49.162980987Z",
  "currency": "AUD",
  "debtor_account": {
    "account_type": "BANKED_BANK_ACCOUNT_ENTITY",
    "bank_account_id": "06a1cb4b-f038-4d4d-b3f9-2114e31125a2"
  },
  "mandate": {
    "id": "3f80b430-4127-46f9-a86f-3ce18a02a53d"
  },
  "expiration": "2025-06-21T10:38:49.162981594Z",
  "id": "4690e5d4-5fcb-49e1-ad90-396dc48587c5",
  "original_payin_information": {
    "amount": 10,
    "id": "82a649c5-af14-474a-997a-b25b0d3f45be"
  },
  "status_details": {
    "status": "PENDING"
  },
  "updated_at": "2025-05-22T10:38:49.246322209Z"
}

Scenario 2. Create a Mandate Refund Less Than the Original Payment Amount

Use Case: A customer's order was 10.00 AUD, but only one item worth 5.00 AUD was returned. The original payment was made via a 'Pay by Bank' pay-in.

Implementation Strategy: To create a mandate refund, use the refund mandate token provided during onboarding and populate the original_payin_information field with the `transaction ID of the original pay-in. To request a partial refund, specify an amount less than the original transaction—for example, enter 5.00 in the amount field.

Example Request:

json
POST /v3/refunds
{
  "amount": 5,
  "original_payin_information": {
    "id": "82a649c5-af14-474a-997a-b25b0d3f45be"
  },
  "processing_method": {
    "method_type": "MANDATE",
    "mandate": {
      "token": "a6017842-1a01-4cc1-9d5e-d66ef0094685"
    }
  }
}

Example Response:

json
{
  "amount": 5,
  "created_at": "2025-05-22T10:38:49.162980987Z",
  "currency": "AUD",
  "debtor_account": {
    "account_type": "BANKED_BANK_ACCOUNT_ENTITY",
    "bank_account_id": "06a1cb4b-f038-4d4d-b3f9-2114e31125a2"
  },
  "mandate": {
    "id": "3f80b430-4127-46f9-a86f-3ce18a02a53d"
  },
  "expiration": "2025-06-21T10:38:49.162981594Z",
  "id": "4690e5d4-5fcb-49e1-ad90-396dc48587c5",
  "original_payin_information": {
    "amount": 10,
    "id": "82a649c5-af14-474a-997a-b25b0d3f45be"
  },
  "status_details": {
    "status": "PENDING"
  },
  "updated_at": "2025-05-22T10:38:49.246322209Z"
}

Account to Account Refund Scenarios

These scenarios outline how to process a full or partial Account to Account refund for a 'Pay by Bank' pay-in.

Scenario 1. Create a Full Account to Account Refund

Use Case: A customer paid 10.00 AUD via a standard single payment and requires a full refund.

Implementation Strategy: To create an Account to Account refund, use the refund bank_account_id provided during onboarding and populate the original_payin_information field with the transaction ID of the original pay-in. To refund the full transaction amount, leave the amount field blank (null)

Example Request:

json
POST /v3/refunds
{
  "amount": 10, // Leave blank for full refund
  "original_payin_information": {
    "id": "82a649c5-af14-474a-997a-b25b0d3f45be"
  },
  "processing_method": {
    "method_type": "ACCOUNT_TO_ACCOUNT",
    "debtor_account": {
      "account_type": "BANKED_BANK_ACCOUNT_ENTITY",
      "bank_account_id": "06a1cb4b-f038-4d4d-b3f9-2114e31125a2"
    }
  }
}

Example Response:

json
{
  "amount": 10,
  "created_at": "2025-07-02T11:10:22.512Z",
  "currency": "AUD",
  "debtor_account": {
    "account_type": "BANKED_BANK_ACCOUNT_ENTITY",
    "bank_account_id": "06a1cb4b-f038-4d4d-b3f9-2114e31125a2"
  },
  "expiration": "2025-08-01T11:10:22.512Z",
  "id": "c4d9e8f7-6a5b-4c3d-b2a1-e0f9d8c7b6a5",
  "original_payin_information": {
    "amount": 10,
    "id": "82a649c5-af14-474a-997a-b25b0d3f45be"
  },
  "status_details": {
    "status": "PENDING"
  },
  "updated_at": "2025-07-02T11:10:22.678Z"
}

Scenario 2. Create a Partial Account to Account Refund

Use Case: A customer is eligible for a partial refund of 5.00 AUD on a 10.00 AUD order as a goodwill gesture.

Implementation Strategy: To create an Account to Account refund, use the refund bank_account_id provided during onboarding and populate the original_payin_information field with the transaction ID of the original pay-in. To request a partial refund, specify an amount less than the original transaction—for example, enter 5.00 in the amount field.

Example Request:

json
POST /v3/refunds
{
  "amount": 5,
  "original_payin_information": {
    "id": "82a649c5-af14-474a-997a-b25b0d3f45be"
  },
  "processing_method": {
    "method_type": "ACCOUNT_TO_ACCOUNT",
    "debtor_account": {
      "account_type": "BANKED_BANK_ACCOUNT_ENTITY",
      "bank_account_id": "06a1cb4b-f038-4d4d-b3f9-2114e31125a2"
    }
  }
}

Example Response:

json
{
  "amount": 5,
  "created_at": "2025-07-02T11:15:05.123Z",
  "currency": "AUD",
  "debtor_account": {
    "account_type": "BANKED_BANK_ACCOUNT_ENTITY",
    "bank_account_id": "06a1cb4b-f038-4d4d-b3f9-2114e31125a2"
  },
  "expiration": "2025-08-01T11:15:05.123Z",
  "id": "d5e6f7a8-9b0c-1d2e-3f4a-5b6c7d8e9f0a",
  "original_payin_information": {
    "amount": 10,
    "id": "82a649c5-af14-474a-997a-b25b0d3f45be"
  },
  "status_details": {
    "status": "PENDING"
  },
  "updated_at": "2025-07-02T11:15:05.234Z"
}

Retrieving a Refund

You can check the status of any refund by its unique ID. This is useful for confirming whether the funds have been sent successfully.

Get Refund by ID

Use Case: You want to confirm the final status of a refund you processed earlier.

Implementation Strategy: Use a GET request to the /v3/refunds/{id} endpoint with the ID of the refund you want to retrieve.

Example Request:

json
GET /v3/refunds/4690e5d4-5fcb-49e1-ad90-396dc48587c5

Example Response (Successful Refund):

The status will transition from PENDING to SENT once the refund has been successfully processed and settled in the customers bank account.

json
{
  "original_payin_information": {
    "id": "1ae1ce03-dfa9-4593-b487-65c656991cb5",
    "amount": 400
  },
  "id": "13612aeb-4d97-40c8-b3a5-d6567647c988",
  "created_at": "2024-11-01T15:48:26.374Z",
  "updated_at": "2024-11-01T15:48:26.374Z",
  "amount": 400,
  "currency": "AUD",
  "mandate": {
    "id": "1d81c1f4-5349-46cf-97e7-ff642db33ff6"
  },
  "debtor_account": {
    "account_type": "BANKED_BANK_ACCOUNT_ENTITY",
    "bank_account_id": "a6850617-a7b9-4ae7-adc2-b86bae6fc35f"
  },
  "status_details": {
    "status": "SENT",
  },
  "expiration": "2024-12-01T14:18:25.162Z"
}

mandate: The mandate field is only present for refunds processed using a mandate. For Account to Account refunds, this field will not be included.

Implementation Best Practices

Webhook Processing for Refunds

Set up webhooks to receive real-time updates on refund status changes. Your system should listen for refund-specific events to automate internal processes:

Example Webhook Handler:

javascript
function handleRefundWebhook(webhookData) {
  const { event, data } = webhookData;

  switch (event) {
    case 'refund.sent':
      // Update your system: Mark refund as complete
      updateRefundStatus(data.id, 'completed');
      // Send customer notification
      notifyCustomer(data.original_payin_information.id, 'refund_completed');
      break;

    case 'refund.failed':
      // Update your system: Mark refund as failed
      updateRefundStatus(data.id, 'failed');
      // Alert support team for manual intervention
      alertSupportTeam(data.id, data.failure_reason);
      break;

    case 'refund.pending':
      // Update your system: Mark refund as processing
      updateRefundStatus(data.id, 'processing');
      break;

    default:
      console.log(`Received unhandled refund event: ${event}`);
  }
}

Refund Expiration Strategy

Unlike payments, refunds typically don't require customer action, but they do have expiration times. Monitor refund expiration to handle edge cases:

  • Mandate Refunds: Expire within 30 days if not processed
  • Account to Account Refunds: Expire within 30 days if not processed
  • Failed Refunds: Implement retry logic for temporary failures (e.g., insufficient funds)

Testing Strategies

Scenario-Based Testing

Thoroughly test all refund scenarios in the sandbox environment to ensure your integration handles both success and failure cases correctly.

Refund Testing Checklist:

  • [ ] Successful full and partial refunds (both Mandate and Account to Account)
  • [ ] Failed refunds (invalid account details, insufficient funds)
  • [ ] Multiple partial refunds for same payment

Testing with Mock Bank

For testing with mock bank accounts see our Testing with Mock Bank section.

Mock Refund Scenarios:

  • Use test mandate tokens provided in sandbox
  • Simulate network failures and retries
  • Verify webhook delivery in test environment

Next Steps

After implementing these common refund scenarios, explore:

For specific implementation questions or regional requirements, contact Banked Support.

© 2025 Banked Ltd.

Dark Theme
PrivacyTerms