Payouts
A payout sends money from your account to a recipient: a card, a bank account or a wallet. Use payouts for disbursements such as seller settlements, insurance claims or customer withdrawals.
Availability depends on the payment providers enabled for your account. Contact info@nivc.ai.
Payouts to Vietnamese bank accounts (NAPAS 247 and CITAD) depend on Vietnamese providers that are not live yet. The request format for Vietnamese bank payouts will be published here when they are available. The examples on this page use a card payout, which is one of the payout types the API supports today.
Payout flow
A payout goes through three steps. You can run them one at a time, or combine them.
- Create.
Create a payout with the amount, currency, recipient and
payout_method_data. The payout waits inrequires_confirmation(or inrequires_payout_method_dataif you did not send the recipient details yet). - Confirm.
Confirm the payout. VNSwitch checks the details with the
provider and sets up the transfer. The payout moves to
requires_fulfillment. - Fulfill.
Fulfill the payout to release the money. The payout moves to
initiatedorpendingwhile the provider works, then tosuccessorfailed.
Two flags on the create request shorten the flow:
| Flag | Effect |
|---|---|
confirm: true | Create and confirm in one request. |
confirm: true with auto_fulfill: true | Create, confirm and fulfill in one request. Use this when you do not need a review step before money leaves your account. |
Keeping the steps separate lets you review or approve a payout (for example, a manual check of large amounts) between confirm and fulfill. Until a payout reaches a final status you can cancel it.
Payout status
| Status | Meaning |
|---|---|
requires_payout_method_data | Created without recipient details. Send payout_method_data when you confirm. |
requires_confirmation | Created and waiting for confirm. |
requires_creation | Confirmed and being set up with the provider. |
requires_vendor_account_creation | The provider needs a recipient account to be set up first. |
requires_fulfillment | Confirmed and waiting for fulfill. |
initiated, pending | Sent to the provider; waiting for the result. |
success | The money was sent. Final. |
failed | The payout did not go through. See error_code and error_message. Final. |
cancelled | You cancelled the payout. Final. |
expired | The payout was not completed in time. Final. |
reversed | The provider reversed a payout that had been sent. Final. |
ineligible | The provider found the recipient or payout method ineligible. |
not_permitted | The provider refused the payout, for example because the recipient details could not be verified. Final. |
VNSwitch sends a webhook when a payout reaches initiated, success, failed, cancelled,
expired, reversed or not_permitted. The event_type values are payout_initiated,
payout_success, payout_failed, payout_cancelled, payout_expired, payout_reversed and
payout_not_permitted. The other statuses do not send a webhook. See
Webhooks.
Payout method data
payout_type says what kind of recipient you are paying, and payout_method_data holds the
recipient details under a key with the same name.
payout_type | payout_method_data | Required fields |
|---|---|---|
card | { "card": { … } } | card_number, expiry_month, expiry_year, card_holder_name |
bank | { "bank": { … } } | Depends on the bank scheme. For example SEPA needs iban and bic; ACH needs bank_account_number and bank_routing_number. account_holder_name, bank_name and bank_country_code are optional. |
wallet | { "wallet": { … } } | Depends on the wallet. For example { "paypal": { "email", "telephone_number", "paypal_id" } } or { "venmo": { "telephone_number" } }. |
Card numbers and bank account details are sensitive. Send them only from your servers, over the API, and do not store them in your own logs.
Create a payout
Creates a payout. With the default flags it only records the payout; nothing is sent until you confirm and fulfill it.
POST /payouts/create
Authentication: secret API key (api-key header).
Body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
amount | integer | Yes | Amount to pay out, in the minor unit of the currency (for VND, whole dong: 150000 is 150,000 VND). |
currency | string | Yes | ISO 4217 currency code, for example VND. |
payout_type | string | No | card, bank, wallet or bank_redirect. See
Payout method data. |
payout_method_data | object | No | Recipient details. Required before the payout can be confirmed, either here or in the confirm request. |
customer | object | No | The recipient as a customer: id, name, email, phone, phone_country_code. If you leave out id, VNSwitch can create a customer for you. |
confirm | boolean | No | true confirms the payout in the same request. Default false. |
auto_fulfill | boolean | No | true fulfills the payout right after it is confirmed. Default false. |
merchant_order_reference_id | string | No | Your own reference for this payout, up to 255 characters. Useful for reconciliation. |
description | string | No | A description of the payout. |
entity_type | string | No | Who receives the money, for example Individual (default) or Company. |
priority | string | No | Requested speed, if the provider supports it: instant, fast, regular, wire, cross_border or internal. |
billing | object | No | The recipient’s billing address. Some providers require it. |
metadata | object | No | Your own key-value data. Up to 50 keys; key names up to 40 characters, values up to 500 characters. |
Example request
Response
{
"payout_id": "payout_7c1e4b9a2f",
"merchant_id": "merchant_demo",
"merchant_order_reference_id": "WD-2026-0042",
"amount": 150000,
"currency": "VND",
"payout_type": "card",
"status": "requires_confirmation",
"connector": null,
"auto_fulfill": false,
"customer_id": "cus_demo_001",
"customer": {
"id": "cus_demo_001",
"name": "Nguyễn Văn An",
"email": "an.nguyen@example.vn",
"phone": "912345678",
"phone_country_code": "+84"
},
"client_secret": "payout_payout_7c1e4b9a2f_secret_<RANDOM>",
"return_url": null,
"business_country": null,
"entity_type": "Individual",
"recurring": false,
"description": "Wallet withdrawal",
"profile_id": "pro_demo_001",
"error_code": null,
"error_message": null,
"created": "2026-11-01T09:30:00.000Z"
}Response
A payout object. Key fields:
| Field | Description |
|---|---|
payout_id | The payout ID. Use it in the other payout operations. |
status | See Payout status. |
amount, currency | The payout amount and currency. |
payout_type | The payout type. |
connector | The payment provider handling the payout, once one is chosen. |
auto_fulfill | Whether the payout is fulfilled automatically after confirm. |
customer | The recipient. |
client_secret | Only for client-side calls made with a publishable key. Do not send it from your server. |
error_code, error_message | Set when the payout failed. |
created | ISO 8601 creation time. |
Retrieve a payout
Returns the current state of a payout.
GET /payouts/{payout_id}
Authentication: secret API key (api-key header).
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
payout_id | string | Yes | The payout ID. |
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
force_sync | boolean | No | true asks the provider for the latest status before responding. Default false. Use it only when a payout has stayed initiated or pending longer than expected; otherwise wait for the webhook. |
Example request
Response
{
"payout_id": "payout_7c1e4b9a2f",
"merchant_id": "merchant_demo",
"merchant_order_reference_id": "WD-2026-0042",
"amount": 150000,
"currency": "VND",
"payout_type": "card",
"status": "success",
"connector": "<PROVIDER>",
"auto_fulfill": false,
"customer_id": "cus_demo_001",
"client_secret": "payout_payout_7c1e4b9a2f_secret_<RANDOM>",
"return_url": null,
"business_country": null,
"entity_type": "Individual",
"recurring": false,
"profile_id": "pro_demo_001",
"connector_transaction_id": "<PROVIDER_REFERENCE>",
"error_code": null,
"error_message": null,
"created": "2026-11-01T09:30:00.000Z"
}Response
The payout object, with the same fields as
Create a payout.
connector_transaction_id is the provider’s reference for the transfer.
Confirm a payout
Confirms a payout that is in requires_confirmation or requires_payout_method_data. VNSwitch
checks the details with the provider. If auto_fulfill is true, the payout is also fulfilled.
POST /payouts/{payout_id}/confirm
Authentication: secret API key (api-key header).
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
payout_id | string | Yes | The payout to confirm. |
Body parameters
All body fields are optional. Send {} to confirm the payout as created, or send fields that
were missing or that you want to change before confirming.
| Parameter | Type | Required | Description |
|---|---|---|---|
payout_type | string | No | Payout type, if not sent at create. |
payout_method_data | object | No | Recipient details. Required here if the payout is in requires_payout_method_data. |
auto_fulfill | boolean | No | true fulfills the payout right after confirming it. |
amount | integer | No | New amount in the minor unit. |
metadata | object | No | Your own key-value data. |
client_secret is only for client-side confirmation with a publishable key. When you
call this endpoint from your server with the secret API key, do not send
client_secret; VNSwitch rejects the request if you do.
Example request
Response
{
"payout_id": "payout_7c1e4b9a2f",
"merchant_id": "merchant_demo",
"amount": 150000,
"currency": "VND",
"payout_type": "card",
"status": "requires_fulfillment",
"connector": "<PROVIDER>",
"auto_fulfill": false,
"customer_id": "cus_demo_001",
"client_secret": "payout_payout_7c1e4b9a2f_secret_<RANDOM>",
"return_url": null,
"business_country": null,
"entity_type": "Individual",
"recurring": false,
"profile_id": "pro_demo_001",
"error_code": null,
"error_message": null,
"created": "2026-11-01T09:30:00.000Z"
}Response
The payout object. Without auto_fulfill the status is normally requires_fulfillment.
Fulfill a payout
Releases the money for a payout in requires_fulfillment. Any other status returns an error.
The result can arrive later: watch for the payout_success or payout_failed webhook.
POST /payouts/{payout_id}/fulfill
Authentication: secret API key (api-key header).
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
payout_id | string | Yes | The payout to fulfill. |
Body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
payout_id | string | Yes | The same payout ID as in the path. |
Example request
Response
{
"payout_id": "payout_7c1e4b9a2f",
"merchant_id": "merchant_demo",
"amount": 150000,
"currency": "VND",
"payout_type": "card",
"status": "initiated",
"connector": "<PROVIDER>",
"auto_fulfill": false,
"customer_id": "cus_demo_001",
"client_secret": "payout_payout_7c1e4b9a2f_secret_<RANDOM>",
"return_url": null,
"business_country": null,
"entity_type": "Individual",
"recurring": false,
"profile_id": "pro_demo_001",
"connector_transaction_id": "<PROVIDER_REFERENCE>",
"error_code": null,
"error_message": null,
"created": "2026-11-01T09:30:00.000Z"
}Response
The payout object, usually with status initiated, pending or success.
Cancel a payout
Cancels a payout that has not reached a final status, for example one waiting in
requires_confirmation or requires_fulfillment. A payout that is already success,
failed, cancelled or in another final status cannot be cancelled.
POST /payouts/{payout_id}/cancel
Authentication: secret API key (api-key header).
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
payout_id | string | Yes | The payout to cancel. |
Body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
payout_id | string | Yes | The same payout ID as in the path. |
Example request
Response
{
"payout_id": "payout_7c1e4b9a2f",
"merchant_id": "merchant_demo",
"amount": 150000,
"currency": "VND",
"payout_type": "card",
"status": "cancelled",
"connector": "<PROVIDER>",
"auto_fulfill": false,
"customer_id": "cus_demo_001",
"client_secret": "payout_payout_7c1e4b9a2f_secret_<RANDOM>",
"return_url": null,
"business_country": null,
"entity_type": "Individual",
"recurring": false,
"profile_id": "pro_demo_001",
"error_code": null,
"error_message": null,
"created": "2026-11-01T09:30:00.000Z"
}Response
The payout object with status cancelled. If the provider has already started the transfer, the
cancellation is passed to the provider and the final result can arrive as a webhook.
List payouts
Returns your payouts, filtered by the query parameters. All parameters are optional.
GET /payouts/list
Authentication: secret API key (api-key header).
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
customer_id | string | No | Only payouts to this customer. |
limit | integer | No | Number of payouts to return, 1 to 100. Default 10. |
starting_after | string | No | A payout ID. Returns the payouts after it, for the next page. |
ending_before | string | No | A payout ID. Returns the payouts before it, for the previous page. |
created | string | No | ISO 8601 date-time. Only payouts created at this time. |
start_time | string | No | ISO 8601 date-time. Only payouts created at or after this time. |
end_time | string | No | ISO 8601 date-time. Only payouts created up to this time. Defaults to now. Use it together with start_time. |
Example request
Response
{
"size": 1,
"total_count": 1,
"data": [
{
"payout_id": "payout_7c1e4b9a2f",
"merchant_id": "merchant_demo",
"amount": 150000,
"currency": "VND",
"payout_type": "card",
"status": "success",
"connector": "<PROVIDER>",
"auto_fulfill": false,
"customer_id": "cus_demo_001",
"client_secret": "payout_payout_7c1e4b9a2f_secret_<RANDOM>",
"return_url": null,
"business_country": null,
"entity_type": "Individual",
"recurring": false,
"profile_id": "pro_demo_001",
"created": "2026-11-01T09:30:00.000Z"
}
]
}Response
| Field | Description |
|---|---|
size | Number of payouts in this response. |
total_count | Number of payouts that match the filters. |
data | Array of payout objects. |