When you create a KRW recipient via the Wise API, we automatically run a series of validations (format checks) and verifications (Confirmation of Payee, or CoP) before returning the response.
This guide provides details specific to the verification that occurs when creating KRW recipients.
KRW supports the following recipient types, which follow the same recipient behaviour:
| Recipient type | API value | Description |
|---|---|---|
| South Korean (Personal) | south_korean_paygate | Bank code + bank account number (individual). |
| South Korean (Business) | south_korean_paygate_business | Bank code + bank account number (business). |
Field-level validation checks the format and correctness of input fields. If any fail, the recipient is not created and the API returns a validation error.
The following validations occur when the recipient type is south_korean_paygate or south_korean_paygate_business:
| Field | Rules | Error if invalid |
|---|---|---|
| Bank Code | Must be a valid bank code from the Wise bank list for South Korea. | NOT_VALID |
| Account Number | 10–16 digits only. | NOT_VALID |
| Name | At least one character for first name and family name allowed. Max length validated. | NOT_VALID |
Invalid account number:
{
"errors": [
{
"code": "NOT_VALID",
"path": "accountNumber",
"message": "The account number provided is invalid."
}
]
}Verification checks account existence only (type ACCOUNT_EXISTENCE). It only runs after all field validations pass. There is no name matching for KRW. The check only validates that the account number and bank code pair is valid. We would thus return an outcomes.[].type of type ACCOUNT_EXISTENCE.
- Wise calls the data provider service with the recipient's bank code and account number.
- Data provider verifies that the account number is valid for the given bank.
- If the account/bank pair is invalid, the outcome is blocking and recipient creation fails with an error.
- If the account is valid, the outcome is
SUCCESS.
There is no name matching step. The verification only confirms account existence. The resolvedName, providedName, and recommendedUpdates fields are always empty for KRW.
The fieldsChecked paths are the same in both V1 and V2 for KRW.
| Recipient type | Fields checked (V1 & V2) |
|---|---|
| South Korean (both personal and business) | details.accountNumber, details.bankCode |
If verification discovers the account/bank pair is invalid, this is blocking and recipient creation fails.
| Blocking outcome | Error code | Error path | When it happens |
|---|---|---|---|
INVALID_ACCOUNT_BANK_PAIR | INVALID_ACCOUNT_BANK_PAIR | account/details/accountNumber | Data provider says the account number is not valid for the selected bank. |
Sample blocking error (Invalid account/bank pair)
{
"errors": [
{
"code": "INVALID_ACCOUNT_BANK_PAIR",
"path": "account/details/accountNumber",
"message": "The entered account number is not valid for the selected bank."
}
]
}| Outcome | Blocking? | When it happens |
|---|---|---|
SUCCESS | No | Account number is valid for the selected bank. |
COULD_NOT_CHECK | No | PayGate service returned an error or timed out. |
| (blocks creation) | Yes | Account number is not valid for the selected bank. |
| Outcome | Recipient created? | What to do |
|---|---|---|
SUCCESS | Yes | Proceed with the transfer. No additional action needed. |
COULD_NOT_CHECK | Yes | Inform the user that verification wasn't possible. If they accept, make PATCH request to proceed. |
| (blocking error) | No | Fix the invalid input and retry recipient creation. |
KRW never produces PARTIAL_FAILURE or non-blocking FAILURE outcomes. The only possible non-blocking outcomes are SUCCESS and COULD_NOT_CHECK.
Both V1 and V2 endpoints run the same validations and verifications. The difference is the field naming and how the confirmation result is returned.
| Aspect | /v1/accounts/ | /v2/accounts/ |
|---|---|---|
| Confirmations in response | Always included in the recipient response (if available) | Only included if you request them via responseConfiguration.additionalInformation |
| Fields checked paths | details/accountNumber, details/bankCode | details/accountNumber, details/bankCode |
| Accept confirmation | PATCH /v1/accounts/{id}/confirmations | PATCH /v2/accounts/{id}/confirmations |
Unlike other currencies, the fieldsChecked paths are identical between V1 and V2 for KRW because bankCode and accountNumber paths are the same in both versions.
When creating a recipient with V2, include the following in your request to receive the confirmations field:
{
"type": "south_korean_paygate",
"details": { ... },
"responseConfiguration": {
"additionalInformation": ["CONFIRMATION_RESULT"]
}
}Without this, V2 will create the recipient and run all checks, but will not include the confirmations field in the response. You would then need to fetch it separately via GET /v2/accounts/{id}.
All payloads below show the confirmations field as it appears in the response after creating a recipient.
Because KRW is account-existence-only, there is no resolvedName, providedName, or recommendedUpdates.
{
"id": 123456,
"type": "south_korean_paygate",
"accountHolderName": "Kim Minjun",
"details": {
"bankCode": "088",
"accountNumber": "1234567890"
},
"confirmations": {
"acceptedOutcomes": false,
"acceptedAt": null,
"quoteId": null,
"outcomes": [
{
"type": "ACCOUNT_EXISTENCE",
"outcome": "SUCCESS",
"timestamp": "2026-03-08T10:30:00Z",
"requiresCustomerAcceptance": false,
"fieldsChecked": ["details/accountNumber", "details/bankCode"],
"message": null,
"resolvedName": null,
"providedName": null,
"recommendedUpdates": []
}
]
}
}{
"id": 123456,
"type": "south_korean_paygate",
"accountHolderName": "Kim Minjun",
"details": {
"bankCode": "088",
"accountNumber": "1234567890"
},
"confirmations": {
"acceptedOutcomes": false,
"acceptedAt": null,
"quoteId": null,
"outcomes": [
{
"type": "ACCOUNT_EXISTENCE",
"outcome": "COULD_NOT_CHECK",
"timestamp": "2026-03-08T10:30:00Z",
"requiresCustomerAcceptance": true,
"fieldsChecked": ["details/accountNumber", "details/bankCode"],
"message": "We couldn't verify the account right now. You can still proceed.",
"resolvedName": null,
"providedName": null,
"recommendedUpdates": []
}
]
}
}Returned when an internal Wise error occurs.
The requiresCustomerAcceptance field is true when the outcome value is COULD_NOT_CHECK.
Before you can use the recipient for a transfer, you must make a PATCH request to confirm the user has acknowledged the result.
For KRW, acceptance is only needed for COULD_NOT_CHECK. SUCCESS does not require acceptance, and FAILURE (invalid account/bank pair) is blocking, so there's no confirmation to accept.
Endpoint: PATCH /v1/accounts/{accountId}/confirmations or PATCH /v2/accounts/{accountId}/confirmations
Body:
{
"acceptedOutcomes": true
}The response mirrors the original confirmations object, but now acceptedOutcomes is true and acceptedAt contains a timestamp:
{
"confirmations": {
"acceptedOutcomes": true,
"acceptedAt": "2026-03-08T10:35:00Z",
"quoteId": null,
"outcomes": [
{
"type": "ACCOUNT_EXISTENCE",
"outcome": "COULD_NOT_CHECK",
"timestamp": "2026-03-08T10:30:00Z",
"requiresCustomerAcceptance": true,
"fieldsChecked": ["details/accountNumber", "details/bankCode"],
"message": "We couldn't verify the account right now. You can still proceed.",
"resolvedName": null,
"providedName": null,
"recommendedUpdates": []
}
]
}
}- Create a recipient via
POST /v1/accounts/(or V2) with valid details. - Inspect the response. Check the
confirmations.outcomes.outcomefield. - If outcome requires acceptance (
requiresCustomerAcceptance: true), callPATCH /v1/accounts/{id}/confirmationswith{"acceptedOutcomes": true}. - Create a transfer using the accepted recipient.
Recipient verification is not available in the sandbox environment for KRW because the data provider is disabled in the sandbox. This means that in sandbox, verification will always return COULD_NOT_CHECK.
To test the full verification flow with actual account validation, you must test in a staging or production-like environment. Contact the Wise team for testing options.
| Test scenario | Expected outcome |
|---|---|
| Any valid account/bank pair | COULD_NOT_CHECK |
| Any invalid account/bank pair | COULD_NOT_CHECK — (no validation occurs) |
| Invalid account number format (outside 10–16 digits) | Blocking field error: NOT_VALID on details/accountNumber |
| Invalid bank code | Blocking field error: NOT_VALID on details/bankCode |
| Test scenario | Expected outcome |
|---|---|
| Valid account number for the selected bank | SUCCESS |
| Invalid account number for the selected bank | Blocking error: INVALID_ACCOUNT_BANK_PAIR |
| Data provider service error/timeout | COULD_NOT_CHECK |
| Invalid account number format | Blocking field error: NOT_VALID on details/accountNumber |