Mandiri Virtual Account

Prev Next
This content is currently unavailable in Indonesian. You are viewing the default (English) version.

Mandiri Virtual Account is a payment solution provided by Bank Mandiri, enabling customers to make payments using a unique virtual account number generated for each transaction. As one of Indonesia's leading banks with a strong reputation for innovation, Bank Mandiri is a popular choice for secure and efficient payment solutions.  

When customers select Mandiri Virtual Account at checkout, they are provided with a virtual account number. They can complete the payment through mobile banking, internet banking, or ATMs. Once the payment is processed, you receive an instant confirmation, ensuring a seamless and reliable transaction experience for you and your customers.


Features

Channel code

MANDIRI_VIRTUAL_ACCOUNT

Currency

IDR

Minimum amount

1

Maximum amount

50,000,000,000

User approval flow

PRESENT TO CUSTOMER

Reusable payment code

Custom payment code

Display merchant name

MERCHANT

Display user name

Set expiry

Settlement time

Instant

Refund

Partial refund

Multiple partial refund

Refund validity

N/A

Compatible integration

Payment API, Payment Links

Payment flow

Mobile banking

  1. Log in to Livin’ by Mandiri app

  2. Select IDR Transfer > Transfer to new recipient

  3. Enter virtual account number (e.g. 8860863623046)

  4. Enter or confirm payment amount

  5. Click Continue

  6. Enter MPIN

ATM

  1. Insert ATM Card

  2. Select preferred language

  3. Enter ATM PIN

  4. Select PAYMENT > MULTI PAYMENT

  5. Enter company code 88608 (XENDIT), then press CORRECT

  6. Enter virtual account number (e.g. 8860863623046), then press CORRECT

  7. Enter payment amount, then press CORRECT

  8. Confirm payment details

Crypto Merchant Integration: Payer Verification

Recent regulations in Indonesia require additional verification steps for payments made through BRI and Mandiri virtual accounts on crypto platforms. This guide will help you implement the necessary changes to comply with these requirements while maintaining a smooth payment experience for your end users.

Pilot Feature Notice

Payer verification is currently in pilot phase. You may encounter incomplete features, unexpected behavior, or changes to the API during development. We recommend thorough testing in sandbox environment and staying updated with our documentation for the latest changes.

Crypto Platform Exclusive

This feature is only available for crypto platforms. If you operate a crypto platform and need access to this feature, please contact us at help@xendit.co.

What's Changed

Starting in August 2025 (pending bank approval), all payments made to BRI_VIRTUAL_ACCOUNT and MANDIRI_VIRTUAL_ACCOUNT must include payer verification data. This means you'll need to collect and verify the identity of end users making payments to ensure they match the registered account holder.

This requirement only affects BRI and Mandiri virtual accounts. Other payment channels continue to work as before.

New Prefixes/MID

As part of this change, new prefixes will be introduced:

  • Mandiri VA: 87910 (closed payment), 87909 (open payment)

  • BRI VA: Waiting for bank confirmation (will be updated)

Existing virtual accounts cannot be used with the new verification system and must be recreated using the new flow.

A. Integration Flow

The verification process works by comparing the payer's bank account details with the information you provide when creating the virtual account. Here's how it flows:

  1. Create Virtual Account: Include customer verification data when setting up the virtual account

  2. End User Makes Payment: When an end user pays, their bank details are automatically checked

  3. Verification Result: You receive the verification status in the payment webhook

  4. Handle Result: Take appropriate action based on whether verification passed or failed

B. How to Integrate

1. Virtual Account Creation

When creating virtual accounts for BRI or Mandiri, you'll now need to include verification data in the channel_properties. This data helps verify that payments come from the correct source. See routing payment channels for full list of required information.

All existing BRI and Mandiri virtual accounts must be recreated using this new flow. Previously created virtual accounts will not work with the verification system.

Request - POST /v3/payment_requests

