A payment represents one attempt to collect money from a customer. You create it on your server, attach a payment method, confirm it, and then follow its status until it reaches a final value. See Payment lifecycle for what each status means and Redirects and customer actions for payments that need the customer to do something.

You can run a payment in two ways:

  • Two steps: create the payment with confirm: false, then confirm it later with Confirm a payment, from your server or from your front end using the publishable key and the payment’s client_secret.
  • One step: create the payment with confirm: true and the payment method in the same call. See Create and confirm a payment in one call.

All amounts are integers in the currency’s smallest unit. VND has no smaller unit, so "amount": 150000 with "currency": "VND" is 150,000 VND. See Amounts and currencies.

Payment object fields

Every payment operation returns the same payment object. These are the fields you will use most.

FieldTypeDescription
payment_idstringVNSwitch’s ID for the payment. Store it with your order.
statusstringWhere the payment is in its lifecycle, for example requires_payment_method, requires_customer_action, requires_capture, succeeded or failed. See Payment lifecycle.
amountintegerThe amount to collect, in the currency’s smallest unit.
amount_capturableintegerThe amount you can still capture. Relevant when capture_method is manual.
amount_receivedintegerThe amount captured so far.
currencystringThree-letter ISO 4217 code, for example VND.
customer_idstringThe customer this payment belongs to.
capture_methodstringautomatic or manual. See Capture a payment.
payment_methodstringThe payment method group, for example card, wallet, bank_transfer or real_time_payment.
payment_method_typestringThe specific method within the group, for example credit, debit or viet_qr.
payment_method_dataobjectNon-sensitive details of the method used. For cards: last4, expiry, holder name and network. Full card numbers are never returned.
client_secretstringA secret for this one payment. Pass it to your front end so it can confirm or retrieve the payment with the publishable key. Never log it or put it in a URL you share.
next_actionobjectPresent when status is requires_customer_action. Tells you what the customer must do, such as follow a redirect or scan a QR code. See Redirects and customer actions.
return_urlstringWhere VNSwitch sends the customer after a redirect.
descriptionstringYour free-text description.
metadataobjectYour own key-value data, returned unchanged.
setup_future_usagestringon_session or off_session. Whether the payment method was saved for later use.
mandate_idstringSet when the payment created or used a mandate. See Mandates.
error_code, error_messagestringWhy the latest attempt failed, as reported by the payment provider.
unified_code, unified_messagestringThe same failure in a provider-independent form. Prefer these for your own logic.
manual_retry_allowedbooleantrue if you can confirm the payment again after a failure.
refundsarrayRefunds made on this payment. See Refunds.
attempt_countintegerHow many attempts were made to process the payment.
createdstringWhen the payment was created (ISO 8601).

A confirmed card payment

{
  "payment_id": "pay_8f2c1d9e0a",
  "merchant_id": "merchant_demo",
  "status": "succeeded",
  "amount": 150000,
  "net_amount": 150000,
  "amount_capturable": 0,
  "amount_received": 150000,
  "currency": "VND",
  "customer_id": "cus_demo_001",
  "capture_method": "automatic",
  "payment_method": "card",
  "payment_method_type": "credit",
  "payment_method_data": {
    "card": {
      "last4": "4242",
      "card_exp_month": "12",
      "card_exp_year": "2030",
      "card_holder_name": "NGUYEN VAN AN",
      "card_network": "Visa"
    }
  },
  "client_secret": "pay_8f2c1d9e0a_secret_Xk2pQ9rTz4",
  "description": "Order #1001",
  "return_url": "https://merchant.example.vn/checkout/return",
  "metadata": { "order_id": "1001" },
  "next_action": null,
  "error_code": null,
  "error_message": null,
  "attempt_count": 1,
  "created": "2026-11-01T09:30:00Z"
}

Create a payment

Creates a payment without charging the customer yet. Use this when your front end collects the payment method and confirms the payment later.

POST /payments

Authentication: secret API key (api-key header).

With confirm: false (the default), the payment is returned with status requires_payment_method, or requires_confirmation if you already attached a payment method. Nothing is sent to a payment provider until you confirm the payment. Pass the returned client_secret to your front end if it will confirm the payment; keep your secret API key on your server.

Body parameters

