# What each endpoint does

Back to the [README](../README.md). The simulator's choices where the spec is silent are in [behaviour/](behaviour/README.md).

**Only 14 of these endpoints are active:** 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.8, 4.9, 4.12, 4.13, 4.14, 4.16, 4.20 and 4.30. A simulator started the normal way answers the other 26 with HTTP 404 `{"error": "endpoint_not_enabled", ...}` and does not use up the `txnRefNo`. Their code and tests are still here and are described below, so one can be switched back on: see the [Endpoints section of the README](../README.md#endpoints).

**4.1 Purchase Card** creates a card. Send `customerInfo` and
`loadDetails` (`productCode`, `billingAmount`, ...). You get back `proxyNumber`,
`cardNumber`, `cardExpiry` and, for an inactive card, a 6-digit
`activationCode`. The card's opening balance is `billingAmount`. To register
one of the pre-printed instant cards instead, also send its `proxyNumber` (see
Seed data).

**4.2 Update Customer Details** changes the contact details given at
purchase. Send `customerInfo` with `mobileNumber` and `emailAddress`, plus
`address` and/or `mailAddress` to replace those. The name can't be changed.
Look the card up by `proxyNumber`, or by `customerId` to update all of that
customer's cards. Get Card Details shows the new mobile number and email.

**4.3 Get Card Details** returns `cardStatus`, `expiryDate`,
`maskedCardNumber`, `cvv`, and the `nameOnCard`, `mobileNumber` and `emailId`
given at purchase. Look the card up by `proxyNumber`, or by `customerId` to
get all of that customer's cards. With several cards, each field is a
comma-separated list in the same order, e.g. `"cardStatus": "I,M"`.

**4.4 Block/Unblock** changes the status. Send `flag` (`L`, `UL`, `BL`, `BS`
or `BD`) and a `reason`. Only the moves in the diagram are allowed:

| Problem | Code |
|---|---|
| The card already has that status | `MATCRD` |
| The card is permanently blocked | `CRDBLP` |
| Blocking a locked card (unlock it first) | `CRDLKD` |
| The card isn't active yet (`M`) | `NOTACT` |

**4.5 Card Activation** moves an `M` card to `I`. `activationCode` is
optional. If you send it, it must be the one Purchase Card returned (`IACTNO`
otherwise). An active card returns `CRDACT`, a locked one `CRDLKD`, and a
blocked one `CRDBLO`.

**4.6 Card Replacement** issues a new card in place of an old one. Send
`type` `PP` (physical to physical) for a card that has been hot-listed with
Block/Unblock flag `BL`, `BS` or `BD` (`NTBLCD` otherwise), or `VP` (virtual
to physical) for an active or inactive card. You get back `newProxyNumber`,
a masked `newCardNumber` and `expiryDate`. The new card takes over the old
card's balance, added accounts and customer details, and starts inactive
(`M`), so activate it with 4.5 (no `activationCode` needed). The old card
keeps its status with a zero balance. Replacing it again returns `ORDEXT`.

**4.7 Account Addition** adds another product's account to a card. Send
`productInfo.details` with `productCode`, `loadAmount`, `billingAmount`,
`loadCurrency` and `billingCurrency` (one object, or a list for several
products). The new account's balance is `billingAmount`. A product the card
already has returns `ACTEXT`. A locked card returns `CRDLKD`, a blocked one `CRDBLO`.

**4.8 Load Card** adds `productInfo.billingAmount` to the balance of the
card's account for `productCode` and returns the new `cardBalance` with
`feeAmount` `"0.00"`. Active (`I`) and inactive (`M`) cards can be loaded.
`productCode` must be the card's product or one added with 4.7 (`INPDID`
otherwise) and `billingCurrency` that account's currency (`INVCCY`
otherwise). A locked card returns `CRDLKD`, a blocked one `CRDBLO`.

**4.9 Query Balance** returns the card's `productCode`, `balanceAmount` and
`accountCcy` in `productInfo.details`. For a card with accounts added by 4.7,
`details` is a list with one entry per open account, the card's own product
first. It doesn't check the card's status, except that a closed card returns
`CRDCLD`.

**4.10 Amount Refund** takes `amount` out of the card's account for
`productCode` and returns the remaining `balanceAmount` with `feeAmount`
`"0.00"`. Send `requestType` `REFUND`, and `amount` `"**"` to refund the
whole balance. More than the balance returns `EXEAMT`. Like Load Card,
active and inactive cards can be refunded; a locked card returns `CRDLKD`, a
blocked one `CRDBLO`.

**4.11 Account Closure** closes the card's account for `productCode`. The
account's balance must be zero (`BALNT0` otherwise), so refund it first with
4.10. When the card's last open account is closed, the card is closed too
(status `C`). A closed account returns `ACCCLD` to Load Card, Refund and a
second closure, and is left out of Query Balance.

