Refunds a payment in full or in part. You can make several partial refunds until the payment is fully refunded; each one reduces remaining. Only payments with status succeeded or partially_refunded can be refunded.
MAXFI sends the refund to the payment provider during the call. When the provider accepts it, the response is 200 and a payment.refunded event is queued for your account’s webhook URL at once. If the provider’s answer is not known yet, the response is 202 with status refund_pending.
POST/v2/payments/{id}/refund
Authentication: sk_live_ / sk_test_. Secret API key. Use it only on your server.
Make retries safe
Send a unique key for each refund you intend to make: the idempotency_key field in the body or the Idempotency-Key header. A repeat with the same key within 24 hours does not refund again: it returns the stored result with its status code — 202 for refund_pending — and the idempotent-replay: true header. The same key with another payment, amount or reason returns 409 IDEMPOTENCY_KEY_REUSED. The header also protects against a repeat sent while the first request is still running: such a repeat gets 409 IDEMPOTENCY_IN_PROGRESS. Without a key, a retried request can refund again as long as an amount remains.
Path parameter
Parameter
Description
{id}
Payment ID: cs_… for payments made on the payment page, pay_… for payments created with POST /v2/payments. Test keys see only test payments, live keys only live ones.
Request body
Field
Type
Description
amount
integer
Amount to refund, in minor units. Omit it to refund the whole remaining amount. An amount larger than what remains returns 400.
reason
string(500)
Your note. Returned in the response and in data.refund.reason of the payment.refunded event.
idempotency_key
string(128)
Key that makes retries safe (see above).
Response — 200
Field
Type
Description
id
string
Payment ID.
payment_id
string
Payment ID (the same value as id).
status
string
refunded once the payment is fully refunded; partially_refunded while an amount remains.
amount_refunded
integer
Amount refunded by this call.
total_refunded
integer
Total refunded on this payment.
remaining
integer
Amount that can still be refunded.
reason
string
Your note, echoed.
connector_refund_id
string | null
The payment provider’s reference for this refund, if it returned one. Quote it in support requests.
Response — 202 refund_pending
The provider did not confirm the outcome in time (for example, a timeout). The refund may still go through. Do not send it again; check the payment later with GET /v2/payments/{id}.
Field
Type
Description
status
string
refund_pending.
amount_refunded
integer
0 until the outcome is confirmed.
refund_pending_amount
integer
Amount being verified.
message
string
Explanation in English.
Errors
HTTP
Code
Reason
400
VALIDATION_ERROR
amount is not a positive integer, or reason is longer than 500 characters.
400
BAD_REQUEST
The payment’s status does not allow a refund, it is already fully refunded, the amount exceeds what remains, or the provider declined the refund.
401
UNAUTHORIZED
Missing or invalid API key.
403
FORBIDDEN
A restricted key without refunds:write.
404
NOT_FOUND
No payment with this ID in your account and mode.
409
CONFLICT
Another refund of this payment is being processed at the same moment, or the payment cannot be refunded automatically — contact support.
409
IDEMPOTENCY_KEY_REUSED
The key (idempotency_key or Idempotency-Key) was already used with a different request — another payment, amount or reason.
409
IDEMPOTENCY_IN_PROGRESS
A request with the same Idempotency-Key header is still being processed. Retry later.
429
RATE_LIMIT_EXCEEDED
More than 100 requests in 60 seconds from your IP address.
Webhook
After a 200 response MAXFI queues payment.refunded. data.status is refunded or partially_refunded; data.refund holds amount, currency, reason, is_partial, total_refunded and connector_refund_id. Delivery takes up to 8 attempts until your endpoint answers with 2xx — see Webhooks.
POST /v2/payments/{id}/refund · MAXFI Developer Hub