# Contacts (Beneficiaries) Manage the user's saved beneficiary list. All endpoints are on the encrypted API (`sfunc=n`, session key) — see [README](README.md) for the request format. Contacts belong to the **currently selected** profile — call `P47` for the profile first (see [03-accounts.md](03-accounts.md)). Every write returns a `beneficiaryVersion` counter that increments on each change. --- ## List Contacts — `routePath: B41` **Request**: ```json { "sfunc": "n", "xxid": "", "data": { "start": 1, "end": 10, "benefType": "A", "search": "", "includeCount": 1, "searchCategoryId": 0, "sortBenef": "", "nonce": "", "appId": "", "sodium": "", "routePath": "B41", "xxid": "" } } ``` | Field | Example | Description | |---|---|---| | `start` | `1` | First row (`rnum`, 1-based, inclusive) | | `end` | `10` | Last row (inclusive) | | `benefType` | `A` | `A`=All, `L`=Local, `I`=Internal, `S`=Swift | | `search` | `` | Search query (empty = all) | | `includeCount` | `1` | Include `total_count` | | `searchCategoryId` | `0` | Category filter (`0` = all) | | `sortBenef` | `` | Sort field (empty = default) | ### Pagination Rows are selected by their 1-based `rnum`, both ends inclusive. The client pages in windows of 10: | Page | `start` | `end` | |---|---|---| | 1 | `1` | `10` | | 2 | `11` | `20` | | N | `(N-1)*10 + 1` | `N*10` | The last row of the final page has `last: "1"`. Stop there, or when total fetched equals `total_count`. ### Beneficiary Types | `benefType` | Meaning | |---|---| | `I` | Internal (MIB to MIB) | | `L` | Local (other Maldivian banks, e.g. BML) | | `S` | Swift (international) | ### Response ```json { "success": true, "responseCode": "1", "reasonCode": "103", "reasonText": "beneficiary retrieval success", "total_count": "47", "pos": "0", "data": [ { "benefNo": "100001", "benefName": "Person Name", "benefAccount": "7700000000001", "benefType": "L", "bankColor": "#AC0000", "benefBankName": "Bank of Maldives PLC", "bankCode": "BML", "benefStatus": "A", "benefBankId": "3", "benefNickName": "Nickname", "benefSwiftCode": "MALBMVMV", "transferCy": "462", "transferCyDesc": "MVR", "customerImgHash": "", "benefImgHash": "", "benefCategoryID": "100002", "createdDate": "2025-05-25 10:38:49", "rnum": "1", "last": "0" } ], "categories": [ { "id": "100002", "categoryName": "Friends", "icon": "f095", "createdDate": "2023-05-18 14:35:22", "modifiedDate": "2023-05-19 12:06:05", "numBenef": "23" } ] } ``` | Field | Consumed | Description | |---|---|---| | `benefNo` | yes | Unique beneficiary ID — use for update and delete | | `benefName` | yes | Legal/full name; used as fallback when nickname is blank | | `benefNickName` | yes | User-assigned nickname (prefer over `benefName` for display) | | `benefAccount` | yes | Account number | | `benefType` | yes | `L`, `I`, or `S` | | `bankColor` | yes | Hex color for placeholder avatar background | | `benefBankName` | yes | Bank display name. Shown as transfer subtitle and contact detail (`MibContactParser.kt`). | | `bankCode` | yes | Short bank code (e.g. `"BML"`, `"MIB"`) | | `benefStatus` | yes | Beneficiary status (`"A"` = active) | | `transferCyDesc` | yes | Currency (e.g. `"MVR"`, `"USD"`) | | `customerImgHash` | yes | Hash for fetching the contact photo via `B46`. May be missing, blank, or the literal **string** `"null"` — the client filters all three so downstream code only sees a real hash or `null`. | | `benefCategoryID` | yes | Category ID — `"0"` means uncategorized | | `benefImgHash` | server-only | Photo set on the beneficiary itself; equals `customerImgHash` when set | | `benefSwiftCode` | server-only | SWIFT BIC — present in payload, not read by the app | | `benefBankId` | server-only | Numeric bank ID — not consumed | | `transferCy` | server-only | Currency numeric code (e.g. `"462"`) — only `transferCyDesc` is consumed | | `rnum` / `last` | server-only | Row number and last-row flag, used for paging | ### Categories Every `B41` response carries the full category list in `categories` — there is no separate categories call. | Field | Description | |---|---| | `id` | Category ID — use as `searchCategoryId` / `categoryId` | | `categoryName` | Display name | | `numBenef` | Number of beneficiaries in this category (string) | | `icon` | Icon code | --- ## Get Contact Photo — `routePath: B46` **Request** — route fields: ```json { "imageHash": "", "routePath": "B46" } ``` ### Response ```json { "success": true, "msg": "image found", "message": "image found", "profileImage": "" } ``` `profileImage` is raw base64 JPEG with no data URI prefix. Decode with `Base64.decode(value, Base64.DEFAULT)` then `BitmapFactory.decodeByteArray(...)`. Cache decoded bitmaps — the same hash may appear across multiple contacts. --- ## Create Contact — `routePath: B43` **Request** — route fields: ```json { "benefName": "RECIPIENT NAME", "benefAccount": "7700000000001", "bankNo": "3", "nickName": "Nickname", "transferCy": "462", "categoryId": "0", "image": "", "bankName": "Bank of Maldives PLC", "bankSwift": "MALBMVMV", "routePath": "B43" } ``` | Field | Description | |---|---| | `benefName` | Full name (from account lookup) | | `benefAccount` | Beneficiary account number | | `bankNo` | `"2"` = MIB, `"3"` = BML | | `nickName` | Display nickname — **max 20 characters** | | `transferCy` | Currency numeric code (`"462"` = MVR, `"840"` = USD) | | `categoryId` | Category ID (`"0"` = uncategorized) | | `image` | Base64 JPEG photo. Omit the field when there is no photo. | | `bankName` | Bank name from the login bank list (`A41` `bankData`) | | `bankSwift` | Bank BIC from the same list | | `bankNo` | `bankName` | `bankSwift` | |---|---|---| | `2` | Maldives Islamic Bank | `MADVMVMV` | | `3` | Bank of Maldives PLC | `MALBMVMV` | ### Response ```json { "success": true, "responseCode": "1", "reasonCode": "102", "reasonText": "beneficiary creation success", "data": [ { "benefNo": "1336023", "benefNickName": "Nickname", "customerImgHash": "", ... } ], "beneficiaryVersion": 8 } ``` ### Errors A nickname over 20 characters is rejected with HTTP `400`: ```json { "success": false, "responseCode": "2", "reasonCode": "201", "reasonText": "invalid nick name", "errorKey": "nickName" } ``` --- ## Update Contact — `routePath: B52` Same fields as `B43`, plus: | Field | Description | |---|---| | `benefNo` | Beneficiary to update | | `imageChanged` | `"1"` when a new `image` is sent, `"0"` to keep the current photo | **Request** — route fields: ```json { "benefName": "RECIPIENT NAME", "benefAccount": "7700000000001", "bankNo": "3", "nickName": "New nickname", "transferCy": "462", "categoryId": "100002", "benefNo": "240301", "imageChanged": "0", "bankName": "Bank of Maldives PLC", "bankSwift": "MALBMVMV", "routePath": "B52" } ``` ### Response ```json { "success": true, "responseCode": "1", "reasonCode": "107", "reasonText": "Beneficiary Updated Successfully", "data": [ { "benefNo": "240301", "benefNickName": "New nickname", "customerImgHash": "", ... } ], "beneficiaryVersion": 6 } ``` Reload the list with `B41` afterwards to pick up the change. --- ## Delete Contact — `routePath: B48` **Request** — route fields: ```json { "benefNo": "240301", "routePath": "B48" } ``` ### Response ```json { "success": true, "responseCode": "1", "reasonCode": "108", "reasonText": "Beneficiary deleted Successfully", "beneficiaryVersion": 7 } ``` ---   --- [← Transfer](08-transfer.md)