# Acme RHB Bank Malaysia Payments (API) (/guides/rhb-my-payments)



This describes validations / allowed data formats for Acme payments going
through RHB Bank Malaysia. These will be validated by Acme and further validated by
the bank. These rules may be stricter than what the bank requires.

### Common Definitions [#common-definitions]

* SWIFT Character Set:
  * The 26 uppercase Latin letters `A`-`Z`
  * The 26 lowercase Latin letters `a`-`z`
  * The 10 digits `0`-`9`
  * Forward slash `/`
  * Hyphen `-`
  * Question mark `?`
  * Colon `:`
  * Left and right parentheses `(` `)`
  * Full stop `.`
  * Comma `,`
  * Single quote `'`
  * Plus sign `+`
  * Space ` `

* BIC11:
  * 11-character Bank Identifier Code

## General notes [#general-notes]

* The format for BIC (used in `receiver.bank`) is strictly validated using `[A-Z]{6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3})?`
  (as specified in [ISO20022 BICFIIdentifier](https://www.iso20022.org/standardsrepository/type/BICFIIdentifier)).
* RHB support both Pre-authorization (STP) flow and authorization flow via RHB Reflex, the configuration is done on RHB's backend.

## MY\_IBG [#my_ibg]

Malaysia Interbank GIRO — next-day settlement.

<Callout type="warn" title="Important">
  * Currency must be **MYR only**.
  * `customerReference` max length is **20 characters** for RHB payments.
  * Receiver's `residencyStatus` is mandatory for MY IBG.
</Callout>

| field                                   | pattern / charset                                             | max length     | mandatory/optional |
| --------------------------------------- | ------------------------------------------------------------- | -------------- | ------------------ |
| payments\[N].customerReference          | SWIFT                                                         | 20             | M                  |
| payments\[N].paymentDetails             | SWIFT                                                         | 140            | O                  |
| payments\[N].paymentAdviceEmails\[N]    | Valid email address <br /> Example: `["finance@company.com"]` | 500 (combined) | O                  |
| payments\[N].receiver.name              | SWIFT                                                         | 70             | M                  |
| payments\[N].receiver.bank              | Alphanumeric (BIC/SWIFT code)                                 | 11             | M                  |
| payments\[N].receiver.bankAccountNumber | Numeric                                                       | 20             | M                  |
| payments\[N].receiver.residencyStatus   | `RESIDENT` or `NON_RESIDENT`                                  |                | M                  |

Example Request:

```json
{
  "type": "MY_IBG",
  "amount": 1000,
  "currency": "MYR",
  "senderAccountId": "intacc_0H3BQNTQGBW2W",
  "customerReference": "INV-001",
  "paymentDetails": "Payment for invoice 001",
  "paymentAdviceEmails": ["finance@example.com"],
  "receiver": {
    "name": "Ahmad bin Ali",
    "bank": "PBBEMYKLXXX",
    "bankAccountNumber": "1234567890",
    "residencyStatus": "RESIDENT"
  }
}
```

## MY\_IBFT [#my_ibft]

Malaysia Instant Fund Transfer via DuitNow Bank Account Transfer.

<Callout type="warn" title="Important">
  * Currency must be **MYR only**.
  * `customerReference` max length is **20 characters** for RHB payments.
  * Receiver's `residencyStatus` is mandatory for MY DuitNow Account Transfer.
  * Receiver's `accountType` is mandatory for MY DuitNow Account Transfer.
</Callout>

| field                                   | pattern / charset                                             | max length     | mandatory/optional |
| --------------------------------------- | ------------------------------------------------------------- | -------------- | ------------------ |
| payments\[N].customerReference          | SWIFT                                                         | 20             | M                  |
| payments\[N].paymentDetails             | SWIFT                                                         | 140            | O                  |
| payments\[N].paymentAdviceEmails\[N]    | Valid email address <br /> Example: `["finance@company.com"]` | 500 (combined) | O                  |
| payments\[N].receiver.name              | SWIFT                                                         | 60             | M                  |
| payments\[N].receiver.bank              | Alphanumeric (BIC/SWIFT code)                                 | 11             | M                  |
| payments\[N].receiver.bankAccountNumber | Numeric                                                       | 20             | M                  |
| payments\[N].receiver.residencyStatus   | `RESIDENT` or `NON_RESIDENT`                                  |                | M                  |
| payments\[N].receiver.accountType       | `CHECKING` or `SAVINGS`                                       |                | M                  |

Example Request:

```json
{
  "type": "MY_IBFT",
  "amount": 1000,
  "currency": "MYR",
  "senderAccountId": "intacc_0H3BQNTQGBW2W",
  "customerReference": "INV-001",
  "paymentDetails": "Payment for invoice 001",
  "paymentAdviceEmails": ["finance@example.com"],
  "receiver": {
    "name": "Ahmad bin Ali",
    "bank": "PBBEMYKLXXX",
    "bankAccountNumber": "1234567890",
    "residencyStatus": "RESIDENT",
    "accountType": "SAVINGS"
  }
}
```

## Payment Response [#payment-response]

* RHB returns a reference Id upon payment created successfully, this is returned in the `bankReference` field.
* The `underlyingErrorMessage` field should contains payment status code and error message returned by RHB (if any).

Example of underlyingErrorMessage from RHB:

```
"underlyingErrorMessage" : "N3: Invalid Account Number"
```

Payment status definition:

| Status       | Description                                                                 |
| ------------ | --------------------------------------------------------------------------- |
| `PROCESSING` | Status upon creation                                                        |
| `SUBMITTED`  | Payment submitted to RHB, awaiting final confirmation (polling in progress) |
| `COMPLETED`  | Payment posting successful                                                  |
| `FAILED`     | Payment unsuccessful or rejected by RHB. (check `resultCode` for details)   |

Possible result Code for failed payments:

| resultCode             | Description                                                          |
| ---------------------- | -------------------------------------------------------------------- |
| `REQUEST_TIMEOUT`      | Payment posting timeout.                                             |
| `PAYMENT_EXPIRED`      | Payment expired.                                                     |
| `PAYMENT_CANCELLED`    | Payment aborted or cancelled by user.                                |
| `PAYMENT_REJECTED`     | Payment rejected.                                                    |
| `REJECTED_BY_APPROVER` | Payment rejected by authorizer.                                      |
| `OTHERS`               | Default resultCode if status code return is not a known status code. |

Example response:

```json
{
  "id": "pymt_0Q0T6K4DZFRZT",
  "type": "MY_IBFT",
  "amount": 100,
  "currency": "MYR",
  "bankReference": "260408894262",
  "customerReference": "ACMELVIBG02",
  "senderAccountId": "intacc_0H3BQNTQGBW2W",
  "receiver": {
    "name": "John Doe",
    "bank": "PBBEMYKLXXX",
    "bankAccountNumber": "1234567890",
    "address": {},
    "residencyStatus": "RESIDENT",
    "accountType": "SAVINGS"
  },
  "paymentDetails": null,
  "currencyExchange": {
    "fxContractId": null
  },
  "senderAccountCurrency": "MYR",
  "status": "COMPLETED",
  "resultCode": null,
  "paymentAdviceEmails": ["finance@example.com"],
  "createdAt": "2026-04-08T05:12:14.447Z",
  "updatedAt": "2026-04-08T05:12:14.936Z"
}
```