ParameterTypeRequiredDescription
amountintegerYesAmount in the currency’s smallest unit. For VND, the number of dong: 150000 is 150,000 VND.
currencystringYesThree-letter ISO 4217 code, for example VND.
confirmbooleanNotrue confirms the payment in the same call; you must then include the payment method. Default false.
capture_methodstringNoautomatic (default) captures the funds as soon as the payment is authorised. manual only authorises them; you capture later with Capture a payment.
customer_idstringNoYour customer’s ID, for example cus_demo_001. Required if you save the payment method. See Customers.
customerobjectNoCustomer details: id, name, email, phone, phone_country_code. Creates the customer if it does not exist, or attaches an existing one. If you also send customer_id, it must match customer.id.
payment_methodstringNoPayment method group: card, wallet, bank_redirect, bank_transfer, real_time_payment and others.
payment_method_typestringNoSpecific method, for example credit, debit or viet_qr.
payment_method_dataobjectNoThe payment method details, keyed by group. For a card: {"card": {"card_number", "card_exp_month", "card_exp_year", "card_holder_name", "card_cvc"}}.
return_urlstringNoWhere VNSwitch sends the customer after a redirect, for example 3-D Secure or a bank page. If omitted, the return URL set on your business profile is used. See Redirects and customer actions.
descriptionstringNoFree text for your records or for display to the customer.
metadataobjectNoYour own key-value data, up to 50 keys. Key names up to 40 characters, values up to 500 characters. Do not put card or personal data here.
setup_future_usagestringNoon_session or off_session. Saves the payment method to the customer for later payments. Use off_session if you will charge it while the customer is not present. See Saved payment methods and recurring payments.
authentication_typestringNothree_ds or no_three_ds. Whether to ask for 3-D Secure on card payments.
merchant_order_reference_idstringNoYour order reference, for reconciliation.
billingobjectNoBilling address and phone.
session_expiryintegerNoHow long the client_secret stays valid, in seconds. Default 900 (15 minutes).

Example request

Response

{
  "payment_id": "pay_8f2c1d9e0a",
  "merchant_id": "merchant_demo",
  "status": "requires_payment_method",
  "amount": 150000,
  "net_amount": 150000,
  "amount_capturable": 150000,
  "currency": "VND",
  "customer_id": "cus_demo_001",
  "capture_method": "automatic",
  "client_secret": "pay_8f2c1d9e0a_secret_Xk2pQ9rTz4",
  "description": "Order #1001",
  "return_url": "https://merchant.example.vn/checkout/return",
  "metadata": { "order_id": "1001" },
  "next_action": null,
  "attempt_count": 1,
  "created": "2026-11-01T09:30:00Z",
  "expires_on": "2026-11-01T09:45:00Z"
}

Response

The payment object. Store payment_id with your order and send client_secret to your front end if it will confirm the payment. See Payment object fields.

Create and confirm a payment in one call

Creates the payment and sends it to the payment provider straight away. Use this when your server already has everything it needs, for example a recurring charge or a server-to-server integration.

POST /payments

Authentication: secret API key (api-key header).

Set confirm: true and include the payment method (payment_method, payment_method_type and payment_method_data, or a saved method). The body parameters are the same as for Create a payment.

Sending raw card numbers from your server means your systems handle card data and fall under PCI DSS requirements. If that is not what you want, collect card details on the front end and confirm with the publishable key and client_secret instead.

Example request

Response

{
  "payment_id": "pay_8f2c1d9e0a",
  "status": "succeeded",
  "amount": 150000,
  "amount_capturable": 0,
  "amount_received": 150000,
  "currency": "VND",
  "customer_id": "cus_demo_001",
  "capture_method": "automatic",
  "payment_method": "card",
  "payment_method_type": "credit",
  "payment_method_data": {
    "card": {
      "last4": "4242",
      "card_exp_month": "12",
      "card_exp_year": "2030",
      "card_holder_name": "NGUYEN VAN AN",
      "card_network": "Visa"
    }
  },
  "client_secret": "pay_8f2c1d9e0a_secret_Xk2pQ9rTz4",
  "return_url": "https://merchant.example.vn/checkout/return",
  "next_action": null,
  "attempt_count": 1,
  "created": "2026-11-01T09:30:00Z"
}

Response

The payment object. Check status:

  • succeeded: the money is collected (with capture_method: automatic).
  • requires_capture: the amount is authorised and waiting for you to capture it (with capture_method: manual).
  • requires_customer_action: the customer must complete a step such as 3-D Secure. Read next_action and follow Redirects and customer actions.
  • processing: the provider has not answered yet. Wait for a webhook or retrieve the payment later.
  • failed: see error_code, error_message, unified_code and unified_message.

Update a payment

Changes a payment that has not been confirmed yet, for example when the customer edits the cart before paying.

POST /payments/{payment_id}

Authentication: secret API key (api-key header). From a front end, use the publishable key and include the payment’s client_secret in the body.

You can update a payment only while its status is requires_payment_method, requires_confirmation or requires_customer_action. Send only the fields you want to change.

Path parameters

ParameterTypeRequiredDescription
payment_idstringYesThe payment to update.

Body parameters

The update body accepts the same fields as Create a payment, all optional. The ones you will use most:

