Accept PaymentsRefunds

Refunds

Issue full or partial refunds against completed payment sessions.

Before you begin

Refunds are merchant-initiated. They can only be issued against sessions in SUCCEEDED state. Kadosei automatically routes the refund to the provider that processed the original payment; you do not need to specify a provider.

Refund states

A refund moves through the following lifecycle states:

StateDescription
PENDINGSubmitted to the provider, awaiting confirmation.
COMPLETEDThe provider confirmed the refund was processed. Funds are being returned to the customer.
FAILEDThe provider rejected the refund. A refund.failed webhook is delivered with the reason where available.

Effect on the payment session

Issuing a refund updates the parent session state:

  • Full refund: session transitions from SUCCEEDED to REFUNDED.

  • Partial refund: session transitions from SUCCEEDED to PARTIALLY_REFUNDED. The remaining refundable balance is updated.

  • When cumulative partial refunds equal the original amount: session transitions from PARTIALLY_REFUNDED to REFUNDED.


Create a refund

The Idempotency-Key header is required. Use a unique value per refund request to prevent duplicates on retry. If a request with the same key was already processed, Kadosei returns the existing refund record.

POST /api/v1/sessions/{sessionId}/refunds
Idempotency-Key: your-unique-key

{
  "amount": 45.00,
  "reason": "REQUESTED_BY_CUSTOMER",
  "lineItems": [
    {
      "name": "Wireless Headphones",
      "sku": "WH-100",
      "quantity": 1,
      "unitPrice": 45.00
    }
  ]
}

All fields except Idempotency-Key are optional. Omit amount to refund the full remaining balance. lineItems are informational only, Kadosei stores them against the refund record but does not validate them against the original session or the refund amount.

{
  "refundId": "3d72f30c-2977-44bf-b2e8-ff09b9b3216d",
  "sessionId": "6a2fca3f-fffd-4f3a-8eaf-11af4e21aa7b",
  "status": "PENDING",
  "amount": 45.00,
  "currency": "AUD",
  "reason": "REQUESTED_BY_CUSTOMER",
  "createdAt": "2026-04-24T12:30:00.000Z"
}

A 201 response means the refund has been submitted to the provider. Final confirmation of whether the refund succeeded or failed arrives via webhook. A 202 response means the refund was accepted and is being processed asynchronously and the outcome will also arrive via webhook.

A PENDING status in the response does not mean the refund is complete. Listen for refund.completed or refund.failed webhook events to confirm the outcome and update your records accordingly.


Webhook events

EventDescription
refund.completedThe provider confirmed the refund was processed successfully.
refund.failedThe provider rejected the refund. The failureReason field in the payload indicates the cause where available.

Errors

StatusCause
400Missing Idempotency-Key header, or request validation failed (e.g. amount below 0.01).
404Session not found.
409A request with this idempotency key is already being processed. Wait retryAfter seconds and retry.
422Session is not in a refundable state, the requested amount exceeds the remaining refundable balance, or the idempotency key was previously used with different parameters.