{
  "reference_id": "crypto-user-12345",
  "type": "REUSABLE_PAYMENT_CODE",
  "country": "ID",
  "currency": "IDR",
  "channel_code": "MANDIRI_VIRTUAL_ACCOUNT",
  "channel_properties": {
    "expires_at": "2024-12-31T23:59:59Z",
    "display_name": "John Doe",
    "verification_data": {
      "customer_name": "John Doe",
      "accepted_name_variations": ["Jogn Doe", "John D", "J. Doe"],
      "allowed_bank_accounts": [
        {
          "bank_name": "BCA",
          "account_number": "2876783233",
          "account_name": "John Doe"
        },
        {
          "bank_name": "MANDIRI",
          "account_number": "1234567890",
          "account_name": "John Doe"
        }
      ]
    }
  }
}

Response

{
  "payment_request_id": "pr-90392f42-d98a-49ef-a7f3-abcezas123",
  "status": "ACCEPTING_PAYMENTS",
  "channel_code": "MANDIRI_VIRTUAL_ACCOUNT",
  "actions": [
    {
      "type": "PRESENT_TO_CUSTOMER",
      "descriptor": "VIRTUAL_ACCOUNT_NUMBER",
      "value": "87910123456789"
    }
  ]
}

Understanding Verification Fields

  • customer_name: The exact name registered for this crypto account.

  • accepted_name_variations: Common variations of the customer's name (typos, abbreviations, etc.).

  • allowed_bank_accounts: List of bank accounts that are permitted to send payments to this virtual account. You can  refer to Indonesia bank channel names for bank_name , however we won’t do any validation for that parameter.

2. Handle Verification Results

When an end user makes a payment, you'll receive a webhook with verification results. The webhook includes information about whether the payer's details match your verification criteria.

Note: The verification_result object will only be present for BRI_VIRTUAL_ACCOUNT and MANDIRI_VIRTUAL_ACCOUNT payments using the new verification system.

For comprehensive guidance on implementing webhooks, refer to our webhook handling documentation. If you experience webhook delivery issues, check our delayed webhooks guide.

Webhook Example

{
  "event": "payment.capture",
  "business_id": "5f27a14a9bf05c73dd040bc8",
  "created": "2025-07-03T07:00:27.200Z",
  "data": {
    "payment_id": "py-889cfe14-8a20-4fe6-823e-2363fc22ba9e",
    "status": "SUCCEEDED",
    "channel_code": "MANDIRI_VIRTUAL_ACCOUNT",
    "reference_id": "crypto-user-12345",
    "request_amount": 1000000,
    "payment_details": {
      "payer_name": "John Doe",
      "payer_account_number": "2876783233",
      "issuer_name": "MANDIRI",
      "verification_result": {
        "is_eligible": true,
        "sender_verification": {
          "result": "SENDER_MATCHED",
          "reason": "Name matched"
        },
        "risk_assessment": {
          "result": "NONE",
          "reason": "No alert"
        }
      }
    }
  }
}

Verification Status Types

Status

Description

Action Required

SENDER_MATCHED

Payer details match your verification data

Process payment normally

UNKNOWN

Verification couldn't determine if details match due to network timeout or other technical issues

Do not treat as successful payment, instead do a refund

Important Note on UNKNOWN Status

The UNKNOWN verification result is unlikely to occur under normal circumstances, as ineligible payments should typically be rejected outright. However, network timeouts during the verification process may occasionally result in this status. When you receive an UNKNOWN result, the payment should not be considered successful and you should either process a refund.

3. Updating Virtual Account Details

If you need to update the verification data for an existing virtual account (for example, when an end user adds a new bank account or changes their registered name), follow these steps:

Step 1: Cancel the Current Payment Request

POST /v3/payment_requests/{payment_request_id}/cancel

Step 2: Create a New Payment Request

Create a new payment request using the same virtual account number but with updated verification data:

