8.0 KiB
Account Lookup & Transfer
Two-step process: look up the recipient to validate the account and get the holder name, then execute the transfer.
All endpoints are on the encrypted API (sfunc=n, session key). See README for the request format. The source account must belong to the currently selected profile — call P47 for its profile first (see 03-accounts.md).
Step 1 — Account Lookup — routePath: B40
One route resolves every supported input:
| Input format | Example | Resolves to |
|---|---|---|
Starts with 7, exactly 13 digits |
7700000000000 |
BML / local bank account |
Starts with 9, exactly 17 digits |
90100000000000000 |
MIB account |
Starts with 7 or 9, exactly 7 digits |
9600001 |
Favara mobile alias |
A followed by 6 digits |
A000001 |
Favara National ID alias |
Contains @ |
user@example.com |
Favara email alias |
Request:
{
"sfunc": "n",
"xxid": "<session xxid>",
"data": {
"search": "7700000000000",
"nonce": "<computed nonce>",
"appId": "<appId>",
"sodium": "<random 20-bit int>",
"routePath": "B40",
"xxid": "<session xxid>"
}
}
Input Rules
- Mobile aliases must be the bare 7 digits.
+960 9600001and+9609600001return no match. - National ID aliases need an uppercase
A—a000001returns no match,A000001resolves. The client uppercases the prefix before sending (MibTransferClient.kt). - Partial input (e.g.
9600) returns an emptydataarray.
Response
BML account:
{
"success": true,
"data": [
{
"benefName": "ACCOUNT HOLDER NAME",
"benefAccount": "7700000000000",
"bankCode": "MALBMVMV",
"benefBankName": "Bank of Maldives"
}
]
}
MIB account:
{
"success": true,
"data": [
{
"benefName": "ACCOUNT HOLDER NAME",
"benefAccount": "90100000000000000",
"bankCode": "MIB",
"benefBankName": "MIB",
"transferCy": "462",
"transferCyDesc": "MVR"
}
]
}
Favara alias (resolving to an MIB account):
{
"success": true,
"data": [
{
"benefName": "Account Holder Name ",
"benefAccount": "90100000000000000",
"bankCode": "MADVMVMV",
"benefBankName": "Maldives Islamic Bank PLC."
}
]
}
| Field | Description |
|---|---|
benefName |
Account holder name — trim whitespace |
benefAccount |
Resolved account number to use for the transfer |
bankCode |
"MIB" or a bank BIC (MADVMVMV = MIB, MALBMVMV = BML). Normalize "MIB" to MADVMVMV. |
benefBankName |
Bank display name |
transferCy / transferCyDesc |
Account currency — present for MIB account lookups only |
Lookup Errors
No match returns success: true with an empty data array:
{ "success": true, "data": [] }
Show "account not found" in that case.
Currency
| Lookup | Currency |
|---|---|
| MIB account | From transferCyDesc ("MVR" / "USD") |
| Favara alias → MIB | Not returned — unknown |
| BML / local | "MVR" — cross-bank lookups only resolve MVR accounts |
USD cross-bank accounts: a BML account denominated in USD cannot be resolved here. For USD BML→MIB transfers the user must first save a BML contact (see Notes below).
Step 2 — Execute Transfer
Two routes depending on the destination bank:
bankNo |
routePath |
Destination |
|---|---|---|
2 |
T50 |
MIB internal account |
3 |
T51 |
BML or other local bank (via Favara) |
Request:
{
"sfunc": "n",
"xxid": "<session xxid>",
"data": {
"benefName": "ACCOUNT HOLDER NAME",
"benefNo": "0",
"fromAccountNo": "90101000000001000",
"benefAccountNo": "7700000000000",
"transferCy": "462",
"benefCurrencyCode": "462",
"amount": "100.00",
"bankNo": "3",
"purpose": "",
"otp": "123456",
"otpType": "3",
"nonce": "<computed nonce>",
"appId": "<appId>",
"sodium": "<random 20-bit int>",
"routePath": "T51",
"xxid": "<session xxid>"
}
}
| Field | Description |
|---|---|
benefName |
Recipient name (from lookup) |
benefNo |
"0" (not a saved contact) |
fromAccountNo |
Source account number |
benefAccountNo |
Destination account number |
transferCy |
Currency numeric code ("462" = MVR, "840" = USD) |
benefCurrencyCode |
Same as transferCy |
amount |
Amount as string (e.g. "100.00", ".01") |
bankNo |
"2" = MIB internal, "3" = local/BML |
purpose |
Transfer remarks; may be empty |
otp |
Current TOTP code |
otpType |
"3" (authenticator OTP) |
Response — Success
T50 (internal):
{
"success": true,
"responseCode": "2",
"reasonCode": "2011",
"reasonText": "Internal transfer success",
"data": [
{ "date": "2026-05-16 15:10:25", "trxId": "97999863", "availableBalance": "37.41" }
],
"accountBalance": [ ... ]
}
T51 (local):
{
"success": true,
"responseCode": "2",
"reasonCode": "2011",
"reasonText": "Local transfer completed successfully via Favara",
"data": [
{ "date": "2026-05-16 15:10:25", "trxId": "817054125" }
]
}
| Field | Description |
|---|---|
trxId |
Transaction ID |
date |
Completion timestamp |
availableBalance |
T50 only — source account balance after the transfer |
accountBalance |
T50 only — refreshed balances for the selected profile (same shape as in 03-accounts.md) |
Response — Failure
Failures return HTTP 400 with an encrypted body:
{
"success": false,
"responseCode": "1",
"reasonCode": "213",
"reasonText": "Invalid OTP",
"data": [ { "otpId": "50487016" } ]
}
reasonCode |
reasonText |
Meaning |
|---|---|---|
213 |
Invalid OTP |
Wrong or stale OTP |
707 |
That OTP is already used! |
The OTP was already accepted for an earlier request |
201 |
Transaction currency does not match From Account currency! |
transferCy doesn't match the source account |
Show reasonText to the user.
OTP Retry
On 213 or 707 the client waits for the next 30-second TOTP window (plus 1 second for clock skew), generates a new code and resends the transfer once. A second failure of any kind is shown to the user (MibTransferHandler.kt).
Transfer Type Summary
| Recipient | Lookup | bankNo |
Transfer |
|---|---|---|---|
MIB (17-digit 9…) |
B40 |
2 |
T50 |
BML (13-digit 7…) |
B40 |
3 |
T51 |
| Favara alias → MIB | B40 |
2 |
T50 |
| Favara alias → BML | B40 |
3 |
T51 |
Currency Codes
transferCy |
Currency |
|---|---|
"462" |
MVR (Maldivian Rufiyaa) |
"840" |
USD |
Other Transfer-Screen Routes
Called by the official app when opening the transfer screen. Not consumed by thijooree.
routePath |
Request | Returns |
|---|---|---|
T63 |
— | Currencies with rates (numericCode, code, name, rate) |
T66 |
currencyCode |
Sell rate for a currency (sellRate) |
T70 |
— | Upload settings (numFiles, fileSize) |
T71 |
optional transferCy |
AML thresholds (eddAmount, cddAmount, currencyCode) |
MibIpsAccountInfo (client model)
B40 lookups are mapped into this structure (MibModels.kt):
| Field | Description |
|---|---|
accountName |
Account holder name (trimmed) |
accountNumber |
Resolved account number |
bankId |
Bank BIC (MADVMVMV = MIB, MALBMVMV = BML, etc.) |
currency |
"MVR", "USD", or "" (unknown) — see Currency above |
Notes
- BML → MIB USD transfers require a saved BML contact first. Because USD BML accounts can't be resolved via
B40, the app cannot validate the account number directly. The workaround inTransferFragment.ktis to add the BML account as a beneficiary (see 09-contacts.md), then transfer to that beneficiary. - Session expiry: see README for the unified expiry detection rules.
← Personal Profile Next → Contacts