**4.12 Get X Transactions** returns the card's transactions between
`fromDate` and `toDate` (`DDMMYYYY`), newest first, at most `count` (1–99) of
them, plus the card's `activateDate`. `count` `"**"` returns up to 99
whatever the dates. The money-moving endpoints record transactions with
codes from appendix 7.4:

| Endpoint | `transactionCode` | `description` | `drCrIndicator` |
|---|---|---|---|
| 4.1 Purchase Card (opening balance) | `100261` | Online Card Issuance | `C` |
| 4.7 Account Addition (each new account's opening balance) | `100045` | New Card Account | `C` |
| 4.8 Load Card | `100054` | Topup | `C` |
| 4.10 Amount Refund | `100052` | Refund | `D` |
| 4.13 Debit/Credit, `type` `BAT` | `302551` / `302552` | Balance Adjustment Debit / Credit | `flag` |
| 4.13 Debit/Credit, `type` `FEE` | `101100` | Charge Fees | `flag` |
| 4.14 Fund Transfer, source card | `100119` | Fund Transfer Debit Transaction | `D` |
| 4.14 Fund Transfer, destination card | `100120` | Fund Transfer Credit Transaction | `C` |

`transactionRefNumber` is the `txnRefNo` of the request that made the
transaction. No matching transactions returns `17`.

**4.13 Debit/Credit the Account** debits (`flag` `D`) or credits (`C`)
`amount` to the card's account for `productCode` and returns the new
`cardBalance`. `type` is `BAT` (balance adjustment) or `FEE`. An `amount` in
another `currency` than the account's is converted (see [Exchange rates](exchange-rates.md)), and `NOEXRT` means there's no rate. A debit larger than the
balance returns `LSSBAL`. Non-blank `remarks` replace the transaction's
description in 4.12. Like Load Card, a locked card returns `CRDLKD`, a
blocked one `CRDBLO`.

**4.14 Fund Transfer** moves `destAccount.amount` from the `sourceAccount`
card's account to the `destAccount` card's account, each picked by
`proxyNumber`, `productCode` and `accountCcy`. Both cards must be active
(`SRCACC` / `DESACC` otherwise) and belong to different holders (`NOTSAM`).
An unknown card or product returns `INVFPD` / `INVTPD`, an `accountCcy` that
isn't the account's `INVFCY` / `INVTCY`, and more than the source balance
`LSSBAL`. Both cards change together or not at all. `amount` is in the
destination currency; across currencies the source pays its converted cost
(see [Exchange rates](exchange-rates.md)), and `NOEXRT` means there's no rate.

**4.15 Exchange Rate** saves `exRate` and `bankRate` for a `buyCurrency` /
`sellCurrency` pair, replacing any earlier rate for that pair. A malformed
currency returns `BUYNOT` / `SELNOT`, a bad rate `INVEXR`. The response is just
`txnRefNo` and the response code. Debit/Credit and Fund Transfer convert
with the saved rates.

**4.16 Card Order** places an order for `order.quantity` non-personalized
cards of `order.productCode` in `order.cardDesign`, and returns its
`invoiceNo` and `orderRefNo`. The design must be one the product has in the
`:card_designs` config (`INVPLA` otherwise). `branchId` and a `delivery`
address are optional. No cards are created until the order is receipted.

**4.17 Card Receipt** receipts delivered cards of an order: `receipt.quantity`
packs from `fromPackNo` to `toPackNo`. A pack number is the card's proxy
number, so the receipted cards join the instant-card inventory and Purchase
Card can register them by `proxyNumber`. That makes a full stock flow: order
with 4.16, receipt with 4.17, sell with 4.1. An unknown `orderRefNo` returns
`17`, and receipting more than the order has left returns `INVQTY`.

**4.18 Update Stock Details** reports `quantity` cards of an order damaged,
listed by pack number in `refNumbers.packNo`. A receipted pack leaves the
inventory, so Purchase Card can't sell it. A pack that was never receipted
counts as delivered damaged: it uses up the order and can't be receipted
later. A pack that's anything else (sold, another order's or seed
inventory, or already damaged) returns `DATERR`.

**4.19 Get Stock Details** counts a branch's stock from its card orders, one
`stockInfo` entry per configured product: `cardOrdered`, `cardActivated`
(cards sold from the orders' packs and activated), `cardWithBranch`
(receipted and not yet activated, sold or not) and `cardDamaged`. Orders
placed without a `branchId` are under the API user's branch, `APIUSER` by
default.

**4.20 Status Request** reports what happened to an earlier request: send
its `txnRefNo`, and the response has that request's `responseCode` and
`responseText` (`00`, or the error it got). A reference no request has used
returns `TXNNRV` ("Transaction not received"). Asking doesn't use the
reference up, so a request can still be sent with it afterwards.

**4.21 Change Password** changes the password of the API user in the
`netid` header. Passwords are sent hashed: SHA-256, then Base64. The default
user `APIUSER` starts with `Password@1`, whose hash is
`printf 'Password@1' | openssl dgst -sha256 -binary | base64`. A wrong
`oldPassword` returns `CRPDWG`, a `newPassword` among the last 13 `PSTHIS`,
and an unknown `netid` `INVUSR`.

**4.22 Access Rights** returns the `userName`, `lastLogin` and `menuList` of
a card holder's web profile, looked up by `userId`. Profiles are seeded from
config (see [seed data and config](seed-data-and-config.md)), since the REST API can't create them; the default
is the sample's `CUSTOMER1`. An unknown `userId` returns `INVUSR`.

**4.23 PIN Retrieval** returns the card's ATM PIN as an `epinBlock` (see
[PINs](pins.md)). The card holder proves they have the card with `expiryDate`
(MMYY, as printed: `0729` for the seed card), `cvv2` (the `cvv` from Get
Card Details) and `dob` (DDMMYYYY, as given in Purchase Card's
`customerInfo.dob`). Any mismatch returns `103`.

