POST /v1/refunds
Issues a refund. PSP-specific behaviour described in the Refunds guide.
Request
Section titled “Request”POST /v1/refundsHost: payment.uncle-z.comX-PAY-Key: pk_<your app's public key>X-PAY-Timestamp: <unix seconds>X-PAY-Signature: <hex hmac-sha256>Idempotency-Key: <uuid>Content-Type: application/json
{ "payment_id": "abc123…", "amount_minor": 1500, "reason": "customer requested"}Body fields
Section titled “Body fields”| Field | Required | Notes |
|---|---|---|
payment_id | yes | 32-char hex of a payment in status=succeeded. |
amount_minor | no | Smallest unit. Omit for full refund (uses the original payment’s amount). Pass an explicit value for partial refunds. Must be ≤ original amount. |
reason | no | Free-form string echoed back on the refund row + outbound webhook. Useful for support tickets. |
Response (201)
Section titled “Response (201)”{ "refund_id": "def456…", "payment_id": "abc123…", "status": "succeeded", "amount_minor": 1500, "currency": "USD", "provider_ref": "<PSP refund id>", "reason": "customer requested", "created_at": "2026-05-09T13:00:00Z"}Status states
Section titled “Status states”status | Meaning |
|---|---|
initiated | Refund request sent to PSP, waiting for confirmation. Rare — most PSPs respond synchronously. |
succeeded | PSP confirmed. Money returning to the buyer. |
failed | PSP rejected (out of refund window, insufficient merchant balance, etc.). |
A refund.succeeded outbound webhook fires once the PSP confirms (immediately for synchronous flows, later for async ones like manual Polar refunds).
Errors
Section titled “Errors”| Status | Body | Meaning |
|---|---|---|
401 | auth errors | Same as POST /v1/payments. |
404 | payment not found | Payment id doesn’t exist or doesn’t belong to your app. |
409 | idempotency conflict | Reused Idempotency-Key with different body. |
422 | payment must be in 'succeeded' state to refund (got X) | You can only refund completed payments. |
422 | payment already has a refund | Only one refund per payment today. |
422 | refund amount exceeds payment amount | amount_minor larger than the original payment. |
502 | refund failed: … | PSP rejected; verbatim error included. Common: refund window expired. |
Idempotency
Section titled “Idempotency”Always include Idempotency-Key. Refunds are sensitive to retry-without-key bugs because a duplicate request creates a duplicate refund attempt at the PSP, potentially crediting the buyer twice. See Idempotency.