Voids#
Cancel transactions before they settle.
Overview#
Voiding cancels a transaction before it's been settled (batched). Unlike refunds, voids prevent the transaction from ever appearing on the customer's statement.
Key Differences: Void vs Refund
| Feature | Void | Refund |
|---|---|---|
| Timing | Before settlement (status: approved) |
After approval or settlement |
| Statement | Never appears | Appears as separate credit |
| Fees | None (transaction cancelled) | Processing fees may apply |
| Speed | Instant cancellation | 3-10 business days |
| Amount | Whole transaction only | Full or partial |
| Record | Original transaction's status becomes voided |
A new refund transaction (REF-…) |
API Route Options#
| Auth Type | Endpoint | Use Case |
|---|---|---|
API Key (x-api-key) |
POST /api/v1/public/void |
ERP / server integration |
| JWT Bearer | POST /api/v1/transactions/:id/void |
Dashboard / admin (requires the transactions.void permission) |
| SDK / API key | POST /api/v1/auxvault/void |
Official v2.0 SDK namespace; server-side x-api-key, SDK public keys get 403 |
For ERP and server-to-server integrations, see Void a Transaction — Public API in the Transactions API.
Void Transaction (Admin API)#
Endpoint#
:transactionId is the transaction UUID or its TXN-… / ACH-… ID. No request body is needed.
curl -X POST https://uat.auxcore.net/api/v1/transactions/7c9e6679-7425-40de-944b-e07fc1f90ae7/void \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Tenant-ID: your-tenant-id"Response (200):
{
"success": true,
"data": {
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"transactionId": "TXN-1769605200000-A1B2C3D4",
"type": "sale",
"status": "voided",
"amount": "150.00",
"currency": "USD",
"updatedAt": "2026-01-28T13:00:00.000Z"
},
"gatewayVoided": true
}Request Parameters#
The void endpoints take no parameters besides the transaction ID. A reason sent in the body is accepted but not stored.
Response Fields#
| Field | Type | Description |
|---|---|---|
data |
object | The voided transaction record (status: "voided") |
gatewayVoided |
boolean | true when the gateway confirmed the reversal |
warning |
string | Present when gatewayVoided is false; explains that the card hold will expire on its own |
What Can Be Voided#
| Transaction | Voidable? |
|---|---|
Approved sale or authorization (status: approved) |
Yes — reversed at the gateway |
| Pending ACH debit | Yes — cancelled before it is sent to the bank (Payliance is asked first and must confirm) |
| TSYS capture waiting for its batch | Yes — removed from the batch locally |
| Settled transaction | No — use refund |
| Cash transaction | No — use refund |
| Declined, voided or refunded transaction | No |
| Transaction lost to a chargeback | No |
Uncaptured authorizations can be voided; voiding releases the hold rather than waiting for it to expire.
When to Use Voids#
✅ Use Void For:#
Customer cancellations (same day)
bash# Customer calls minutes after purchase to cancel curl -X POST https://uat.auxcore.net/api/v1/transactions/TXN-1769605200000-A1B2C3D4/void \ -H "Authorization: Bearer YOUR_TOKEN" -H "X-Tenant-ID: your-tenant-id"Duplicate charges
bash# Accidentally charged customer twice curl -X POST https://uat.auxcore.net/api/v1/transactions/TXN-1769605260000-E5F6A7B8/void \ -H "Authorization: Bearer YOUR_TOKEN" -H "X-Tenant-ID: your-tenant-id"Order errors — wrong product or price charged
Suspected fraud — fraudulent transaction detected before settlement
Releasing an authorization hold — the order will not be fulfilled
❌ Don't Use Void For:#
- Settled transactions → Use refund instead
- Partial cancellations → Void is all-or-nothing; use a partial refund
- Cash payments → Use refund
Settlement Windows#
A transaction can be voided while its status is approved. Once settlement marks it settled, a void is refused and you must refund. Settlement timing depends on the merchant's gateway and batch schedule.
⚠️ Important: The gateway is the final word. If the processor has already settled the transaction, the void is rejected even if AuxCORE still shows approved; the error message then suggests issuing a refund.
Validation Rules#
Void errors are returned as HTTP 400 with error.code: "VALIDATION_ERROR" (or 404 NOT_FOUND for an unknown transaction). The reason is in error.message:
| Situation | error.message |
|---|---|
| Already settled | This transaction has already been settled and cannot be voided. Please issue a refund instead. |
| Not approved (declined, voided, refunded, …) | Only approved transactions can be voided |
| Cash transaction | Void is not supported for Cash transactions. Please issue a refund instead. |
| Lost chargeback | This transaction has already been lost to a chargeback and cannot be voided. … |
| Gateway rejected the reversal | Gateway reversal was unsuccessful (code: …). … — with This transaction may have already been settled — please issue a refund instead. when the gateway reports it settled |
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Only approved transactions can be voided"
}
}When the gateway rejects the reversal, the transaction is not marked voided — the charge is still active.
Void vs Refund Decision Tree#
Transaction needs to be cancelled
↓
Is its status "settled"?
↓ ↓
YES NO ("approved")
↓ ↓
Use REFUND Use VOID
(appears on (never appears
statement) on statement)How to check if settled:
curl https://uat.auxcore.net/api/v1/transactions/7c9e6679-7425-40de-944b-e07fc1f90ae7 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Tenant-ID: your-tenant-id"Response:
{
"success": true,
"data": {
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"transactionId": "TXN-1769605200000-A1B2C3D4",
"status": "approved",
"settledDate": null
}
}status: "approved"→ Use voidstatus: "settled"→ Use refund
Common Scenarios#
Scenario 1: Customer Changes Mind#
Timeline: 30 minutes after purchase
Action: Void
curl -X POST https://uat.auxcore.net/api/v1/public/void \
-H "x-api-key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"transactionId": "7c9e6679-7425-40de-944b-e07fc1f90ae7"}'Result: Transaction cancelled, never appears on statement
Scenario 2: Next-Day Cancellation#
Timeline: 24 hours after purchase
Action: Check if settled, then decide
# Check settlement status
curl https://uat.auxcore.net/api/v1/public/transaction/7c9e6679-7425-40de-944b-e07fc1f90ae7 \
-H "x-api-key: YOUR_API_KEY"
# If status is "approved":
curl -X POST https://uat.auxcore.net/api/v1/public/void \
-H "x-api-key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"transactionId": "7c9e6679-7425-40de-944b-e07fc1f90ae7"}'
# If status is "settled":
curl -X POST https://uat.auxcore.net/api/v1/public/refund \
-H "x-api-key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"transactionId": "7c9e6679-7425-40de-944b-e07fc1f90ae7"}'Void via AuxCORE SDK#
curl -X POST https://uat.auxcore.net/api/v1/auxvault/void \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"TransactionId": "7c9e6679-7425-40de-944b-e07fc1f90ae7"}'Returns { "success": true, "Status": 1, "TransactionId": "…", "message": "Transaction voided" }, or the error status with { "success": false, "Status": 9, "message": "Void failed" }.
Webhooks#
transaction.voided#
{
"id": "9e3c5a17-2b6d-4f80-b1a4-7c8d2e6f0a93",
"type": "transaction.voided",
"created": "2026-01-28T13:00:00.000Z",
"data": {
"transactionId": "TXN-1769605200000-A1B2C3D4",
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"type": "sale",
"status": "voided",
"amount": "150.00",
"currency": "USD",
"orderId": "ORDER-2026-001",
"merchantId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"timestamp": "2026-01-28T13:00:00.000Z"
},
"metadata": {
"tenantId": "your-tenant-id",
"merchantId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
}Best Practices#
✅ DO:#
- Void quickly - Same day before settlement
- Check settlement status - Before attempting void
- Notify customer - Confirm cancellation
- Use webhooks - Automate void notifications
- Fall back to refund - If void fails because the transaction settled, refund instead
❌ DON'T:#
- Don't void after settlement - Use refund instead
- Don't forget to notify - Customer expects confirmation
- Don't void partially - It's all or nothing
- Don't skip error handling - Always check if void succeeded
Testing#
Test Voids in Sandbox#
# 1. Create test transaction (Public API)
TXNID=$(curl -s -X POST https://uat.auxcore.net/api/v1/public/transaction \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"Amount": 100.00,
"SuggestedMode": "Card",
"pciToken": "pci_tok_8f2c1a9b7e4d"
}' | jq -r '.data.TransactionId')
# 2. Void the transaction (Public API)
curl -X POST https://uat.auxcore.net/api/v1/public/void \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"transactionId": "'"$TXNID"'"}'
# 3. Verify voided (Public API)
curl "https://uat.auxcore.net/api/v1/public/transaction/$TXNID" \
-H "x-api-key: YOUR_API_KEY"
# Should show status: "voided"
# 4. Try to void again (should fail)
curl -X POST https://uat.auxcore.net/api/v1/public/void \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"transactionId": "'"$TXNID"'"}'
# Returns 400 VALIDATION_ERROR — "Only approved transactions can be voided"Error Handling#
Void Failed, Use Refund#
async function cancelTransaction(transactionId) {
const result = await voidTransaction(transactionId);
if (result.success) return result;
// Void errors share the VALIDATION_ERROR code — the message says why.
const message = result.error?.message || '';
if (/settled/i.test(message)) {
return refundTransaction(transactionId);
}
throw new Error(message);
}Impact on Merchant Fees#
Void = No Fees#
Original transaction: $100.00
Processing fee: $3.00
↓
Transaction voided
↓
Customer charged: $0.00
Merchant pays: $0.00 (fee refunded)Refund = Fees Apply (usually)#
Original transaction: $100.00
Processing fee: $3.00
↓
Transaction refunded next day
↓
Customer refunded: $100.00
Merchant still pays: $3.00 (fee not refunded)💡 Tip: Void quickly to save on processing fees!
Next Steps#
Need help? Contact support@auxcore.net