ElebneElebneDocs
Pay API

Refunds

Issue full or partial refunds on paid intents. Support multiple partial refunds up to the original amount.

Refunds

Refund paid intents fully or partially. You can issue multiple partial refunds on the same intent until the total refunded equals the original payment amount.

Full refund

Omit the amount field to refund the entire payment.

POST /dev/intents/{referenceNumber}/refund
curl -X POST https://api.elebne.ai/api/v1/dev/intents/PI-3XXXXXXXXXXXXXX/refund \
  -H "Authorization: Bearer sk_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Idempotency-Key: refund-order-5678" \
  -d '{
    "reason": "customer_request",
    "note": "Customer changed their mind"
  }'
const response = await fetch(
  'https://api.elebne.ai/api/v1/dev/intents/PI-3XXXXXXXXXXXXXX/refund',
  {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer sk_test_YOUR_KEY',
      'Content-Type': 'application/json',
      'X-Idempotency-Key': 'refund-order-5678',
    },
    body: JSON.stringify({
      reason: 'customer_request',
      note: 'Customer changed their mind',
    }),
  }
);

const { data } = await response.json();
console.log(data.refunded); // true
response = requests.post(
    'https://api.elebne.ai/api/v1/dev/intents/PI-3XXXXXXXXXXXXXX/refund',
    headers={
        'Authorization': 'Bearer sk_test_YOUR_KEY',
        'Content-Type': 'application/json',
        'X-Idempotency-Key': 'refund-order-5678',
    },
    json={
        'reason': 'customer_request',
        'note': 'Customer changed their mind',
    },
)

print(response.json())

Partial refund

Include an amount field (in centimes) to refund only part of the payment.

curl -X POST https://api.elebne.ai/api/v1/dev/intents/PI-3XXXXXXXXXXXXXX/refund \
  -H "Authorization: Bearer sk_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Idempotency-Key: partial-refund-1" \
  -d '{
    "amount": 20000,
    "reason": "product_defective",
    "note": "1 of 3 items was damaged"
  }'
const response = await fetch(
  'https://api.elebne.ai/api/v1/dev/intents/PI-3XXXXXXXXXXXXXX/refund',
  {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer sk_test_YOUR_KEY',
      'Content-Type': 'application/json',
      'X-Idempotency-Key': 'partial-refund-1',
    },
    body: JSON.stringify({
      amount: 20000,
      reason: 'product_defective',
      note: '1 of 3 items was damaged',
    }),
  }
);

const { data } = await response.json();
console.log(data.amountRefunded); // 20000
response = requests.post(
    'https://api.elebne.ai/api/v1/dev/intents/PI-3XXXXXXXXXXXXXX/refund',
    headers={
        'Authorization': 'Bearer sk_test_YOUR_KEY',
        'Content-Type': 'application/json',
        'X-Idempotency-Key': 'partial-refund-1',
    },
    json={
        'amount': 20000,
        'reason': 'product_defective',
        'note': '1 of 3 items was damaged',
    },
)

print(response.json())

Multiple partial refunds

You can issue multiple partial refunds on the same intent. Each refund is tracked individually in the refunds array.

Original payment:  50000 centimes (500.00 MRU)
1st partial refund: 20000 centimes (200.00 MRU)  -> totalAmountRefunded: 20000
2nd partial refund: 15000 centimes (150.00 MRU)  -> totalAmountRefunded: 35000
3rd partial refund: 15000 centimes (150.00 MRU)  -> totalAmountRefunded: 50000 (fully refunded)

After any refund, the intent status changes to REFUNDED. You can continue issuing partial refunds until totalAmountRefunded equals the original amount.

Request body

FieldTypeRequiredDescription
amountintegerNoPartial refund amount in centimes. Omit for full refund. Minimum: 1.
reasonstringNoRefund reason. Suggested values: customer_request, product_defective, duplicate, fraud.
notestringNoFree-text note for your records. Max 500 characters.

Checking refund status

After refunding, the intent's refunds array contains each individual refund:

{
  "success": true,
  "data": {
    "referenceNumber": "PI-3XXXXXXXXXXXXXX",
    "status": "REFUNDED",
    "amount": 50000,
    "payment": {
      "amountPaid": 50000,
      "paidAt": "2026-04-04T10:35:00.000Z",
      "method": "WALLET"
    },
    "refunds": [
      {
        "amountRefunded": 20000,
        "reason": "product_defective",
        "note": "1 of 3 items was damaged",
        "refundedAt": "2026-04-04T14:00:00.000Z"
      },
      {
        "amountRefunded": 15000,
        "reason": "customer_request",
        "note": null,
        "refundedAt": "2026-04-04T15:30:00.000Z"
      }
    ],
    "totalAmountRefunded": 35000
  }
}

Error cases

Error codeHTTPDescription
IDEMPOTENCY_KEY_REQUIRED400Missing X-Idempotency-Key header
INTENT_NOT_FOUND404Intent does not exist or belongs to another business
INTENT_REFUND_INVALID_STATUS400Intent is not in PAID or REFUNDED status
REFUND_EXCEEDS_REMAINING400Refund amount exceeds remaining refundable balance
INSUFFICIENT_BALANCE400Merchant account has insufficient balance for the refund

Merchant balance required

Refunds are debited from your merchant account balance. Ensure you have sufficient funds before issuing refunds.

Testing refunds in sandbox

In sandbox mode, use the simulate-payment endpoint to create a paid intent, then test refunds against it.

Create an intent with sk_test_ key

Simulate payment via POST /dev/intents/{ref}/simulate-payment

Issue a refund via POST /dev/intents/{ref}/refund

Next steps

Was this page helpful?

On this page