Skip to content
Status

Void an authorisation

Releases an authorisation so the money the gateway was holding is no longer reserved and can never be captured. The void is its own transaction (a vo_ id) attached to the authorisation; it carries the authorised amount less anything already captured, and by default it also settles the agreement behind it, cancelling a contract that has never taken a payment or writing off the charge the authorisation was raised for. An authorisation is never refunded: it is captured (Capture an authorised payment) or voided, and only the resulting payment or capture can be refunded (Refund a payment).

  • Merchant View: Transaction (Void)
  • API: Void a payment (POST /payments/{payment_id}/void) — :id is an authorisation’s payment (pay_), capture (cap_) or transaction (tr_) id, or the payment’s alt_key; the body is optional
  • Automatically (Shuttle): split payment rollback — one leg of a multi-part authorisation fails to authorise: every leg that did authorise is voided, keeping the balance
  • Automatically (Shuttle): contract completion — a contract is saved as COMPLETED while a successful authorisation is still open on it and the contract’s authorised total exceeds that authorisation’s amount: the authorisation is voided, keeping the balance
  • The source is an authorisation (action AUTH) with an amount above zero whose status is neither DECLINED nor INVALID_PAYMENT_METHOD.
  • The gateway the authorisation was taken on still exists and is neither archived nor inactive.
  • Nothing need be true about how much of the authorisation is still uncaptured, unvoided or unexpired; see Rules.
  • From Merchant View: the instance option manual_capture is on and the authorisation still reports an authorised amount above zero.

The call takes no body: the authorisation to void is the one named in the URL, and the amount is always what is left of it.

Checked by the API means Shuttle refuses the request however it is sent; a screen name means only that screen refuses it, and a direct API call would be accepted.

Rule Checked by What you see
:id must resolve to an authorisation (action AUTH). A pay_, ca_ or tr_ id is fetched directly; anything else is searched as the payment’s alt_key among authorisations. DECLINED and INVALID_PAYMENT_METHOD attempts on the alt_key are ignored The API NOT_FOUND: “Payment not found”
When an alt_key matches several authorisations, the newest authorisation with an authorised amount above zero is voided. If none has one, the newest is used and the rules below decide whether it can be voided, so an alt_key holding only a REQAUTH attempt voids that attempt. Several authorisations on one alt_key are not refused The API The void of the authorisation chosen
The gateway the authorisation was taken on must exist and be neither archived nor inactive; it is checked before the void record is created and again before the gateway is called The API INVALID: “(BOLT-7185) Sorry we could not process this type of payment (archived gateway).”
Authorisation expiry is not checked, server-side or in Merchant View: Void stays on offer after expires has passed, where the screen badges the authorisation EXPIRED, and the gateway decides The API and Merchant View screen the gateway’s answer, recorded as a DECLINED void
A gateway decline is not an error response: the call returns the void with status DECLINED and the gateway’s gateway_message The API HTTP 200 with void.status DECLINED
A gateway that throws fails the call and leaves the void UNRESOLVED with no webhook; a payment connector that cannot be resolved at all is not an error and leaves the void UNRESOLVED with a webhook The API INVALID: “(BOLT-7010) Internal Error: Failed to process transaction with gateway” on a throw; HTTP 200 with void.status UNRESOLVED when no connector answered
The instance option manual_capture gates only Merchant View; the route accepts a void with the option off Merchant View screen control hidden
  • The caller receives a void object (vo_ id, amount, reference, status, gateway_status, gateway_message, processed, payment, source_transaction, parts) with status SUCCESS, PENDING, DECLINED or UNRESOLVED. A decline still returns HTTP 200, so read status; only a request that could not create a void at all returns an error.
  • The amount voided is what was authorised less what has already been captured. On success the authorisation’s voided rises by it and its authorised falls to zero, so no capture can follow.
  • Unless the balance is retained, the agreement behind the authorisation is settled: a contract that has never taken a payment becomes CANCELLED; one that has taken money before keeps its status and the charge the authorisation was raised for is written off instead, clearing what it still owed and its next payment date (Write off a charge).
  • Webhooks: VOID.SUCCESS, VOID.PENDING, VOID.FAILED or VOID.UNRESOLVED for the void, PAYMENT.UPDATE for the authorisation, and CONTRACT.COMPLETE when the balance was not retained. A one-off due at once raises no contract webhook at all, so the most common shape of authorisation reports only the void. CHARGE.WRITTENOFF follows a written-off charge on every other contract shape.
  • In Merchant View the authorisation is badged VOIDED, Capture and Void disappear from it, and the screen moves to the new void transaction.
  • Roles: Admin and Support.
  • Permission keys (for clients managing permissions directly): agreement, payment_contract, payment_transaction or * on the client or on the authorisation’s division, scoped to the payment’s account; checked by Shuttle, which also passes a customer (account) session whose account is the payment’s own. Without one the caller sees UNAUTHORIZED “Unauthorized” (HTTP 401). Merchant View requires payment_transaction specifically to show the action bar, so a user holding only agreement or payment_contract can void through the API but sees no control.
  • API keys: an instance session reaches the route with the same service-layer check. A key scoped read-only or to payment links carries only view permissions and cannot void; a key with full scope acts as Admin.

Was this page helpful?