Refunds
Process full and partial refunds for card and ACH transactions.
Overview
The Refunds API allows you to return funds to customers for completed transactions. You can:
- 💰 Full refunds - Return the entire transaction amount
- 📊 Partial refunds - Return a portion of the transaction amount
- 🔄 Multiple refunds - Issue multiple partial refunds up to the original amount
- ⚡ Instant processing - Refunds process immediately
- 📧 Automatic notifications - Customers receive refund confirmations
API Route Options
| Auth Type | Endpoint | Use Case |
|---|---|---|
API Key (x-api-key) |
POST /api/v1/public/refund |
ERP / server integration |
| JWT Bearer | POST /api/v1/transactions/:id/refund |
Dashboard / admin |
For ERP and server-to-server integrations, see Refund — Public API.
Process a Refund (Admin API)
Endpoint
POST /api/v1/transactions/:transactionId/refund
Full Refund
Refund the entire transaction amount:
curl -X POST https://dev.auxcore.net/api/v1/transactions/txn_abc123/refund \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Tenant-ID: your-tenant-id" \
-H "Content-Type: application/json" \
-d '{}'
Response:
{
"success": true,
"data": {
"refundId": "ref_xyz789",
"transactionId": "txn_abc123",
"status": "approved",
"amount": 150.75,
"currency": "USD",
"refundedAt": "2026-01-28T15:30:00Z",
"type": "full"
}
}
Partial Refund
Refund a portion of the transaction amount:
curl -X POST https://dev.auxcore.net/api/v1/transactions/txn_abc123/refund \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Tenant-ID: your-tenant-id" \
-H "Content-Type: application/json" \
-d '{
"amount": 50.00,
"reason": "Item returned"
}'
Response:
{
"success": true,
"data": {
"refundId": "ref_partial_456",
"transactionId": "txn_abc123",
"status": "approved",
"amount": 50.00,
"remainingAmount": 100.75,
"currency": "USD",
"reason": "Item returned",
"refundedAt": "2026-01-28T15:30:00Z",
"type": "partial"
}
}
Request Parameters
| Field | Type | Description | Required |
|---|---|---|---|
amount |
decimal | Refund amount (omit for full refund) | No |
reason |
string | Reason for refund | No |
metadata |
object | Custom key-value pairs | No |
Multiple Partial Refunds
You can issue multiple partial refunds until you reach the original transaction amount:
# First partial refund
curl -X POST https://dev.auxcore.net/api/v1/transactions/txn_abc123/refund \
-d '{"amount": 30.00, "reason": "First item returned"}'
# Second partial refund
curl -X POST https://dev.auxcore.net/api/v1/transactions/txn_abc123/refund \
-d '{"amount": 20.00, "reason": "Second item returned"}'
The system tracks the total refunded amount and prevents over-refunding.
Get Refund Status
Endpoint
GET /api/v1/refunds/:refundId
curl https://api.auxvault.com/api/v1/refunds/ref_xyz789 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Tenant-ID: your-tenant-id"
Response:
{
"success": true,
"data": {
"refundId": "ref_xyz789",
"transactionId": "txn_abc123",
"status": "approved",
"amount": 150.75,
"currency": "USD",
"reason": "Customer request",
"refundedAt": "2026-01-28T15:30:00Z",
"settledAt": "2026-01-29T08:00:00Z",
"card": {
"brand": "Visa",
"last4": "1111"
}
}
}
List Refunds
Endpoint
GET /api/v1/refunds
Query Parameters
| Parameter | Type | Description |
|---|---|---|
page |
integer | Page number (default: 1) |
limit |
integer | Items per page (default: 50) |
startDate |
date | Filter by start date |
endDate |
date | Filter by end date |
status |
string | Filter by status (approved, declined, pending) |
transactionId |
string | Filter by original transaction |
curl "https://api.auxvault.com/api/v1/refunds?startDate=2026-01-01&status=approved" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Tenant-ID: your-tenant-id"
Refund Statuses
| Status | Description |
|---|---|
approved |
Refund processed successfully |
declined |
Refund declined by processor |
pending |
Refund pending (rare) |
failed |
Refund failed - see error |
Declined Refunds (PRA)
When a refund is declined (Payment Refund Authorization issue), it enters the Refund Decline Queue for automatic retry.
Declined Response:
{
"success": false,
"data": {
"refundId": "ref_declined_123",
"status": "declined",
"declineReason": "Account closed",
"queuedForRetry": true,
"retryScheduledAt": "2026-01-28T16:00:00Z"
}
}
The system will automatically retry declined refunds up to 3 times with exponential backoff.
Learn more about Refund Decline Queue →
Refund Timeline
| Event | Timeframe |
|---|---|
| Refund initiated | Immediate |
| Customer sees refund | 3-5 business days (card) / 3-5 business days (ACH) |
| Settlement | Next settlement batch |
⏰ Note: While refunds are processed immediately by AuxVault, it takes 3-5 business days for funds to appear in the customer's account.
Webhooks
Receive notifications when refunds are processed:
refund.processed
{
"type": "refund.processed",
"data": {
"refundId": "ref_xyz789",
"transactionId": "txn_abc123",
"amount": 150.75,
"status": "approved"
}
}
refund.declined
{
"type": "refund.declined",
"data": {
"refundId": "ref_declined_123",
"transactionId": "txn_abc123",
"amount": 150.75,
"declineReason": "Account closed",
"queuedForRetry": true
}
}
Best Practices
✅ DO:
- Provide refund reasons for tracking
- Verify transaction ID before refunding
- Check refundable amount before partial refunds
- Handle declined refunds via webhook
- Notify customers when refund is processed
- Track refund IDs for reconciliation
❌ DON'T:
- Don't refund more than original amount
- Don't refund voided transactions (void instead)
- Don't assume instant customer receipt
- Don't retry declined refunds manually (queue handles it)
Error Handling
Transaction Not Refundable
{
"success": false,
"error": {
"code": "NOT_REFUNDABLE",
"message": "Transaction cannot be refunded",
"details": {
"reason": "Transaction already voided"
}
}
}
Refund Amount Exceeds Available
{
"success": false,
"error": {
"code": "INVALID_AMOUNT",
"message": "Refund amount exceeds available balance",
"details": {
"originalAmount": 100.00,
"refundedAmount": 80.00,
"availableToRefund": 20.00,
"requestedAmount": 50.00
}
}
}
Transaction Not Found
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Transaction not found",
"details": {
"transactionId": "txn_invalid"
}
}
}
Testing
Test Refund Scenarios
Use these transaction IDs in sandbox to test refund scenarios:
| Transaction ID | Result |
|---|---|
txn_refund_approved |
Refund succeeds |
txn_refund_declined |
Refund declined (enters queue) |
txn_refund_partial |
Partial refund allowed |
Code Examples
JavaScript
async function processRefund(transactionId, amount = null) {
const response = await fetch(
`https://dev.auxcore.net/api/v1/transactions/${transactionId}/refund`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'X-Tenant-ID': tenantId,
'Content-Type': 'application/json'
},
body: JSON.stringify({
...(amount && { amount }),
reason: 'Customer request'
})
}
);
const result = await response.json();
if (result.success) {
console.log('Refund processed:', result.data.refundId);
} else {
console.error('Refund failed:', result.error);
}
return result;
}
Python
def process_refund(transaction_id, amount=None):
url = f'https://dev.auxcore.net/api/v1/transactions/{transaction_id}/refund'
payload = {'reason': 'Customer request'}
if amount:
payload['amount'] = amount
response = requests.post(
url,
headers={
'Authorization': f'Bearer {token}',
'X-Tenant-ID': tenant_id,
'Content-Type': 'application/json'
},
json=payload
)
result = response.json()
if result.get('success'):
print(f"Refund processed: {result['data']['refundId']}")
else:
print(f"Refund failed: {result['error']}")
return result
Next Steps
Need help? Contact support@auxvault.com