Every payment has a status. It changes as the payment moves from creation to a final outcome. Your code should act on status, not on HTTP status codes or on where the customer’s browser ends up. This page lists every status, shows the usual paths between them, and maps them to webhook events.

Payment statuses

StatusMeaningFinal?What you do
requires_payment_methodThe payment exists but has no payment method yet, or the last attempt failed and needs a new method.NoAttach a method and confirm the payment.
requires_confirmationA payment method is attached, but the payment has not been confirmed.NoConfirm the payment.
requires_customer_actionThe customer must do something: complete 3-D Secure, approve in a bank or wallet app, or scan a QR code.NoRead next_action. See Redirects and customer actions.
requires_merchant_actionThe payment is waiting for a decision from you, for example after a manual fraud review.NoReview the payment in the dashboard.
processingThe payment provider is still working on it.NoWait for a webhook, or retrieve the payment with force_sync=true.
requires_captureThe full amount is authorised and held. Only happens with capture_method: manual.NoCapture or cancel it.
partially_authorized_and_requires_captureOnly part of the amount was authorised, and it is waiting for capture.NoCapture what was authorised, or cancel.
partially_captured_and_capturablePart of the amount was captured and more can still be captured.NoCapture the rest, or leave it.
partially_captured_and_processingPart of the amount was captured and the rest is still being processed.NoWait for a webhook.
succeededThe money is collected. You can refund it.YesFulfil the order.
partially_capturedPart of the authorised amount was captured; the rest can no longer be captured.YesFulfil for the captured amount (amount_received).
failedThe payment did not go through. No money was collected.YesShow the customer an error. If manual_retry_allowed is true, you can confirm the same payment again.
cancelledYou cancelled the payment before money was collected.YesNothing.
cancelled_post_captureThe payment was cancelled after capture.YesNothing.
expiredThe payment was not completed or captured in time.YesCreate a new payment if the customer still wants to pay.
conflictedThe amount or currency the provider processed differs from what you sent.NoContact before fulfilling.
reviewThe payment is held for manual review after an unexpected answer from the provider, for example a capture that failed after it first succeeded.NoDo not fulfil yet. Wait for a webhook.

“Final” means VNSwitch will not move the payment to another status by itself. A succeeded payment can still be refunded or disputed; those have their own objects and statuses (see Refunds and Disputes).

How statuses connect

            create (confirm: false)
                     |
                     v
         requires_payment_method
                     |  attach payment method
                     v
          requires_confirmation
                     |  confirm
                     v
   +-----------------+-------------------+
   |                 |                   |
   v                 v                   v
requires_       processing ------>  failed
customer_action      |
   |  customer       |
   |  completes      |
   v                 v
   +-----> (authorised) -------+
             |                 |
   capture_method:     capture_method:
     automatic             manual
             |                 |
             v                 v
         succeeded      requires_capture
                               |  capture
                               v
                           succeeded

  Before capture, cancel  ->  cancelled
  Not completed in time   ->  expired
  (authorised) is a step, not a status value.

Automatic capture flow

This is the default (capture_method: "automatic"). Authorisation and capture happen together.

  1. Create the payment: requires_payment_method.
  2. Confirm it with a payment method.
  3. The payment becomes succeeded, or requires_customer_action first if the customer has to authenticate, or processing if the provider answers later.
  4. You receive the payment_succeeded webhook. Fulfil the order.

Manual capture flow

Use capture_method: "manual" when you want to hold the money first and collect it later, for example when you ship goods or confirm a booking.

  1. Create the payment with capture_method: "manual" and confirm it.
  2. Once authorised, the status is requires_capture and you receive payment_authorized. amount_capturable shows how much you can collect.
  3. When you are ready, capture the payment. A full capture gives succeeded; a partial capture gives partially_captured.
  4. If you do not want the money, cancel the payment to release the hold. The status becomes cancelled.

Authorisations do not last forever. The payment provider sets the limit, often a few days for cards. Capture before capture_before when it is present. Otherwise the hold is released and the payment can end as expired.

Customer action flow

Many payment methods need the customer to do something outside your page: 3-D Secure for cards, approval in a banking or wallet app, or scanning a QR code.

  1. You confirm the payment.
  2. The status is requires_customer_action and the response has a next_action. You receive the action_required webhook.
  3. You send the customer to the redirect URL or show the QR code. See Redirects and customer actions.
  4. The customer finishes. The status moves to succeeded, requires_capture, processing or failed.
  5. You confirm the result on your server, as described in Confirm the outcome on your server.

Failed payments and retries

A failed payment collected no money. The response tells you why:

  • error_code and error_message: the payment provider’s own code and text.
  • unified_code and unified_message: the same failure in a form that does not depend on the provider. Use these for your logic and customer messages.

If manual_retry_allowed is true, you can call Confirm a payment again on the same payment, with the same or a different payment method. Otherwise create a new payment. See Errors for API errors (HTTP 4xx and 5xx), which are different from a failed payment.

Refund statuses

A refund is a separate object with its own status. You can refund a payment that is succeeded or partially_captured.

Refund statusMeaningFinal?
pendingThe refund was sent and is waiting for the provider.No
succeededThe money was returned to the customer.Yes
failedThe refund did not go through.Yes
reviewThe refund needs manual review.No

See Refunds for the refund operations.

Payment webhook events

VNSwitch sends a webhook when a payment or refund reaches one of these statuses. The event_type field in the webhook body tells you which. See Webhooks for how to receive and verify them.

event_typeSent when the payment status becomes
payment_succeededsucceeded
payment_failedfailed
payment_processingprocessing or partially_captured_and_processing
payment_authorizedrequires_capture
payment_partially_authorizedpartially_authorized_and_requires_capture
payment_capturedpartially_captured or partially_captured_and_capturable
payment_cancelledcancelled
payment_cancelled_post_capturecancelled_post_capture
payment_expiredexpired
action_requiredrequires_customer_action, requires_merchant_action, conflicted or review
refund_succeededRefund status succeeded
refund_failedRefund status failed
refund_reviewRefund status review

No event is sent for requires_payment_method or requires_confirmation, because those only change when you call the API yourself. A fully captured payment is reported as payment_succeeded.

Confirm the outcome on your server

Never fulfil an order just because the customer’s browser reached your return_url, or because your front end says the payment worked. Anyone can open that URL or change its query parameters.

Before you ship goods or credit an account, confirm the status from VNSwitch on your server in one of two ways:

  • Webhook: wait for payment_succeeded (or payment_authorized for manual capture), after verifying the webhook signature. See Webhooks.
  • Retrieve: call Retrieve a payment with your secret key. Add force_sync=true if the status is not final yet.

Check that status, amount and currency match your order. Webhooks can arrive more than once and in any order, so make your handler idempotent: record the payment_id and the status you acted on, and skip events you have already processed.