Refunds

Create, schedule, and track refunds for successful incoming transactions.

Base URL: /v1/refunds
Auth: Authorization: Bearer <secret_key>

A refund returns all or part of a successful incoming transaction. Tsara tracks the refundable amount across every refund linked to that transaction, preventing the combined reserved and successful refunds from exceeding the original payment.

Refunds can be handled manually or scheduled for automatic return to the captured sender account when sender details are available. Automatic refunds use a business-owned source account, include the configured refund fee, and create an outward transfer record only when execution has provider-backed success evidence.

Refund rules

Refunds are transaction-bound:

  • only successful incoming transactions can be refunded
  • each refund reserves all or part of the remaining refundable balance
  • manual refunds are finalized through an operator workflow
  • automatic sender refunds are scheduled for the captured sender bank account; if scheduled_at is omitted, the default is 10 minutes after creation
  • the business wallet must cover the refund amount and configured refund fee before automatic execution
  • refunds move from pending to processing and then successful or failed
  • webhook events are available for each meaningful state transition

Create refund

POST /v1/refunds

Provide one of:

  • transaction_id
  • trx_id
  • transaction_reference

Example body:

{
  "transaction_reference": "ts-88355107",
  "amount": 200,
  "reference": "rf_order_001",
  "reason": "Customer requested a partial refund"
}

To schedule an automatic return to the captured sender account:

{
  "transaction_reference": "ts-88355107",
  "amount": 200,
  "reference": "rf_order_002",
  "reason": "Order cancelled",
  "execution_mode": "auto_sender",
  "scheduled_at": "2026-09-04T14:30:00+01:00"
}

Omit scheduled_at to use the default delay. Automatic execution is rejected when the original transaction does not contain usable sender bank details.

Fetch refund

GET /v1/refunds?reference=rf_order_001

You can also fetch by id or uid.

List refunds

GET /v1/refunds?page=1&limit=20&status=pending

Supported filters:

  • id
  • uid
  • reference
  • status
  • page
  • limit

Process refund

POST /v1/refunds/process

Example body:

{
  "reference": "rf_order_001",
  "note": "Operations team has started processing this refund"
}

Finalize refund

POST /v1/refunds/finalize

Allowed final statuses:

  • successful
  • failed

Example body:

{
  "reference": "rf_order_001",
  "status": "successful",
  "provider_reference": "rf_provider_001",
  "provider_response": "{\"message\":\"Refund completed\"}",
  "note": "Refund completed manually"
}

Status flow

Refund status values:

  • pending
  • processing
  • successful
  • failed

Transaction refund state reflects the aggregate position across all refunds tied to the original transaction.

Webhooks

Refund webhook events:

  • refund.pending
  • refund.processing
  • refund.successful
  • refund.failed

Support endpoints:

  • POST /v1/webhooks/refund-resend
  • GET /v1/webhooks/refund-attempts
  • GET /v1/webhooks/refund-logs

All refund webhooks are signed with X_TSARA_SIGNATURE using your business webhook secret.