Refunds
Request
Request a refund of a previously settled transaction by passing the transaction_id (tra_) of the original charge and a reason. The funds are returned to the card used on the original transaction — no card details are required.
The full transaction amount is refunded by default; pass amount to refund a smaller amount. A transaction can be refunded once — on success it moves to status REFUNDED and can no longer be refunded again.
Only settled transactions (transaction status PAID) that were paid by Card (Online), Apple Pay or Google Pay can be refunded. The merchant must also have sufficient available balance to cover the refund (this balance check is skipped for accounts settling on their own acquiring MID).
Card transaction IDs are returned by Checkout Link, Checkout Form, Card Vault Charge, and captured Card Vault Pre-Auth holds, or can be found via transactions.
Path
POST /refunds/{transaction_id}/request
| Path Parameter | Type | Description | Example |
|---|---|---|---|
| transaction_id | String(32) | The original settled card transaction to refund — see transactions | tra_pr6CvR_4pvWwmgQ4y3dtY |
Example (Basic)
Refund the full transaction amount.
{
"reason": "Order cancelled by customer" // recorded against the refund and shown in reporting
}
Example (Advanced)
Partial refund with a custom reference and signature.
{
"reason": "Item returned — partial refund for one of two items", // recorded against the refund and shown in reporting
"amount": "150.00", // [optional] must be <= the transaction amount; omit to refund in full
"reference": "REF-2026-00042", // [optional] your reference for this refund; defaults to the original transaction reference
"signature": "secret-key-for-payload" // [optional] shared-secret signature for the payload, see the signature section below
}
Request Parameters
Field | Required | Type | Description | Example |
|---|---|---|---|---|
| reason | Y | String(512) | Reason for the refund; recorded against the refund and shown in reporting | Order cancelled by customer |
| amount | N | String | Amount to refund; must be greater than 0 and less than or equal to the original transaction amount. Omit to refund the full transaction | 150.00 |
| reference | N | String(35) | Your reference for this refund; defaults to the original transaction reference | REF-2026-00042 |
| signature | N | String | Optional passphrase signature for verifying the payload | secret-key-for-payload |
Response Body
The refund is submitted to the card scheme immediately. On success the original transaction (tra_) is moved to REFUNDED, the refunded amount is recorded against it, and a refund.successful webhook is sent. If the processor declines the refund, the request returns an error response (non-200) and the transaction is left unchanged.
{
"status": true,
"result": {
"transaction_id": "tra_pr6CvR_4pvWwmgQ4y3dtY",
"customer_id": "cus_abc123...",
"refund_status": "REFUNDED",
"amount": "150.00",
"refundable_amount": "49.00",
"currency": "ZAR",
"reference": "REF-2026-00042",
"reason": "Item returned — partial refund for one of two items",
"created_at": "2026-07-06T10:15:30Z"
}
}
Response Parameters
Field | Type | Description | Example |
|---|---|---|---|
| status | Boolean | Whether the refund was processed | true |
| result.transaction_id | String(32) | The original transaction that was refunded | tra_pr6CvR_4pvWwmgQ4y3dtY |
| result.customer_id | String(32) | Customer associated with the original transaction, when applicable | cus_abc123... |
| result.refund_status | ENUM | Refund state, see lookups. Refunds are applied immediately, so this is REFUNDED on success | REFUNDED |
| result.amount | String | Amount refunded | 150.00 |
| result.refundable_amount | String | Amount still refundable on the original transaction after this refund | 49.00 |
| result.currency | String(3) | ISO 4217 currency code | ZAR |
| result.reference | String(35) | Reference used for the refund | REF-2026-00042 |
| result.reason | String(512) | Reason supplied on the refund request | Item returned — partial refund for one of two items |
| result.created_at | String | ISO timestamp when the refund was created | 2026-07-06T10:15:30Z |
REFUNDED; the refunded_amount field on each transaction reflects the amount returned to the cardholder.Signature creation
When creating API keys on the dashboard you can download a passphrase key, use it to generate your signature and send it in the signature parameter. The canonicalization and HMAC-SHA256 process is identical across all endpoints — see Checkout Link — Signature creation for Node.js, PHP, C#, Java, and Python examples.
Webhook
When a refund is processed successfully a refund.successful webhook is delivered to your account's webhook endpoints that are subscribed to the event. A refund that is declined by the processor is reported synchronously in the API response (non-200) rather than via webhook.
Webhook Payload
{
"event": "refund.successful",
"data": [
{
"refund": {
"transaction_id": "tra_pr6CvR_4pvWwmgQ4y3dtY",
"customer_id": "cus_abc123...",
"refund_status": "REFUNDED",
"amount": "150.00",
"currency": "ZAR",
"reference": "REF-2026-00042",
"metadata": {
"order_id": "ord_98765"
},
"completed_at": "2026-07-09T08:00:00Z"
}
}
],
"created_at": "2026-07-09T08:00:00Z"
}
Webhook Payload Parameters
Field | Type | Description | Example |
|---|---|---|---|
| event | String | Type of webhook event that occurred | refund.successful |
| data | Array | Array containing refund data | ... |
| data.refund.transaction_id | String(32) | The original transaction that was refunded | tra_pr6CvR_4pvWwmgQ4y3dtY |
| data.refund.customer_id | String(32) | Customer associated with the original transaction, when applicable | cus_abc123... |
| data.refund.refund_status | ENUM | Refund state after the event, see lookups | REFUNDED |
| data.refund.amount | String | Refunded amount | 150.00 |
| data.refund.currency | String(3) | ISO 4217 currency code | ZAR |
| data.refund.reference | String(35) | Reference used for the refund | REF-2026-00042 |
| data.refund.metadata | Object | Custom key/value metadata carried on the original transaction | {"order_id": "ord_98765"} |
| data.refund.completed_at | String | ISO timestamp when the refund was applied | 2026-07-09T08:00:00Z |
| created_at | String | ISO timestamp when webhook was created | 2026-07-09T08:00:00Z |
Webhook Events
| Event | Description | Trigger Condition | Data Included |
|---|---|---|---|
refund.successful | The refund was processed and the funds returned to the cardholder | When the refund is accepted by the card scheme and the transaction is marked REFUNDED | Refund details, original transaction reference |
Webhook Security
All webhooks are sent with the following headers for verification:
X-Signature: HMAC-SHA256 signature of the payloadX-Timestamp: Unix timestamp of when the webhook was sentUser-Agent:Kwik-Webhooks/1.0
Webhook Response
Your endpoint should respond with a 200 status code to acknowledge receipt. Failed webhooks will be retried up to 3 times with exponential backoff.