Checking access…

Skip to main content
Version: v2

Cancel Payment Flow

πŸ”’ InternalInternal information β€” not visible in the public (merchant) site.

Overview​

The cancel endpoint (PATCH /v2/payments/{paymentId}/cancel) allows merchants to void or cancel an in-progress or authorized payment. Cancellation triggers a Stripe void or reversal depending on the current payment state.


Cancellation Eligibility​

Payment StateCancel Allowed?Stripe Action
AUTHORIZEDβœ…Void the PaymentIntent
ACCEPTEDβœ…Reverse the ACH transaction
PENDINGβœ…Cancel before processing
INITIATEDβœ…Cancel before processing
PROCESSING❌Wait for terminal state
COMPLETED❌Use refund (POST /v2/refunds) instead
FAILED❌Already terminal
CANCELLED❌Already terminal

Cancellation Reasons​

ValueWhen to Use
DUPLICATEMerchant identified this as a duplicate payment
FRAUDULENTSuspected fraudulent activity
REQUESTED_BY_CUSTOMERCustomer asked to cancel
ABANDONEDCustomer did not complete (e.g., 3DS timeout)

API Request​

curl -X PATCH "https://api-stg.uhg.com/api/financial/commerce/nonprodcheckout/v2/payments/770e8400-e29b-41d4-a716-446655440000/cancel" \
-H "Authorization: Bearer <token>" \
-H "X-Merchant-Id: b955db5e-aef2-47de-bbb9-c80b9cc16e8f" \
-H "X-Upstream-Env: dev" \
-H "Content-Type: application/json" \
-d '{
"paymentCancellationReason": "REQUESTED_BY_CUSTOMER",
"paymentCancellationMessage": "Customer changed their mind before shipment"
}'

Request Body​

FieldTypeRequiredDescription
paymentCancellationReasonstring (enum)YesOne of: DUPLICATE, FRAUDULENT, REQUESTED_BY_CUSTOMER, ABANDONED
paymentCancellationMessagestringNoFree-text context (for audit trail)

API Response β€” 202 Accepted​

{
"url": "https://api-stg.uhg.com/.../v2/payments/770e8400-e29b-41d4-a716-446655440000",
"data": {
"id": "770e8400-e29b-41d4-a716-446655440000",
"merchantTransactionId": "preauth-20260404-001",
"amount": 25000,
"status": "CANCEL_INITIALIZED",
"paymentAllocations": [
{
"id": "cccc1111-2222-3333-4444-555566667777",
"amount": 25000,
"status": "CANCEL_INITIALIZED"
}
]
}
}

GET β€” After Cancellation (200 OK)​

{
"data": {
"id": "770e8400-e29b-41d4-a716-446655440000",
"amount": 25000,
"status": "CANCELLED",
"paymentAllocations": [
{
"id": "cccc1111-2222-3333-4444-555566667777",
"amount": 25000,
"status": "CANCELED"
}
]
}
}

Webhook β€” PAYMENT_CANCELLED​

{
"name": "PAYMENT_CANCELLED",
"source": "merchant-portal",
"payload": {
"id": "770e8400-e29b-41d4-a716-446655440000",
"merchantTransactionId": "preauth-20260404-001",
"amount": 25000,
"status": "CANCELLED",
"paymentAllocations": [
{
"id": "cccc1111-2222-3333-4444-555566667777",
"amount": 25000,
"status": "CANCELED"
}
]
}
}

Error Scenarios​

ScenarioHTTP StatusError TitleDetail
Payment in COMPLETED state422UNPROCESSABLE_ENTITYPayment cannot be cancelled in COMPLETED state
Payment in FAILED state422UNPROCESSABLE_ENTITYPayment already failed
Payment not found404NOT_FOUNDpaymentId not found
Missing paymentCancellationReason400INVALID_REQUESTpaymentCancellationReason is required
Invalid cancellation reason value400INVALID_REQUESTInvalid enum value
Stripe void failed422PAYMENT_ERRORCancellation processing failed