ParameterTypeRequiredDescription
amountintegerNoNew amount in the currency’s smallest unit.
currencystringNoThree-letter ISO 4217 code. Send it with amount so the amount is never read in the wrong currency.
customer_idstringNoAttach the payment to a customer.
descriptionstringNoNew description.
metadataobjectNoNew key-value data.
return_urlstringNoNew return URL.
capture_methodstringNoautomatic or manual.
payment_method, payment_method_type, payment_method_data—NoAttach or change the payment method.
client_secretstringNoRequired when you call with the publishable key.

Example request

Response

{
  "payment_id": "pay_8f2c1d9e0a",
  "status": "requires_payment_method",
  "amount": 180000,
  "amount_capturable": 180000,
  "currency": "VND",
  "customer_id": "cus_demo_001",
  "capture_method": "automatic",
  "client_secret": "pay_8f2c1d9e0a_secret_Xk2pQ9rTz4",
  "description": "Order #1001 (updated)",
  "metadata": { "order_id": "1001", "coupon": "none" },
  "next_action": null,
  "attempt_count": 1,
  "created": "2026-11-01T09:30:00Z"
}

Response

The updated payment object.

Retrieve a payment

Returns the current state of a payment. Use it to confirm the outcome on your server after a redirect, or when a webhook is late.

GET /payments/{payment_id}

Authentication: secret API key (api-key header). From a front end, use the publishable key with the client_secret query parameter.

Path parameters

ParameterTypeRequiredDescription
payment_idstringYesThe payment to retrieve.

Query parameters

ParameterTypeRequiredDescription
force_syncbooleanNotrue asks the payment provider for the latest status before answering, instead of returning what VNSwitch already knows. Use it when the payment is not in a final status, for example after the customer returns from a redirect. Default false.
client_secretstringNoThe payment’s client_secret. Required when you call with the publishable key.
expand_attemptsbooleanNotrue adds the list of processing attempts (attempts).
expand_capturesbooleanNotrue adds the list of captures on the latest attempt (captures).

Example request

Response

{
  "payment_id": "pay_8f2c1d9e0a",
  "status": "succeeded",
  "amount": 150000,
  "amount_capturable": 0,
  "amount_received": 150000,
  "currency": "VND",
  "customer_id": "cus_demo_001",
  "capture_method": "automatic",
  "payment_method": "card",
  "payment_method_type": "credit",
  "client_secret": "pay_8f2c1d9e0a_secret_Xk2pQ9rTz4",
  "next_action": null,
  "refunds": null,
  "attempt_count": 1,
  "created": "2026-11-01T09:30:00Z"
}

Response

The payment object, including refunds and disputes made on it. See Payment object fields.

Confirm a payment

Sends a created payment to the payment provider for authorisation, with the payment method you attach now or attached earlier.

POST /payments/{payment_id}/confirm

Authentication: secret API key (api-key header). From a front end, use the publishable key and include the payment’s client_secret in the body.

You can confirm a payment in status requires_payment_method or requires_confirmation. If an earlier attempt failed and the payment shows manual_retry_allowed: true, you can confirm it again with the same or another payment method. You cannot confirm a payment that is requires_customer_action; finish the customer step instead (see Redirects and customer actions).

The example response shows a card that needs 3-D Secure: send the customer to next_action.redirect_to_url. Cards without 3-D Secure return succeeded (or requires_capture with manual capture) directly.

Path parameters

ParameterTypeRequiredDescription
payment_idstringYesThe payment to confirm.

Body parameters

The confirm body accepts the same fields as Create a payment, all optional. The ones you will use most:

ParameterTypeRequiredDescription
payment_methodstringNoPayment method group, for example card. Required if no method is attached yet.
payment_method_typestringNoSpecific method, for example credit.
payment_method_dataobjectNoThe payment method details. Required if no method or saved token is attached yet.
payment_tokenstringNoA saved payment method’s token, used instead of payment_method_data. See Payment methods.
return_urlstringNoWhere to send the customer after a redirect.
setup_future_usagestringNoon_session or off_session to save the payment method.
customer_acceptanceobjectNoProof that the customer agreed to save the method or to a mandate. Send it when you save a method for off_session use. See Saved payment methods and recurring payments.
browser_infoobjectNoThe customer’s browser details. Some providers need them for 3-D Secure.
client_secretstringNoRequired when you call with the publishable key.

Example request

Response

{
  "payment_id": "pay_8f2c1d9e0a",
  "status": "requires_customer_action",
  "amount": 150000,
  "amount_capturable": 150000,
  "currency": "VND",
  "customer_id": "cus_demo_001",
  "capture_method": "automatic",
  "payment_method": "card",
  "payment_method_type": "credit",
  "client_secret": "pay_8f2c1d9e0a_secret_Xk2pQ9rTz4",
  "return_url": "https://merchant.example.vn/checkout/return",
  "next_action": {
    "type": "redirect_to_url",
    "redirect_to_url": "https://sandbox.api.vnswitch.nivc.ai/payments/redirect/pay_8f2c1d9e0a/merchant_demo/pay_8f2c1d9e0a_1"
  },
  "attempt_count": 1,
  "created": "2026-11-01T09:30:00Z"
}

