Refunds API
Endpoints
| Method |
Path |
Scope |
Description |
POST |
/v1/refunds |
refunds:write |
Refund a payment |
GET |
/v1/refunds/{id} |
refunds:read |
Get refund status |
Create Refund
Request
POST /v1/refunds
X-API-Key: sk_live_...
{
"payment_id": "a1b2c3d4-...",
"amount": 25.00
}
| Field |
Type |
Required |
Description |
payment_id |
UUID |
✅ |
Original payment to refund |
amount |
decimal |
❌ |
Partial refund. Omit for full refund |
Response
{
"success": true,
"data": {
"id": "refund-uuid-...",
"payment_id": "a1b2c3d4-...",
"status": "completed",
"provider_ref": "re_1abc...",
"amount": "25.00",
"created_at": "2025-01-01T12:00:00Z"
}
}
Provider Behavior
| Provider |
Refund Type |
Timing |
| Stripe |
Direct refund |
Instant — status is completed immediately |
| PayPal |
Capture refund |
Instant — status is completed immediately |
| M-Pesa |
Async reversal |
Status is pending → result arrives via callback → reversed |
flowchart LR
Refund["POST /v1/refunds"] --> Provider{"Which<br/>provider?"}
Provider -->|Stripe| Instant["Stripe Refund API<br/>→ completed"]
Provider -->|PayPal| Capture["PayPal Captures Refund<br/>→ completed"]
Provider -->|M-Pesa| Reversal["Daraja Reversal API<br/>→ pending"]
Reversal --> Callback["Callback arrives<br/>→ reversed"]
Validation Rules
- Payment must be in
completed status
- Payment must have a
provider_ref
- Partial refund amount must be > 0
Error Codes
| Code |
HTTP |
When |
CONFLICT |
409 |
Payment not in completed status, or no provider reference |
NOT_FOUND |
404 |
Payment ID not found |
VALIDATION_ERROR |
422 |
Provider credentials not configured |