Create Refund
Issue a full or partial refund for a completed order. Refunds are processed back to the original payment method (HSA/FSA card or regular card).
Authentication
Authorization: Bearer glm_test_YOUR_API_KEY
Request Body
{
"order_id": "ord_abc123xyz",
"amount": 4235,
"reason": "customer_request",
"notes": "Customer requested refund due to delayed shipping",
"metadata": {
"support_ticket": "TICKET-12345"
}
}
All monetary amounts are integers in cents (e.g., 4995 = $49.95).
Parameters
| Parameter | Type | Required | Description |
|---|
order_id | string | Yes | ID of the order to refund |
amount | integer | No | Amount to refund in cents (omit for full refund) |
reason | enum | Yes | Refund reason (see below) |
notes | string | No | Additional notes (max 500 chars) |
metadata | object | No | Custom key-value pairs |
Finding Order ID: You can get the order_id from:
- Webhook event data (
order.created event)
- Order API response (
GET /v2/orders)
- Your database (store it when receiving
order.created webhook)
- Dashboard order details
Refund Reasons
| Reason | Description | Example Use Case |
|---|
customer_request | Customer requested refund | Customer changed mind, no longer needed |
duplicate | Duplicate payment | Customer accidentally paid twice |
fraudulent | Fraudulent order | Detected fraudulent transaction |
product_unavailable | Product out of stock | Item went out of stock after order |
damaged_product | Product arrived damaged | Item damaged during shipping |
wrong_product | Wrong product shipped | Fulfillment error, sent wrong item |
other | Other reason | Any other reason (explain in notes) |
Request
Response
{
"id": "ref_xyz789",
"order_id": "ord_abc123xyz",
"amount": 4235,
"reason": "customer_request",
"notes": "Customer requested refund due to delayed shipping",
"status": "pending",
"order": {
"id": "ord_abc123xyz",
"order_number": "ORD-2025-001234",
"payment_status": "refunded"
},
"refund_breakdown": {
"hsa_amount": 2995,
"regular_amount": 1240
},
"metadata": {
"support_ticket": "TICKET-12345"
},
"created_at": "2025-10-18T16:00:00Z",
"processed_at": null,
"estimated_arrival": "2025-10-25T16:00:00Z"
}
Response Fields
| Field | Type | Description |
|---|
id | string | Unique refund identifier |
status | enum | Refund status: pending, succeeded, failed, cancelled |
refund_breakdown | object | Split of refund by payment type |
processed_at | timestamp | When refund was processed (null if pending) |
estimated_arrival | timestamp | Estimated date funds return to customer |
Examples
Full Refund
curl -X POST https://api.withgale.com/v2/refunds \
-H "Authorization: Bearer glm_test_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"order_id": "ord_abc123xyz",
"reason": "customer_request",
"notes": "Customer not satisfied with product"
}'
Partial Refund
curl -X POST https://api.withgale.com/v2/refunds \
-H "Authorization: Bearer glm_test_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"order_id": "ord_abc123xyz",
"amount": 1000,
"reason": "damaged_product",
"notes": "Partial refund for damaged item"
}'
Refund Status
| Status | Description |
|---|
pending | Refund initiated, processing |
succeeded | Refund processed successfully |
failed | Refund failed |
cancelled | Refund cancelled |
Split Card Refunds (Automatic)
Gale automatically handles split card refunds. You don’t need to specify how much goes to each card.
When an order is paid with both HSA/FSA and regular card:
{
"order": {
"amounts": {
"hsa_amount": 4995, // Paid with HSA/FSA card
"regular_amount": 895, // Paid with regular card
"total": 5890
}
}
}
Full Refund
Just provide the order_id - Gale splits automatically:
POST /v2/refunds
{
"order_id": "ord_abc123",
"reason": "customer_request"
}
Response shows the breakdown:
{
"id": "ref_xyz789",
"amount": 5890,
"refund_breakdown": {
"hsa_amount": 4995, // Refunded to HSA/FSA card
"regular_amount": 895 // Refunded to regular card
}
}
Partial Refund
Gale splits proportionally based on the original payment ratio:
POST /v2/refunds
{
"order_id": "ord_abc123",
"amount": 2945, // Partial refund
"reason": "damaged_product"
}
Response:
{
"id": "ref_xyz789",
"amount": 2945,
"refund_breakdown": {
"hsa_amount": 2498, // ~84.7% (same ratio as original)
"regular_amount": 447 // ~15.3%
}
}
Key Points:
- You only specify total
amount
- Gale calculates the split automatically
- Each amount refunds to its original payment method
- Response shows the breakdown for your records
Webhooks
Refunds trigger the following webhook events:
{
"type": "refund.created",
"data": {
"id": "ref_xyz789",
"order_id": "ord_abc123xyz",
"amount": 4235,
"status": "pending"
}
}
{
"type": "refund.succeeded",
"data": {
"id": "ref_xyz789",
"order_id": "ord_abc123xyz",
"status": "succeeded",
"processed_at": "2025-10-18T16:05:00Z"
}
}
See Webhooks Reference for all refund events.
Errors
| Status Code | Error Code | Description |
|---|
| 400 | invalid_amount | Refund amount exceeds order total |
| 400 | already_refunded | Order already fully refunded |
| 400 | invalid_state | Order not in refundable state |
| 401 | unauthorized | Invalid or missing API key |
| 404 | not_found | Order not found |
| 422 | validation_error | Field validation failed |
Amount Too Large
{
"error": {
"code": "invalid_amount",
"message": "Refund amount exceeds order total",
"details": {
"requested": 10000,
"maximum": 4235
}
}
}
Already Refunded
{
"error": {
"code": "already_refunded",
"message": "Order has already been fully refunded"
}
}
Invalid State
{
"error": {
"code": "invalid_state",
"message": "Cannot refund order with payment status 'pending'"
}
}
Refund Timeline
| Payment Method | Typical Arrival Time |
|---|
| HSA/FSA Card | 5-10 business days |
| Regular Card | 5-10 business days |
Note: Actual timing depends on the customer’s card issuer.
Important Notes
Refunds cannot be undone. Once a refund is processed, it cannot be reversed. Double-check order ID and amount before submitting.
Partial refunds are supported. You can issue multiple partial refunds up to the order total. The remaining refundable amount is tracked automatically.