API

Refunds API

Refund a captured payment. The refund uses the currency of the original payment. There is no currency field on this request.


Refund

POST /merchant/refund-payment
X-API-KEY: <secret key>
Content-Type: application/json
{
  "track_id": "11111111-2222-3333-4444-555555555555",
  "amount": 1.5
}
FieldTypeRequiredNotes
track_idstringYesVenPays track id returned when the payment was created. Not the acquirer transaction id.
amountnumberNoAmount to refund, in the original payment currency.

There is no currency field. A payment taken in USD is refunded in USD. A payment taken in BHD is refunded in BHD. Send amount in that same currency.

If you omit amount, VenPays refunds the original payment amount. That succeeds only when nothing has been refunded yet. If part of the payment was already refunded, omit amount and the call is rejected. Send refundable_balance from the balance call instead.

The payment must belong to the same profile as the API key. Use a secret key. A publishable key is rejected.

Confirmed refund

HTTP 200

{
  "success": true,
  "refund_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
}

success: true means the provider confirmed the refund. Check POST /merchant/payment-status for the same track_id:

Payment status after a confirmed refundMeaning
refundedThe full original amount has been refunded
partial_refundA portion has been refunded. refundable_balance is what you can still refund

refund_id identifies this refund attempt. There is no separate refund-status endpoint. Use payment status and the balance call.

Provider did not confirm

HTTP 200

{
  "success": false,
  "refund_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
}

success: false means the provider did not confirm the refund. The payment status is left unchanged. A following payment-status call still shows success or partial_refund, not refunded.

Do not treat that 200 as a completed refund. Read refundable_balance and the payment status before you try again. If the status is already refunded, the money was refunded on an earlier confirmed call.

Request errors

These are HTTP errors. The body is { "detail": "<message>" }.

HTTPdetailWhat to check
400Transaction not foundtrack_id is not a payment for this API key. An acquirer transaction id will not match.
400Transaction not refundablePayment status is not success or partial_refund. Includes a payment that is already refunded, still in progress, or failed.
400Refund amount exceeds transaction amountamount is larger than the original payment.
400Refund would exceed original transaction amount. Already refunded: …This amount plus earlier refunds is more than the original payment. The message includes the amount already refunded and the max still allowed.
400Invalid payment providerThis payment method cannot be refunded. benefit_web_checkout returns this.
401X-API-KEY header is required or Invalid API keySend a secret key for the profile that created the payment.
403Publishable keys cannot call this endpointDo not use a pk_ key.
500Internal server error, track_id: …The refund did not finish. Check payment status before retrying.

Refundable balance

POST /merchant/get-refundable-balance
X-API-KEY: <secret key>
Content-Type: application/json
{ "track_id": "11111111-2222-3333-4444-555555555555" }

Response

HTTP 200

{
  "track_id": "11111111-2222-3333-4444-555555555555",
  "total_amount": 10.0,
  "total_refunded": 1.5,
  "refundable_balance": 8.5,
  "currency": "USD",
  "status": "partial_refund"
}

currency is the original payment currency. Refund amount must be in that currency. status is the same payment status as POST /merchant/payment-status.

The same 400 Transaction not found and not-refundable errors apply when the payment cannot be refunded.


How to diagnose a refund

  1. Call POST /merchant/payment-status with the VenPays track_id.
  2. Call POST /merchant/get-refundable-balance and read currency, refundable_balance, and status.
  3. If the refund response was success: true, expect refunded or partial_refund.
  4. If the refund response was success: false, expect the previous status to be unchanged. Compare currency with the currency you charged. The refund is sent in that currency, not in a currency you choose on the refund call.
  5. If the response was 400, use the detail string in the table above. Do not retry a refunded payment.