# CFCFRMS: I4C-MHA API Integration (Banks ↔ I4C 2.0) This is the runbook for the bank's real-time integration with the NCRP-CFCFRMS platform of I4C (Ministry of Home Affairs), built to the **I4C-MHA "Banks API Integration Specification 2.0"**. It covers what the integration does, how to configure and test it, and what an officer does with it day to day. The work is required by RBI letter **CO.DOS.KYC.No.S6675/11-01-006/2025-26 (05 Dec 2025)**. It asks banks, including Primary UCBs, to: - integrate by API for real-time action on cyber-fraud complaints; - cover every system and delivery channel; - periodically review the integration's performance to minimise failures. The older CFCFRMS demo (`/v1/cfcfrms/*`, `/v1/simulator/cfcfrms/*` and the Angular mock interceptor) is untouched. This integration lives beside it under `/v1/i4c/*`. --- ## 1. What happens to a complaint ``` I4C ──POST /auth/token──────────────► bank checks username/password (plain or CryptoJS-encrypted) → access_token I4C ──POST /complaints (Bearer)─────► bank checks token + source IP → validates → stores → ack {00, job_id} │ (after commit, on the I4C worker pool) ▼ for each incident (own transaction): find the account (savings, then current) layer 0 → find the debit, report where the money went layer ≥1 → hold up to the disputed amount at once, trace onward debits for any shortfall, keep the rest as a prospective hold ▼ bank ──POST ───────────────► I4C token bank ──POST (Bearer)──► I4C section 6 message: acknowledgement_no, job_id, transactions[] (outbox: retried with backoff until delivered) ``` ### Response types produced | txn_type_id | txn_type | When | |---|---|---| | 1 | Transaction Put on Hold | Money held on the account here. A 0.00 entry with remarks means nothing could be held yet; the amount is prospective. | | 3 | Money Transfer To | The money went on by outward IMPS/NEFT/RTGS (payee IFSC, account, UTR and I4C bank code), or to another account in this bank. | | 14 | Withdrawal through Cheque | Withdrawn at the branch against a cheque (clerk register or CTS clearing). A branch cash withdrawal above Rs 500 is also reported here, with remarks saying so (see §8). | | 17 | Others Less than equal to 500 | An untraced debit of Rs 500 or less. | | status_code 01 | Record not found | The account does not exist in this CBS. | | status_code 02 | Invalid RRN | The account exists, but no debit/credit of that amount near that date. | | 70010 | (in remarks) | The incident could not be processed after 5 attempts. It is reported so I4C is not left waiting, and is handled manually. | Types 5 (ATM), 6 (AEPS) and 11 (POS) are built to the specification's field lists, but are not produced today, because this CBS has no ATM, AEPS or POS channel. A channel that records those debits only has to classify them as `ATM_WITHDRAWAL` / `AEPS_WITHDRAWAL` / `POS_WITHDRAWAL` in `I4cTransactionTracer`, with the ATM / merchant details. The Money Transfer To entry carries the payee reference under **both** `rrn` (the section 6 table) and `rrn_transaction_id` (the section 6 sample), with the same value. ### Rules applied to holds These follow the MHA SOP for NCRP-CFCFRMS (02.01.2026) and RBI's draft KYC Amendment Directions on debit holds (Sep 2026). - **Only the disputed amount is held** as an amount hold (`AMOUNT_HOLD`). The rest of the balance stays usable. Every debit path honours the hold: counter, transfer, standing instruction, CTS inward and NACH. - **Prospective hold:** what the balance cannot cover is recorded as a shortfall. The *I4C Hold Review* job tops it up from later credits. - **Full debit freeze is never automatic.** An officer asks for it (savings only) and a different officer approves it. - **Review date** is set on every hold: 90 days by default. The register flags holds 15 days before it. - **Customer intimation deadline:** 24 hours by default ("by the end of the next day"). It is tracked in the register until an officer records how the customer was told. - **Release** always goes through maker-checker and records the reason and order: - IO order; - GRM decision (IO / DGRO / SGRO); - MRM restoration; - court order; - LEA direction; - 90-day review; - wrong account. --- ## 2. Endpoints ### Called by I4C (outside the Fineract login; see `SecurityConfig`) | Method | Path | Spec section | |---|---|---| | POST | `/fineract-provider/api/v1/i4c/auth/token` | 2: returns `{"access_token":"…","token_type":"Bearer","expires_in":900}` or 401 `{"message":"You are not authorized to access"}`. Credentials may come as JSON `username`/`password` or `client_id`/`client_secret`, as a form body, or as an `Authorization: Basic` header. | | POST | `/fineract-provider/api/v1/i4c/complaints` | 4 and 5: returns `{"meta":{"response_code":"00","response_message":"Success"},"data":{"acknowledgement_no":"…","job_id":"BANKS-…"}}`, or code `11` "Structure validation failed" (HTTP 400) | I4C sends no tenant header. These paths are served by the tenant in `fineract.i4c.tenant-identifier`. Other refusals: - 503 with code `70004` while the integration is disabled; - 403 from an IP not on the allowlist; - 413 (`70005`) above 1 MB; - 429 (`70006`) above 600 calls/minute from one IP; - 400 (`60015`) when an encrypted envelope cannot be decrypted. **How a push may authenticate** (section 2 names "Basic Auth / Auth 2.0" and credentials "in every request"). `fineract.i4c.inbound.auth-modes` lists the allowed ones; every one checks the same credentials and the same IP allowlist: | Mode | What I4C sends | |---|---| | `TOKEN` | `Authorization: Bearer ` from `/auth/token` | | `BASIC` | `Authorization: Basic base64(username:password)` | | `BODY` | `username` / `password` (or `client_id` / `client_secret`) inside the complaint JSON. They are removed from the message before it is stored. | Each credential may be plain, plain Base64 (the specification's text), or CryptoJS-encrypted (its samples). **Refused pushes.** With `ack.code-style=SECTION5` the ack is always `11` "Structure validation failed". With `SECTION7` it carries the specific section 7 code: `40001` invalid account number, `40004` invalid amount, `40005` invalid date (also a `transaction_date` more than `ack.max-future-days` ahead). **A repeat push** with the same acknowledgement number and the same incidents is never processed twice. With `ack.duplicate-mode=SAME_JOB` it gets `00` and the original job_id. With `CODE_50003` it gets HTTP 409 and `50003` "Duplicate Transaction", still with the original job_id. **Separate ack call.** The ack is always the reply to the push. If I4C also wants it as a call of its own (section 5 is titled "Ack Request Message from BANKS to I4C-MHA"), set `outbound.ack-path`. The ack is then queued with the request and delivered before the response. ### Officer API (ordinary login): `/v1/i4c/admin/*` | Path | Permission | |---|---| | `GET dashboard`, `requests`, `requests/{id}`, `holds`, `holds/{id}`, `hold-actions`, `outbox`, `api-log`, `api-log/{id}`, `bank-master`, `configuration` | `READ_I4C` | | `POST holds/{id}/actions` (`RELEASE` with an optional `amount` for a partial release, `UNFREEZE_AND_RELEASE`, `FREEZE`, `UNFREEZE`) | `REQUESTACTION_I4CHOLD` | | `POST hold-actions/{id}/approve`, `.../reject` | `APPROVEACTION_I4CHOLD` (never your own request) | | `POST holds/{id}/intimation` (record by hand), `POST holds/{id}/intimation/send` (send now on the automatic channels) | `INTIMATE_I4CHOLD` | | `GET intimation-channels` | `READ_I4C` | | `PUT intimation-channels/{channel}`, `POST intimation-channels/{channel}/test` | `CONFIGURE_I4C` | | `POST outbox/{id}/retry`, `requests/{id}/reprocess` | `RETRY_I4C` | Every list (`requests`, `holds`, `hold-actions`, `outbox`, `api-log`, `bank-master`) is paged: it takes `offset` and `limit` (default 20, at most 500) and returns `{totalFilteredRecords, pageItems}`. Each list also takes `fromDate` / `toDate` (yyyy-MM-dd, both days included; not for `bank-master`) and its own filters, which are listed in the Swagger summary of each endpoint. ### GRM / MRM API (ordinary login): `/v1/i4c/cases/*` | Path | Permission | |---|---| | `GET grievances`, `grievances/{id}`, `restorations`, `restorations/{id}`, `pro-rata`, `mrm-balance-report`, `mrm-balance-report.csv`, `holds/{id}/statement.csv`, `documents`, `documents/{id}/content` | `READ_I4C` | | `POST holds/{id}/grievances`, `grievances/{id}/edd`, `…/submit`, `…/nodal`, `…/events`, `…/investigation`, `…/decision`, `…/escalate`, `…/withdraw` | `MANAGE_I4CGRIEVANCE` | | `POST grievances/{id}/action` (raise the account change an order needs) | `MANAGE_I4CGRIEVANCE` + `REQUESTACTION_I4CHOLD` | | `POST holds/{id}/restorations` (assess), `PUT restorations/{id}/request`, `POST restorations/{id}/bank-action`, `…/mrm-updated`, `victim-cases`, `restorations/{id}/receipt`, `…/victim-status` | `MANAGE_I4CRESTORATION` (bank action COMPLIED also needs `REQUESTACTION_I4CHOLD`) | | `POST restorations/{id}/retry-outward` | `APPROVEACTION_I4CHOLD` | | `POST documents` | `MANAGE_I4CGRIEVANCE` / `MANAGE_I4CRESTORATION` / `REQUESTACTION_I4CHOLD` by owner | In the UI: **CFCFRMS → I4C Live**. Its tabs are Dashboard, Complaints from I4C, Holds Register, Approvals, GRM Grievances, MRM Restorations, MRM Balance Report, Responses & API Log, Bank Code Master, and Intimation Settings. A hold's **GRM / MRM & Documents** tab opens a grievance or an MRM assessment, downloads the account statement and holds the IO / court orders. --- ## 3. Configuration (`application.properties`, all values from the environment) | Key / env var | Meaning | |---|---| | `fineract.i4c.enabled` / `FINERACT_I4C_ENABLED` | Master switch. Default `false`. | | `fineract.i4c.tenant-identifier` / `FINERACT_I4C_TENANT` | Tenant that serves I4C's calls. | | `fineract.i4c.bank-code` / `FINERACT_I4C_BANK_CODE` | This bank's code in the I4C Bank Code Master (`root_bankid`). | | `fineract.i4c.bank-name` | Name reported for internal transfers. Defaults to the master's name for the code. | | `…inbound.username` / `FINERACT_I4C_INBOUND_USERNAME` | Username the bank issues to I4C. | | `…inbound.password-hash` / `FINERACT_I4C_INBOUND_PASSWORD_HASH` | **bcrypt** hash of that password (production). | | `…inbound.password` / `FINERACT_I4C_INBOUND_PASSWORD` | Plain password. Used only when no hash is set (UAT). | | `…inbound.token-ttl-seconds` | Token lifetime. Default 900. | | `…inbound.allowed-ips` / `FINERACT_I4C_ALLOWED_IPS` | Comma-separated I4C source IPs. **Blank allows any IP, which is for UAT only.** | | `…inbound.trust-forwarded-for` | Set `true` only behind a reverse proxy that sets `X-Forwarded-For`. | | `…inbound.auth-modes` / `FINERACT_I4C_AUTH_MODES` | `TOKEN,BASIC,BODY` (default). List only the forms I4C uses. | | `…inbound.client-name` / `FINERACT_I4C_CLIENT_NAME` | Client name registered with I4C. The client ID and secret are the inbound username and password. | | `…crypto.mode` / `FINERACT_I4C_CRYPTO_MODE` | `FIELDS` (username/password encrypted, as in the spec), `ENVELOPE` (whole body as `{"data":"…"}`), or `NONE`. | | `…crypto.passphrase` / `FINERACT_I4C_CRYPTO_PASSPHRASE` | The "encryption logic" passphrase I4C shares. | | `…outbound.base-url` / `FINERACT_I4C_OUTBOUND_BASE_URL` | I4C's base URL (from I4C). `internal-simulator` routes to the local simulator. | | `…outbound.auth-path`, `…outbound.response-path` | Paths under the base URL. Defaults `/auth/token`, `/bank/response`. **Confirm with I4C.** | | `…outbound.ack-path` / `FINERACT_I4C_OUTBOUND_ACK_PATH` | Path for a separate ack call. Blank (default) = none. | | `…outbound.username`, `…outbound.password` | Credentials I4C issues to the bank. | | `…outbound.timeout-ms`, `…outbound.max-attempts` | Defaults 15000 ms and 8 attempts (backoff 30 s → 1 h). | | `…match.date-window-days` | ± days for amount/date matching. Default 2. | | `…ack.code-style` / `FINERACT_I4C_ACK_CODE_STYLE` | `SECTION5` (always 11) or `SECTION7` (40001 / 40004 / 40005). Default `SECTION5`. | | `…ack.duplicate-mode` / `FINERACT_I4C_ACK_DUPLICATE_MODE` | `SAME_JOB` (00 + original job_id) or `CODE_50003`. Default `SAME_JOB`. | | `…ack.max-future-days` | A `transaction_date` further ahead than this is refused (40005). Default 1. | | `…hold.review-days`, `…hold.intimation-hours` | Defaults 90 and 24. | | `…restoration.pool-account-no` / `FINERACT_I4C_RESTORATION_POOL_ACCOUNT` | Bank-owned savings account (of a bank client) that outward MRM restorations leave from. Blank = only restorations to accounts in this bank. | | `…restoration.fir-threshold` | MRM: above this amount in one complaint the IO must give an FIR. Default 50000. | | `…simulator.enabled` | Local stand-in for I4C. **Never `true` in production.** | To generate the bcrypt hash: `htpasswd -bnBC 10 "" 'the-password' | tr -d ':\n'` (or any bcrypt tool). Paste the result as `FINERACT_I4C_INBOUND_PASSWORD_HASH`. ### Jobs (Scheduler Jobs screen) - **I4C Dispatch**, every minute: - processes complaints the immediate worker did not finish; - sends responses waiting in the outbox; - purges expired tokens. - **I4C Hold Review**, every 15 minutes: tops up prospective holds, retries automatic intimation, and settles outward MRM restorations the fund-transfer module has finished. - Both do nothing while the integration is disabled. ### Database - **Migration `0610_cfcfrms_i4c_integration.xml`:** - tables `m_i4c_access_token`, `m_i4c_request`, `m_i4c_incident`, `m_i4c_finding`, `m_i4c_hold`, `m_i4c_hold_txn`, `m_i4c_hold_action_request`, `m_i4c_outbox`, `m_i4c_api_log`, `m_i4c_bank_master`; - five permissions; - two jobs. - **Migration `0611_i4c_bank_master_seed.xml`:** - the specification's Bank Code Master (491 entries); - the IFSC prefixes of 57 banks whose prefix is certain. - **Migration `0612_i4c_intimation_channels.xml`:** - `m_i4c_intimation_channel` (EMAIL switched on with a default subject and message; SMS and WHATSAPP switched off); - `m_i4c_intimation_log` (every notice sent, failed or recorded, per hold); - column `m_i4c_hold.auto_intimation_attempts`; - permission `CONFIGURE_I4C`. - **Migration `0613_i4c_grm_mrm.xml`:** - `m_i4c_grievance`, `m_i4c_grievance_event` (GRM), `m_i4c_restoration` (MRM, beneficiary and victim bank), `m_i4c_document` (files, with SHA-256); - columns `m_i4c_hold.released_amount`, `restored_amount`; `m_i4c_hold_action_request.amount`, `restoration_id`, `grievance_id`; - permissions `MANAGE_I4CGRIEVANCE`, `MANAGE_I4CRESTORATION`. ### GRM: grievances against a hold GRM and MRM are I4C web portals with no API. Officers act there; the CBS keeps the bank's record, the deadlines and the documents, and carries orders out on the account through maker-checker. 1. The customer asks the branch to remove the hold / unfreeze. Open a grievance on the hold (Holds Register → hold → **GRM / MRM**). 2. **EDD:** KYC re-verified, the customer's explanation of the credit, risk, and whether the bank supports the request. 3. Raise it on GRM with the KYC, application, photograph and bank statement (attach the same here; the statement downloads from the hold), then record the **GR id**. Stage NODAL_REVIEW. 4. The bank's GRM nodal officer approves (stage WITH_IO, **7 days**) or rejects. 5. The IO decides; if the IO investigates (notice, VC, Samanvaya) record it (**+15 days**). VC requests and information sought are noted in the history. 6. Decision as GRM shows it: *remove put on hold*, *unfreeze, hold continues*, *unfreeze and remove hold*, *keep a smaller amount* (partial), *rejected*, or *seek information*. An allowing decision needs the order number and the signed order copy, and starts a **48-hour** compliance clock. 7. **Raise the account change**: the request goes to a second officer on Approvals; approval changes the account and closes the grievance. 8. Rejected: escalate to the District GRO, then the State GRO (**15 days** each); after the State GRO the customer may go to court. ### MRM: money restoration **Beneficiary bank** (the money is held here): 1. **Assess** each complaint (hold → GRM / MRM → *Assess for MRM*): *possible by attribution*, *possible pro-rata* (the calculator splits what is held on an account by disputed amount), or *not possible* (already refunded / no balance / other) with the reason. Enter the same on MRM; the **MRM Balance Report** page gives every held account's balances for MRM's *Update Account Balance* (CSV). 2. When the victim's request comes from the IO, record the MR id, the refund account (IFSC blank = this bank), the IO, and the papers: a **court order**, or the IO's **BNSS 106 notice** with the victim's **indemnity bond**, plus the **FIR** above Rs 50,000. Attach their copies. 3. **Bank action:** *Compliance* checks the papers and raises a RESTORE request; *not complied* and *refer back to LEA* need the bank statement; *refer back to victim bank* and *consensus* are recorded for MRM. 4. A second officer approves the RESTORE on Approvals. In the same transaction the amount is released from hold and leaves the suspect account: straight to the victim's account if it is here (RESTORED at once, transaction id `CBS-`), otherwise to the **restoration pool** (IN_POOL) and on by NEFT / IMPS / RTGS through the fund-transfer module (its limits, time window, screening and approval apply). TRANSFER_PENDING becomes RESTORED when the transfer settles (Hold Review job). A failed or refused outward leaves the money in the pool for **Send again**, possibly to a corrected account; it never goes back to the suspect. 5. Enter amount, transaction id / UTR and time on MRM, then mark **Entered on MRM** to close. **Victim bank** (our customer lost the money, layer 0): open a victim-bank case with the complaint's ack no., record restored money received (amount, UTR, date, account), or why none is expected (already refunded through bank / police notice / court order, declined, declined to pursue, received through court, not reachable). ### Automatic customer intimation - **Where it is set:** CFCFRMS → I4C Live → **Intimation Settings**. Each channel (Email, SMS, WhatsApp) has an on/off switch, an order, and an editable message. Placeholders such as `{customerName}`, `{amountHeld}`, `{ackNo}` and `{reviewDate}` are filled per hold. Email has a "Send test email" box. - **What happens:** right after the response for a complaint goes to I4C, each new hold with money held is sent to the switched-on channels in order. The first one that reaches the customer marks the hold intimated (mode, "Sent automatically to …", user `system`). - **When it does not reach the customer** (no email on file, mail server down): the attempt is logged as FAILED or SKIPPED_NO_DESTINATION, and the Hold Review job retries up to 3 times. After that, or when no channel is switched on, the hold stays "not yet told". An officer then calls the customer (or writes, or meets them) and records it on the hold's **Customer Intimation** tab. - **Today:** only Email is in use. It goes through the CBS mail settings (`spring.mail.*`), the same ones the KYC notices use. SMS and WhatsApp use the CBS notification gateways and should be switched on only once those gateways are live. - Phone, letter and in-person notices can never be sent by the system. They are always recorded by hand. --- ## 4. Onboarding checklist 1. **Nodal officer / SPOC** registered with I4C. I4C emails them: - user ids and passwords (both directions); - the encryption logic / passphrase; - its public IPs; - UAT URLs. 2. **Give I4C what it needs from the bank:** - the endpoint base: `https:///fineract-provider/api/v1/i4c`; - the bank's public IP; - the client name, client id and client secret it asks for (the inbound username/password above). 3. **Connectivity.** The C-DOT *AWS Client VPN* SOP (IAM Identity Center SSO + MFA) is for **people**: developers and officers testing against UAT. A server cannot run it unattended. For the CBS server, ask C-DOT/I4C for IP whitelisting of the bank's egress IP, or a site-to-site tunnel. Open the firewall both ways: - inbound from I4C's IPs to the CBS on 443; - outbound from the CBS to I4C. 4. **Set the environment variables** in §3, with `fineract.i4c.enabled=true`, and restart. Check **I4C Live → Dashboard → Setup still needed**: it lists anything missing. 5. **Grant permissions:** - `READ_I4C` to the fraud cell and branch managers; - `REQUESTACTION_I4CHOLD` to makers; - `APPROVEACTION_I4CHOLD` to checkers (different people); - `INTIMATE_I4CHOLD` to branch staff; - `RETRY_I4C` to IT operations. 6. **Set the branch IFSCs** in Branch Profile (`m_office_profile.ifsc_code`). They are reported as `ifsc_code` / `root_ifsc_code`. 7. **Test in UAT** with I4C (§5), then switch to production URLs and credentials. --- ## 5. Testing without I4C (local / UAT) Set: ``` FINERACT_I4C_ENABLED=true FINERACT_I4C_SIMULATOR_ENABLED=true FINERACT_I4C_OUTBOUND_BASE_URL=internal-simulator FINERACT_I4C_INBOUND_USERNAME=i4c-test FINERACT_I4C_INBOUND_PASSWORD=i4c-test-pass FINERACT_I4C_BANK_CODE= ``` Then, with a funded active savings account `000000012345`: ```bash H='https://localhost:8443/fineract-provider/api/v1' # 1. Simulate a layer-1 push (fraud money credited to this account) curl -k -X POST "$H/i4c-sim/push" -H 'Content-Type: application/json' \ -d '{"accountNumber":"000000012345","amount":"2500.00","disputedAmount":"2500.00","rrn":"612345678901","transactionDate":"2026-10-20","layer":"1"}' # 2. Or go through the real inbound API exactly as I4C would TOKEN=$(curl -sk -X POST "$H/i4c/auth/token" -H 'Content-Type: application/json' \ -d '{"username":"i4c-test","password":"i4c-test-pass"}' | sed 's/.*"access_token":"\([^"]*\)".*/\1/') curl -k -X POST "$H/i4c/complaints" -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d @complaint.json # 3. See what the bank sent "I4C" curl -k -X POST "$H/i4c-sim/received" ``` What to check: - The ack is `00` with a `job_id`. - The account shows an *Amount Hold* transaction, and its available balance dropped by the held amount. - A withdrawal above the remaining balance is refused. - **I4C Live → Complaints** shows the complaint as PROCESSED, with the response SENT. - **Holds Register** shows the hold. Raise a release as one user. Approving it as the same user is refused; approving it as a second user releases the amount on the account. The backend unit tests are under `fineract-provider/src/test/java/org/apache/fineract/portfolio/cfcfrms/i4c/`: ``` ./gradlew :fineract-provider:test --tests "org.apache.fineract.portfolio.cfcfrms.i4c.*" ``` --- ## 6. Daily operations - **Dashboard.** Watch these figures: - *Customer intimation overdue*; - *Holds due for 90-day review*; - *Release / freeze awaiting approval*; - *Responses failed*. The API performance table (calls, failures, average and max ms in each direction, average complaint-to-response time) is the RBI para 4 periodic review. Export it monthly for the Board / IT committee. - **Holds Register:** - customer intimation: check the automatic notice in the hold's intimation history, press **Send now** to resend, or call the customer and record it; - raise releases on IO / court orders (in full, or the amount the order releases); GRM and MRM orders are raised from their records; - raise a full debit freeze only on an explicit direction. - **GRM Grievances / MRM Restorations:** filter *Past deadline only* every morning; carry out allowed orders within 48 hours; send pooled restorations again; mark restorations entered on MRM. - **Approvals:** a second officer approves or rejects. Approval acts on the account immediately. If the account refuses (closed, hold already released at the counter), the request becomes FAILED with the reason. - **Responses & API Log:** - retry FAILED responses; - open any call to see the masked request and response. --- ## 7. Security notes - I4C's token is 32 random bytes. Only its SHA-256 hash is stored. It expires after `token-ttl-seconds`. - Every inbound call checks the token **and** the source IP allowlist. - Credentials, tokens and PANs are masked in the API log and in the stored payload. - The inbound password should be supplied as a bcrypt hash. All secrets come from environment variables; none are committed defaults. - Holds placed automatically are attributed to the CBS **system** user. Releases and freezes are attributed to the approving officer, with the maker recorded. - The simulator endpoints answer 404 unless `fineract.i4c.simulator.enabled=true`. --- ## 8. Known limits of this CBS (stated honestly) - **No RRN/UTR on account transactions.** - A reported credit is matched by RRN only where the CBS holds one: outward fund transfers (`m_fund_transfer.utr/txn_ref`), or an RRN quoted in a transaction note or transfer description. - Otherwise it is matched by **account, exact amount and date ± window**. The match method is shown per incident. - Inbound IMPS is a stub that posts no credit. - **Follow-up:** store the UTR/RRN on inward postings. - **No UPI, ATM, POS or AEPS channels.** The response formats for ATM (5), AEPS (6) and POS (11) are built and tested, but nothing produces them until such a channel exists. - **Branch cash withdrawals** have no specification type. Above Rs 500 they are reported as type 14 with an empty cheque number and remarks "Cash withdrawal at branch counter (no cheque)". **Confirm with I4C.** - **Current accounts:** the amount hold works, but the CBS's current-account debit block does not reach the account, so a full debit freeze is offered on savings accounts only. - **Current-account transfer legs** are not linked transaction-to-transaction, so onward tracing from a current account is limited to counter withdrawals. - **Payee bank name:** only IFSC prefixes in the seeded list map to an I4C bank code. Others are reported with code 0 and the IFSC in full. - **GRM and MRM** are I4C portal modules with no published API. Officers act there and record it here; nothing is sent to the portals automatically. - **Outward restorations** go only from a savings pool account (the fund-transfer module debits savings accounts only); the pool must be configured, and its client's transfer limits must allow the amounts. - **Current accounts** cannot be debit-frozen (above); GRM *unfreeze* orders apply to savings accounts only. --- ## 9. Questions to settle with I4C / C-DOT 1. Exact URL paths for the bank → I4C token, response and (if any) ack calls, and the token lifetime. 2. Is the section 5 ack the synchronous HTTP response to the push, or also a separate call? Both are supported; set `outbound.ack-path` for the second. 3. Encryption: only username/password (assumed, `FIELDS`), or the whole payload? Is it the CryptoJS/OpenSSL passphrase format (AES-256-CBC, EVP_BytesToKey-MD5) as the samples suggest? 4. Which code set does the ack use, `00`/`11` (section 5) or the section 7 codes (`40001`…)? Both are supported (`ack.code-style`). And does a repeat push get `00` or `50003` (`ack.duplicate-mode`)? Which auth form will I4C use: token, Basic, or credentials in the message (`inbound.auth-modes`)? 5. The specification's samples have typos (`mode_of _payment`, `acknowledment_no`, `approval_code.`). Which spelling will I4C actually send? The parser accepts all of them. 6. The date format for `transaction_datetime` (`yyyy-MM-dd HH:mm:ss` assumed). 7. How to report branch cash withdrawals and debits of unknown channel. 8. For layer ≥ 1, is `payer_account_number` the account at the receiving bank (assumed)? 9. Production IP whitelisting or site-to-site connectivity in place of the user VPN.