Cancel or void a payment¶
cancelPayment reverses a payment before the money moves. It releases a pre-authorisation you are
not going to capture, and — for merchants with voids enabled — voids a captured card payment
that the processor has not settled yet.
When to cancel, void or refund¶
| Situation | What to use |
|---|---|
| Pre-authorised, not yet captured | Cancel. The hold is released; the payer sees no charge. |
Card payment captured (immediateCapture: true), not yet settled, merchant has voids enabled |
Void with cancelPayment. The charge never settles: the payer's authorisation hold drops off after a few days and the charge does not appear on their statement. The merchant is not charged the discount rate (%), but still pays the transaction fee for the original sale. |
| Captured and settled, an ACH payment, or the merchant does not have voids enabled | Refund. The money moved and has to move back. |
Card payments normally settle in the processor's nightly batch, so a void is the same-day option.
Read the payment's settlementStatus just before you decide: PENDING can be voided, SETTLED
needs a refund.
Note
Voiding is switched on per merchant by Aptean. Without it, cancelPayment on a captured
payment is refused exactly as before — so an integration that only ever cancels
pre-authorisations is unaffected.
Headers¶
The standard three. No idempotency key is required.
{
"x-aptean-apim": "<your api key>",
"x-aptean-tenant": "<your tenant id>",
"x-aptean-tenant-secret": "<your tenant secret>"
}
The mutation¶
mutation CancelPayment($input: CancelPaymentInput!) {
cancelPayment(input: $input) {
code
message
error
payment {
id
status
settlementStatus
cancelReason
}
}
}
Variables¶
{
"input": {
"paymentId": "<the payment id to cancel or void>",
"reason": "Order cancelled by customer"
}
}
| Field | Type | Notes |
|---|---|---|
paymentId |
String | Required. |
reason |
String | Required. Free text — it is stored on the payment, shown in the merchant portal, and included in the void emails. Write something a human will understand in six months. |
customData |
JSON | Optional key-value pairs. |
The response¶
{
"data": {
"cancelPayment": {
"code": "SUCCESS",
"message": "Payment canceled.",
"error": null,
"payment": {
"id": "300f5a49-68f0-44a0-8f73-d2f42ced4a90",
"status": "CANCELED",
"settlementStatus": "PENDING",
"cancelReason": "Order cancelled by customer"
}
}
}
}
code is SUCCESS when the payment is now CANCELED. It is ERROR when the processor refused
the reversal — most often because the payment settled a moment before your call. The payment is
then still COMPLETED, its settlementStatus is SETTLED, and you should
refund it instead.
Note
A void does not remove the authorisation hold; it stops the charge from settling. The payer
keeps seeing the hold as a pending charge until their issuer drops it, normally within a
few days, and the charge never appears on their statement. That timing is the issuer's, not
Aptean's. CANCELED means Aptean and the processor are done.
What a void does¶
- The payment becomes
CANCELED. The whole charge is reversed, including any convenience fee. A void cannot be partial. - The charge never settles. The merchant is not charged the discount rate (%) on it, but the transaction fee for the original sale or authorisation still applies.
- No refund is created and
amountRefundedstays0. Reconcile voids bystatus: CANCELED, not by looking for refunds. - Every payment request the payment paid is reopened — back to
UNPAID, orPARTIALLY_PAIDif another payment still counts towards it. This includes a single payment that paid several requests at once. - Any credit memo balance the payment used is given back to the customer.
- The payer and the merchant receive a "Payment Voided" email, subject to the merchant's receipt settings. A payment paid entirely with credit sends none.
- No event is sent to your integration. Read the payment, or its payment requests, to see the change — the same as for refunds.
What can be voided¶
Requests are checked in this order before anything reaches the processor; the first that fails is the error you get back.
| # | The payment must... | Otherwise |
|---|---|---|
| 1 | belong to a merchant with voids enabled | Cannot cancel an auto capture payment. Current payment status is … |
| 2 | be COMPLETED |
Only a captured payment can be voided. Current payment status is … |
| 3 | have no refunds — completed, pending or unknown (a failed one does not count) | This payment has already been refunded, in part or in full, and can no longer be voided. Refund the remaining balance instead. |
| 4 | if it was paid entirely with credit, be less than 24 hours old | This payment was paid with credit more than 24 hours ago and can no longer be voided. |
| 5 | be awaiting settlement (settlementStatus: PENDING) |
This payment has already settled and can no longer be voided. Create a refund instead. (reason code ALREADY_SETTLED), or Only payments awaiting settlement can be voided. Current settlement status is none. |
| 6 | be a card payment | Only card payments can be voided. Create a refund instead. |
Refusals come back in the top-level errors[] array, not as code: "ERROR". Each carries
extensions.exception.reasonCode: NOT_ELIGIBLE_FOR_CANCEL, or ALREADY_SETTLED for rule 5. See
Requests and responses.
Warning
If your integration already calls cancelPayment on captured payments — for
example "try to cancel, and refund if that fails" — those calls start voiding as soon as the
merchant has voids enabled. Review that flow before it is switched on.
Common failures¶
| Message | Cause |
|---|---|
Only pending payments can be cancelled. Current payment status is … |
A pre-authorisation that is already COMPLETED, CANCELED or FAILED. |
Payment not found. |
Wrong paymentId, or the wrong environment. |
cancelReason is required |
reason was not supplied. |
paymentId is required |
paymentId was not supplied. |
The void-specific refusals are in What can be voided.