Refunds & Idempotency
Refunds follow preview → confirm → execute once. Every financial mutation requires an Idempotency-Key so a network retry can't double-charge or double-refund.
Why idempotency matters
A request can time out or drop mid-flight, and you won't know whether the server actually finished processing it. If your code auto-retries without idempotency protection, the same refund could be submitted twice.
Send an Idempotency-Key header (a unique string you generate) on financial calls. Retrying with the same key and same body replays the original result instead of executing again; the same key with a different body returns 409 IDEMPOTENCY_KEY_CONFLICT.
IDEMPOTENCY_KEY_REQUIRED): POST /api/Subscription, POST /api/Subscription/{id}/Cancel, POST /api/Checkout, POST /api/PaymentLink/{id}/Complete, POST /api/Payment/{id}/Attempt, POST /api/Payment/{id}/Reconcile, POST /api/Refund.Refund flow: preview → confirm → execute once
- 1The dashboard's refund button first shows a preview — refundable amount, whether it's eligible.
- 2Only after the merchant confirms does it actually call
POST /api/Refund(with an Idempotency-Key). - 3A refund can't be undone once submitted; clicking "Confirm refund" twice is safely blocked by the same key — it never refunds twice.
/api/Refund— Request a full or partial refund on a paymentcurl -sS -X POST "$BASE/api/Refund" \
-H "Authorization: Bearer $API_KEY" \
-H "Idempotency-Key: refund-order-42" \
-H "Content-Type: application/json" \
-d '{"paymentId":"pay_...","amount":200,"reason":"customer_request"}'When a payment's status is unknown
The Sandbox timeout scenario leaves a payment unknown — meaning "not yet determined", not "failed". Never retry the charge just because it looks like a failure — that can double-charge the customer. Call reconcile to get the final result instead.
/api/Payment/{id}/Reconcile— Resolve an unknown payment's final outcome
ReBate Pay Docs