{
  "reference_id": "crypto-user-12345-updated",
  "type": "REUSABLE_PAYMENT_CODE",
  "country": "ID",
  "currency": "IDR",
  "channel_code": "MANDIRI_VIRTUAL_ACCOUNT",
  "channel_properties": {
    "expires_at": "2024-12-31T23:59:59Z",
    "display_name": "John Doe",
    "virtual_account_number": "87910123456789",
    "verification_data": {
      "customer_name": "John Doe",
      "accepted_name_variations": ["Jogn Doe", "John D", "J. Doe"],
      "allowed_bank_accounts": [
        {
          "bank_name": "BCA",
          "account_number": "2876783233",
          "account_name": "John Doe"
        },
        {
          "bank_name": "MANDIRI",
          "account_number": "1234567890",
          "account_name": "John Doe"
        },
        {
          "bank_name": "BNI",
          "account_number": "9876543210",
          "account_name": "John Doe"
        }
      ]
    }
  }
}

This approach allows you to maintain the same virtual account number while updating the verification criteria.

4. Testing Your Integration

Simulate Successful Payments

You can test successful payments in sandbox using the simulation endpoint:

Request - POST /v3/payment_requests/{payment_request_id}/simulate

{
  "amount": 100000
}

Response

{
    "status": "PENDING",
    "message": "A simulated payment for the specified payment request id is being processed. You will be informed of the result via a webhook."
}

Test Verification Scenarios

To test different verification outcomes, you can create virtual accounts with specific customer names:

  • Successful Verification: Use the exact name you specify in customer_name

  • Unknown Verification: Create a virtual account with customer name "Josua Doe" - this will return verification_result.sender_verification.result: "UNKNOWN"

Example for Unknown Verification

{
  "channel_properties": {
    "verification_data": {
      "customer_name": "Josua Doe",
      "accepted_name_variations": ["J. Doe"],
      "allowed_bank_accounts": [...]
    }
  }
}

This will generate a webhook with "result": "UNKNOWN" for testing purposes.

C. Additional Notes

Recommended Rollout Plan

To minimize risk during implementation, we recommend a phased rollout approach, start with a small percentage of your user base and scale up as confidence grows. This approach allows you to catch and fix issues before they affect your entire user base.

Availability

  • Sandbox Environment: Available now for testing and development

  • Production Environment: Live activation for BRI_VIRTUAL_ACCOUNT and MANDIRI_VIRTUAL_ACCOUNT is scheduled for the second week of August 2025, pending bank approval.

Frequently Asked Questions

Q: What happens if I don't include verification data?
A: Payments to BRI and Mandiri virtual accounts will fail if verification data is missing after the feature goes live.

Q: Can end users use any bank account to pay?
A: Only bank accounts listed in the allowed_bank_accounts field will be accepted. Payments from other accounts will be rejected.

Q: What if an end user's name doesn't exactly match?
A: Use the accepted_name_variations field to include common variations of the end user's name.

Q: Can I still use my existing virtual accounts?
A: No, existing virtual accounts cannot be used with the new verification system. You must recreate them using the new flow with verification data.

Q: Do I need to implement this for all payment channels?
A: No, this requirement only applies to BRI_VIRTUAL_ACCOUNT and MANDIRI_VIRTUAL_ACCOUNT channels.

Q: What should I do with "UNKNOWN" verification results?
A: Do not treat these as successful payments. Either process a refund automatically or conduct manual review before accepting the payment, as UNKNOWN results typically indicate network timeouts during verification.

Q: Will the API change during the pilot phase?
A: Yes, since this is a pilot feature, there may be changes to the API structure, new fields, or modified behavior. Monitor our documentation for updates.

Q: Can I keep the same virtual account number when updating verification details?
A: Yes, you can specify the same virtual_account_number in the new payment request after canceling the previous one.

Q: How often do UNKNOWN verification results occur?
A: UNKNOWN results are rare and typically only occur due to network timeouts during the verification process. Under normal circumstances, ineligible payments should be rejected outright.