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', }, };