Skip to main content

Handling Refunds

This guide explains how to process refunds through the SwiftPay API.

How Refunds Work

When you create a refund:
  1. The refund is created in pending status
  2. We process the refund with our payment processor
  3. The refund status updates to completed or failed
  4. Webhooks notify you of the status change
Refunds can only be created for completed checkout sessions.

Creating a Refund

Full Refund

To refund the full amount of a payment:
curl -X POST https://api.swiftpay.cx/api/refunds \
  -H "Authorization: Bearer mp_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "checkoutSessionId": "sess_abc123",
    "reason": "Customer requested refund"
  }'

Response

{
   "success": true,
   "data": {
      "id": "ref_xyz789",
      "checkoutSessionId": "sess_abc123",
      "amountInCents": 2999,
      "reason": "Customer requested refund",
      "status": "pending",
      "requestedAt": "2024-01-15T10:30:00Z"
   }
}

Refund Statuses

StatusDescription
pendingRefund created, awaiting processing
processingRefund is being processed
completedRefund successful, funds returned
failedRefund failed

Checking Refund Status

Get a Specific Refund

curl https://api.swiftpay.cx/api/refunds/ref_xyz789 \
  -H "Authorization: Bearer mp_live_your_api_key"

List All Refunds

curl "https://api.swiftpay.cx/api/refunds?page=1&limit=20" \
  -H "Authorization: Bearer mp_live_your_api_key"

Filter by Transaction

curl "https://api.swiftpay.cx/api/refunds?transactionId=sess_abc123" \
  -H "Authorization: Bearer mp_live_your_api_key"

Refund Webhooks

Subscribe to refund events to get real-time updates:
EventDescription
refund.completedRefund processed successfully
refund.failedRefund failed

Example Webhook Payload

{
   "id": "evt_abc123",
   "eventType": "refund.completed",
   "eventId": "refund_ref_xyz789",
   "payload": {
      "refundId": "ref_xyz789",
      "sessionId": "sess_abc123",
      "amount": 2999,
      "status": "completed",
      "timestamp": "2024-01-15T10:35:00Z"
   }
}

Refunds and Reserves

If a refund exceeds your available balance, funds will be drawn from your rolling reserves.
When processing a refund:
  1. We first check your available balance
  2. If insufficient, we consume from your active reserves (oldest first)
  3. If still insufficient, the refund will fail
You can view your balance breakdown via the Balance API:
curl https://api.swiftpay.cx/api/balance \
  -H "Authorization: Bearer mp_live_your_api_key"
{
   "success": true,
   "data": {
      "availableBalance": 50000,
      "reservedBalance": 15000,
      "totalBalance": 65000,
      "pendingWithdrawals": 0
   }
}

Processing Time

TypeProcessing Time
Card Refund5-10 business days
Refund processing time depends on the customer’s bank and card network.

Best Practices

Include a clear reason for every refund. This helps with:
  • Internal tracking
  • Customer communication
  • Dispute resolution
Before creating a refund, check your available balance to ensure sufficient funds:
const balance = await getBalance();
if (balance.availableBalance + balance.reservedBalance < refundAmount) {
  throw new Error('Insufficient funds for refund');
}
Don’t poll for refund status. Use webhooks to get real-time updates when a refund completes or fails.
If a refund fails, notify your customer and provide alternative resolution options.

Common Issues

Insufficient Balance

{
   "success": false,
   "error": {
      "type": "validation_error",
      "message": "Insufficient balance for refund",
      "requestId": "req_abc123"
   }
}
Solution: Wait for more payments to settle or contact support.

Session Not Completed

{
   "success": false,
   "error": {
      "type": "validation_error",
      "message": "Can only refund completed sessions",
      "requestId": "req_abc123"
   }
}
Solution: Refunds can only be created for sessions with status completed.

Already Refunded

{
   "success": false,
   "error": {
      "type": "conflict_error",
      "message": "This session has already been refunded",
      "requestId": "req_abc123"
   }
}
Solution: Each session can only be refunded once.