Response

The payment object. Handle status as described in Create and confirm a payment in one call.

Capture a payment

Collects money that was authorised earlier. Use it with payments created with capture_method: "manual", for example to charge only when you ship the order.

POST /payments/{payment_id}/capture

Authentication: secret API key (api-key header).

A manual-capture payment stops at requires_capture once it is authorised. Capture it before the authorisation expires; the provider decides how long that is, and capture_before shows the deadline when the provider gives one. If you do not want the money any more, release the authorisation with Cancel a payment.

Path parameters

ParameterTypeRequiredDescription
payment_idstringYesThe payment to capture. Its status must be requires_capture (or partially_captured_and_capturable / partially_authorized_and_requires_capture).

Body parameters

ParameterTypeRequiredDescription
amount_to_captureintegerNoHow much to capture, in the currency’s smallest unit. Must not exceed amount_capturable. If omitted, the full amount_capturable is captured.
statement_descriptor_suffixstringNoText added to the descriptor on the customer’s card statement, if the provider supports it.

Example request

Response

{
  "payment_id": "pay_8f2c1d9e0a",
  "status": "succeeded",
  "amount": 150000,
  "amount_capturable": 0,
  "amount_received": 150000,
  "currency": "VND",
  "customer_id": "cus_demo_001",
  "capture_method": "manual",
  "payment_method": "card",
  "payment_method_type": "credit",
  "next_action": null,
  "attempt_count": 1,
  "created": "2026-11-01T09:30:00Z"
}

Response

The payment object. status is succeeded after a full capture. After a partial capture with capture_method: manual it is partially_captured, and the rest of the authorisation can no longer be captured. amount_received shows how much was captured.

Cancel a payment

Cancels a payment that has not collected money, or releases an authorisation you no longer want to capture.

POST /payments/{payment_id}/cancel

Authentication: secret API key (api-key header).

You can cancel a payment in requires_payment_method, requires_confirmation, requires_customer_action, requires_capture or partially_authorized_and_requires_capture. You cannot cancel a payment that is succeeded, failed, cancelled, processing, requires_merchant_action or review. To give money back after a successful payment, create a refund instead (see Refunds).

Path parameters

ParameterTypeRequiredDescription
payment_idstringYesThe payment to cancel.

Body parameters

ParameterTypeRequiredDescription
cancellation_reasonstringNoFree-text reason, returned in cancellation_reason.

Example request

Response

{
  "payment_id": "pay_8f2c1d9e0a",
  "status": "cancelled",
  "amount": 150000,
  "amount_capturable": 0,
  "amount_received": null,
  "currency": "VND",
  "customer_id": "cus_demo_001",
  "capture_method": "manual",
  "cancellation_reason": "requested_by_customer",
  "next_action": null,
  "attempt_count": 1,
  "created": "2026-11-01T09:30:00Z"
}

Response

The payment object with status: "cancelled".

List payments

Returns your payments, newest first, optionally filtered by customer and creation time. Use it for reconciliation and back-office screens.

GET /payments/list

Authentication: secret API key (api-key header).

Query parameters

ParameterTypeRequiredDescription
customer_idstringNoOnly payments of this customer.
limitintegerNoNumber of payments to return, 1 to 100. Default 10.
starting_afterstringNoA payment_id. Returns the page of payments after this one.
ending_beforestringNoA payment_id. Returns the page of payments before this one.
createdstringNoOnly payments created at exactly this time (ISO 8601, for example 2026-11-01T09:30:00Z).
created.ltstringNoOnly payments created before this time.
created.gtstringNoOnly payments created after this time.
created.ltestringNoOnly payments created at or before this time.
created.gtestringNoOnly payments created at or after this time.

The time filters are written with a dot: created.gte, not created_gte. Unknown query parameters are rejected with an error.

To page through results, take the payment_id of the last item in data and pass it as starting_after in the next request. Stop when size is smaller than limit.

Example request

Response

{
  "size": 1,
  "data": [
    {
      "payment_id": "pay_8f2c1d9e0a",
      "status": "succeeded",
      "amount": 150000,
      "amount_received": 150000,
      "currency": "VND",
      "customer_id": "cus_demo_001",
      "capture_method": "automatic",
      "payment_method": "card",
      "payment_method_type": "credit",
      "description": "Order #1001",
      "attempt_count": 1,
      "created": "2026-11-01T09:30:00Z"
    }
  ]
}

Response

An object with size (the number of payments in this page) and data (an array of payment objects, see Payment object fields).