Files
CBS-Mobile-App/src/services/api/endpoints.ts
T
Abin ToppoandClaude Opus 5.5 abb14d5768 Implement IMPS fund transfer via initiate and verify-otp
Initiate runs the IMPS name inquiry and sends an OTP; verify-otp sends
ReqPay. The result screen now distinguishes success, failure and
pending reconciliation. The payer is temporarily fixed to the test
account 002002000100019, and the to-mobile form no longer blocks on
mobile/MMID format.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 16:02:03 +05:30

222 lines
7.6 KiB
TypeScript

export const endpoints = {
/** Unauthenticated by necessity — between them these produce a session. */
registration: {
start: '/registration',
verifyOtp: '/registration/verify-otp',
mpin: '/registration/mpin',
},
crypto: {
publicKey: '/crypto/public-key',
},
/**
* Server-driven feature switches. Deliberately callable without a session —
* the sign-in screen's own controls are gated, so this has to resolve before
* anyone has signed in.
*/
features: {
config: '/features/config',
},
auth: {
login: '/auth/login',
me: '/auth/me',
logout: '/auth/logout',
},
accounts: {
/**
* Every account on the signed-in profile. No parameters — the profile comes
* entirely from the session. This is the only endpoint that returns a full
* account number rather than a masked one.
*/
list: '/accounts',
mmid: '/accounts/mmid',
/**
* One transactable account's current balance, by `accountNumber` query
* parameter. Read live from the bank on every call — nothing is cached
* here, and nothing about a balance may be.
*
* SAVINGS and CURRENT only. A deposit's balance is a term-deposit concept
* and lives on `depositDetail` below, which is why the bank keeps the two
* apart rather than answering both from one endpoint.
*/
balance: '/accounts/balance',
/**
* A page of ledger entries for one account. Takes the full account number
* from `list` above, and an optional `fromDate`/`toDate` pair that the
* bank rejects unless both are given or neither is.
*/
statement: '/accounts/statement',
/**
* The same range `statement` pages through, as one PDF. Takes the identical
* `accountNumber` and optional `fromDate`/`toDate` pair and no
* `page`/`size` — the whole range becomes one document. Answers
* `application/pdf`, not the JSON envelope every other endpoint returns.
*/
statementExport: '/accounts/statement/export',
/**
* The last 10 entries as a short PDF, led by the current available balance.
* `accountNumber` only — no date range, and no envelope.
*/
miniStatement: '/accounts/mini-statement',
/**
* One deposit's terms, by `accountNumber` query parameter. Takes the full
* number from `list` above — the masked form every other endpoint returns
* will not resolve.
*/
depositDetail: '/accounts/deposits/detail',
},
beneficiaries: {
list: '/beneficiaries',
save: '/beneficiaries',
validate: '/beneficiaries/validate',
},
/**
* IMPS transfers, in two steps. `initiate` runs the name inquiry and sends an
* OTP but moves no money; `verifyOtp` consumes the OTP and sends ReqPay. The
* server never sends ReqPay before a verified OTP, and never retries it.
*/
fundTransfers: {
initiate: '/fund-transfers/initiate',
verifyOtp: (transferId: string) => `/fund-transfers/${transferId}/verify-otp`,
},
dashboard: {
summary: '/dashboard/summary',
},
transfer: {
beneficiaries: '/transfers/beneficiaries',
submit: '/transfers',
},
payments: {
upi: '/payments/upi',
},
deposits: {
products: '/deposits/products',
fixed: {
list: '/fd/list',
create: '/fd/create',
detail: (id: string) => `/fd/${id}`,
close: '/fd/close',
},
recurring: {
list: '/rd/list',
create: '/rd/create',
detail: (id: string) => `/rd/${id}`,
close: '/rd/close',
},
},
services: {
requests: '/services/requests',
chat: '/services/chat',
},
/**
* Declares a cheque before it is presented. Write-only: the bank is the
* system of record and keeps no client-side copy, so there is nothing to
* list or fetch back — `referenceId` in the response is the only handle.
*/
positivePay: {
register: '/positive-pay',
/**
* Checks the bank does *not* already hold this cheque, before the customer
* fills in the full registration form. "Not found" is the happy path here
* and answers 200 with a null `data`; a cheque already on file is refused
* with `CHEQUE_ALREADY_REGISTERED`.
*/
verify: '/positive-pay/verify',
},
/**
* Stopping a cheque already declared under Positive Pay.
*
* `verify` resolves to the same core-banking lookup as
* `positivePay.verify` — what differs is which answer is good news. There,
* finding the cheque is a rejection; here it is the whole point, and the
* cheque's own detail comes back so the customer can confirm what they are
* about to stop. A cheque that never went through `positivePay.register`
* does not exist to either of these.
*/
cheque: {
verify: '/check/verify',
stopPayment: '/check/stop-payment',
},
/**
* Cheque book issuance — the one cheque journey the bank keeps a history
* for, unlike Positive Pay and stop payment above.
*
* `charges` quotes the fee before the customer commits to `issue`, the same
* preview-then-act convention as `positivePay.verify`. `issue` is
* synchronous: the serial range comes back in its own response, so there is
* no pending state and nothing to poll. `issue` and `list` are the same
* path under different methods, named apart because the screens reach for
* one or the other and a shared constant reads like a copy-paste slip.
*/
chequeBook: {
charges: '/cheque-book/charges',
issue: '/cheque-book',
list: '/cheque-book',
},
loans: {
products: '/loans/products',
active: '/loans/active',
detail: (id: string) => `/loans/${id}`,
apply: '/loans/apply',
eligibility: '/loans/eligibility',
emiSchedule: (id: string) => `/loans/${id}/emi-schedule`,
payEmi: '/loans/pay-emi',
foreclosureQuote: (id: string) => `/loans/${id}/foreclosure`,
prepay: (id: string) => `/loans/${id}/prepay`,
applications: '/loans/applications',
documents: '/loans/documents',
uploadDocument: '/loans/documents/upload',
history: '/loans/history',
notifications: '/loans/notifications',
},
insurance: {
dashboard: '/insurance/dashboard',
plans: '/insurance/plans',
comparePlans: '/insurance/plans/compare',
calculator: '/insurance/calculator',
policies: '/insurance/policies',
policyDetail: (id: string) => `/insurance/policies/${id}`,
purchase: '/insurance/policies/purchase',
premiumDues: '/insurance/premiums/due',
payPremium: '/insurance/premiums/pay',
autoRenew: (policyId: string) => `/insurance/policies/${policyId}/auto-renew`,
claims: '/insurance/claims',
submitClaim: '/insurance/claims/submit',
documents: '/insurance/documents',
uploadDocument: '/insurance/documents/upload',
notifications: '/insurance/notifications',
markNotificationRead: (notificationId: string) =>
`/insurance/notifications/${notificationId}/read`,
otp: '/insurance/otp',
},
cards: {
overview: '/cards',
detail: '/cards/detail',
controls: '/cards/controls',
limits: '/cards/limits',
status: '/cards/status',
notifications: '/cards/notifications',
virtualCard: '/cards/virtual-card',
statements: '/cards/statements',
rewards: '/cards/rewards',
settings: '/cards/settings',
},
profile: {
me: '/profile/me',
},
branches: {
list: '/branches',
detail: (id: string) => `/branches/${id}`,
},
agent: {
dashboard: '/agent/dashboard',
customers: '/agent/customers',
customerDetail: (id: string) => `/agent/customers/${id}`,
collections: '/agent/collections',
collectionHistory: '/agent/collections/history',
commission: '/agent/commission',
loans: '/agent/loans',
sms: '/agent/sms',
routes: '/agent/routes',
},
};