Skip to content

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 amountRefunded stays 0. Reconcile voids by status: CANCELED, not by looking for refunds.
  • Every payment request the payment paid is reopened — back to UNPAID, or PARTIALLY_PAID if 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.