**4.24 ATM PIN Verification** checks that `epinBlock` holds the card's ATM
PIN and `dob` is the card holder's. A wrong PIN returns `104`, and a wrong
`dob` `103`. The block 4.23 returns verifies as-is.

**4.25 ATM PIN Change** replaces the card's ATM PIN: the old PIN's block
(`eoldPinBlock`) must hold the current PIN, and the new one
(`enewPinBlock`) sets it. Either being wrong returns `104`. PIN Retrieval
and Verification use the new PIN from then on.

**4.26 Assign Override Settings** assigns (`flag` `Y`) or removes (`N`) a
campaign code on the card's account for `productCode`. Campaigns are
seeded from config (the sample's `CHGNEW`, for `MCCAED`), each for one
product and valid between two dates. An unknown campaign returns `CCDNOT`,
one for another product `INVCMP`, and one not started yet `INCPDT`.

**4.27 Alert Settings** sets (`alertSet` `Y`) or unsets (`N`) an SMS/email
alert on the card's account for `productCode`: `alertType` `ATMCWD`,
`PURCSE`, `LOWBAL` or `TOPACC`, with `frequency` `TXN`, or `DLY` / `WLY` for
`LOWBAL`, and `channel` `SMS`, `EMAIL` or `BOTH`. A `LOWBAL` alert needs its
threshold in `alertData` (`IVALDA` otherwise).

A full round trip: purchase a card, activate it with the returned
`activationCode`, check it with Get Card Details (`cardStatus: "I"`) and Query
Balance, then lock it with flag `L`. `bash demo.sh` runs most of this against a
running simulator and prints each response.

**4.28 Get Card Number** returns the card's full 16-digit `cardNumber` with
its `expiryDate` and `nameOnCard`, looked up by `proxyNumber`. It's the only
endpoint that returns the number unmasked; Get Card Details masks it.

**4.29 Get CSC Enquiry** returns the card's 4-digit `csc`, looked up by
`proxyNumber`. `expiryDate` (`YYMM`) must match the card's expiry.

**4.30 Card Order Status** returns the 4.16 order with the given `invoiceNo`
(or `orderRefNo`) under `cardOrderInfo.details`, with its `orderStatus`.

**4.31 IVR PIN Set** sets the card's IVR PIN, after checking `dob` as 4.23
does. A second set replaces the first.

**4.32 IVR PIN Change** replaces the card's IVR PIN with `newIvrPin` if
`oldIvrPin` is the current one. A wrong old PIN returns `104`.

**4.34 IVR PIN Validation** checks that `ivrPin` is the card's current IVR
PIN. A wrong one returns `104`. Nothing changes.

**4.35 Reset Web Password** sets the web password of the web profile named
by the `netid` header (see 4.22 for profiles). Both passwords are sent
hashed, and `confirmPassword` must match `newPassword`.

**4.36 Retrieve Web Profile** returns the `userId` of the web profile that
covers the card, with the holder's `emailId` and `mobileNumber` from the
Purchase Card `customerInfo`.

**4.37 ATM PIN Set** sets the card's ATM PIN from `epinBlock`, with no old
PIN needed. `expiryDate`, `cvv2` and `dob` are optional; each one sent must
match the card (`103`). PIN Retrieval and Verification use the new PIN from
then on.

**4.38 New OTP Request** issues a 6-digit OTP for the card, checking
`expiryDate` (MMYY). There is no SMS, so read the OTP from
`GET /_sim/otps`.

**4.39 OTP Validation** checks `otp` against the one 4.38 issued under the
same `txnRefNo`, and uses it up on success.

**4.41 Set Limit Details** sets the card holder's limits: an amount
(`spend…`) and a count (`txn…`) for each of POS, ATM, Ecom and Contactless and
each of Life, Year, Month, Week and Daily, e.g. `spendPOSMonth`. Blank or
missing fields are left as they were.

**4.42 Get Limit Details** returns the limits 4.41 set, with every field
present and `null` where there is none, plus `avail…` (left to spend) and
`prd…` (product-level) fields for each.
