When you create an IDR 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 IDR recipients.
IDR supports one recipient type only:
| Recipient type | API value | Description |
|---|---|---|
| Indonesian Local | indonesian | Bank code + bank account number. |
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 indonesian:
| Field | Rules | Error if invalid |
|---|---|---|
| Bank Code | Must be a valid bank code from the Wise bank list for Indonesia. | NOT_VALID |
| Account Number | 7–18 digits only (bank-specific length requirements apply). | NOT_VALID |
| Name | At least first name + last name (two words separated by a space). Max length validated. | NOT_VALID |
{
"errors": [
{
"code": "NOT_VALID",
"path": "name/fullName",
"message": "The name provided is not valid."
}
]
}Verification checks name matching (type NAME_MATCHING) in a single call to the data provider. It only runs after all field validations pass.
- Wise calls the data provider API with the recipient's bank code and account number.
- Data provider first verifies the account exists.
- If not, the outcome is blocking: either
DOES_NOT_EXIST(account not found) orACCOUNT_CLOSED(account has been closed). In both cases, recipient creation fails. - If the account exists, the data provider returns the registered name on the account.
- If not, the outcome is blocking: either
- Wise compares the registered name with the name you provided using our name-matching algorithm.
The comparison produces one of two results:
| Confidence | What it means | Outcome | Requires acceptance? |
|---|---|---|---|
| GREEN | Names match | SUCCESS | No. Proceed with transfer. |
| YELLOW/RED | Names don't match (partial or complete mismatch) | PARTIAL_FAILURE | Yes. Show result to user and call PATCH to accept. |
Unlike some other currencies, IDR does not distinguish between partial and complete name mismatches at the API level. All non-matching results (whether a close match or a completely different name) produce PARTIAL_FAILURE. IDR does not have a non-blocking FAILURE outcome from name matching.
If the data provider returns an error or if the bank is not supported, the outcome is COULD_NOT_CHECK. The recipient is still created, but you should inform the user that verification wasn't possible.
| Recipient type | Fields checked (V1) | Fields checked (V2) |
|---|---|---|
| Indonesian Local | accountHolderName, details/bankCode, details/accountNumber | name/fullName, details/bankCode, details/accountNumber |
In some cases, verification discovers the account is invalid at the provider level. These are blocking as they cause the recipient creation to fail, even though field-level validation passed.
| Blocking outcome | Error code | Error path | When it happens |
|---|---|---|---|
DOES_NOT_EXIST | INVALID_ACCOUNT_NOT_EXIST | details/accountNumber | Data provider says the account number does not exist. |
ACCOUNT_CLOSED | INVALID_ACCOUNT_ACCOUNT_CLOSED | details/accountNumber | Data provider says the account has been closed. |
{
"errors": [
{
"code": "INVALID_ACCOUNT_NOT_EXIST",
"path": "details/accountNumber",
"message": "The account does not exist."
}
]
}| Outcome | Blocking? | When it happens |
|---|---|---|
SUCCESS | No | Name matches |
PARTIAL_FAILURE | No | Name doesn't match |
COULD_NOT_CHECK | No | Bank is not supported by data provider verification |
COULD_NOT_CHECK | No | Data provider API returned an error or timed out |
| (blocks creation) | Yes | Account not found at data provider |
| (blocks creation) | Yes | Account has been closed |
| Outcome | Recipient created? | What to do |
|---|---|---|
SUCCESS | Yes | Proceed with the transfer. No additional action needed. |
PARTIAL_FAILURE | Yes | Show the verification result to the end user. The recommendedUpdates field contains the registered name from the bank. You can suggest the user update the name. If they accept, call PATCH /v1/accounts/{id}/confirmations (or V2 equivalent). |
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. |
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 |
| Name field path in confirmations | accountHolderName | name/fullName |
| Recommended update path | accountHolderName | name/fullName |
| Accept confirmation | PATCH /v1/accounts/{id}/confirmations | PATCH /v2/accounts/{id}/confirmations |
When creating a recipient with V2, include the following in your request to receive the confirmations field:
{
"type": "indonesian",
"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.
In production, the resolvedName and providedName fields are null. Null fields may be omitted entirely from the actual API response. They are shown here as null for documentation completeness.
{
"id": 123456,
"type": "indonesian",
"accountHolderName": "Budi Santoso",
"details": {
"bankCode": "bca",
"accountNumber": "1234567890"
},
"confirmations": {
"acceptedOutcomes": false,
"acceptedAt": null,
"quoteId": null,
"outcomes": [
{
"type": "NAME_MATCHING",
"outcome": "SUCCESS",
"timestamp": "2026-03-08T10:30:00Z",
"requiresCustomerAcceptance": false,
"fieldsChecked": ["accountHolderName", "details/bankCode", "details/accountNumber"],
"message": null,
"resolvedName": null,
"providedName": null,
"recommendedUpdates": []
}
]
}
}All name mismatches for IDR, whether a close match or a completely different name, produce PARTIAL_FAILURE. The recommendedUpdates field contains the registered name from BCA, so you can suggest the user update the name.
{
"id": 123456,
"type": "indonesian",
"accountHolderName": "Budi Santoso",
"details": {
"bankCode": "bca",
"accountNumber": "1234567890"
},
"confirmations": {
"acceptedOutcomes": false,
"acceptedAt": null,
"quoteId": null,
"outcomes": [
{
"type": "NAME_MATCHING",
"outcome": "PARTIAL_FAILURE",
"timestamp": "2026-03-08T10:30:00Z",
"requiresCustomerAcceptance": true,
"fieldsChecked": ["accountHolderName", "details/bankCode", "details/accountNumber"],
"message": "The name you entered doesn't match the account holder's name. Please check and try again.",
"resolvedName": null,
"providedName": null,
"recommendedUpdates": [
{
"path": "accountHolderName",
"value": "Budi Santoso Wijaya"
}
]
}
]
}
}Returned when an internal Wise error occurs.
{
"id": 123456,
"type": "indonesian",
"accountHolderName": "Budi Santoso",
"details": {
"bankCode": "mandiri",
"accountNumber": "1234567890"
},
"confirmations": {
"acceptedOutcomes": false,
"acceptedAt": null,
"quoteId": null,
"outcomes": [
{
"type": "NAME_MATCHING",
"outcome": "COULD_NOT_CHECK",
"timestamp": "2026-03-08T10:30:00Z",
"requiresCustomerAcceptance": true,
"fieldsChecked": ["accountHolderName", "details/bankCode", "details/accountNumber"],
"message": "We couldn't verify the account holder's name right now. You can still proceed.",
"resolvedName": null,
"providedName": null,
"recommendedUpdates": []
}
]
}
}The requiresCustomerAcceptance field is true when the outcome value is PARTIAL_FAILURE or 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.
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": "NAME_MATCHING",
"outcome": "PARTIAL_FAILURE",
"timestamp": "2026-03-08T10:30:00Z",
"requiresCustomerAcceptance": true,
"fieldsChecked": ["accountHolderName", "details/bankCode", "details/accountNumber"],
"message": "The name you entered doesn't match the account holder's name. Please check and try again.",
"resolvedName": null,
"providedName": null,
"recommendedUpdates": [
{
"path": "accountHolderName",
"value": "Budi Santoso Wijaya"
}
]
}
]
}
}- 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.
The verification result depends on the relationship between the name you provide when creating the recipient and the registered name on the actual bank account at data provider.
IDR verification behavior in the sandbox depends on the data provider API availability. If unavailable, verification will return ``COULD_NOT_CHECK`.
| Test scenario | Expected outcome |
|---|---|
| Valid account, matching name | SUCCESS |
| Valid account, different name (partial or complete mismatch) | PARTIAL_FAILURE |
| Non-existent account number | Blocking error: INVALID_ACCOUNT_NOT_EXIST |
| Closed account | Blocking error: INVALID_ACCOUNT_ACCOUNT_CLOSED |
| Bank not supported by data provider verification | COULD_NOT_CHECK (NOT_SUPPORTED_BANK) |
| Data provider API error/timeout | COULD_NOT_CHECK (REMOTE_SERVER_ERROR) |
| Invalid account number format | Blocking field error: NOT_VALID on details/accountNumber |
| Single-word name (for example, "Budi") | Blocking field error: NOT_VALID on name/fullName |
All name mismatches for IDR produce PARTIAL_FAILURE. There is no separate FAILURE outcome for name mismatches.
The only FAILURE-mapped outcomes (DOES_NOT_EXIST, ACCOUNT_CLOSED) are blocking and result in errors, rather than non-blocking confirmation outcomes.