# Lookups, IVR PIN, web profile, OTP and limits: 4.28-4.42

Behaviour the specs don't define (simulator choices). Back to the [index](README.md).

Get Card Number (4.28):
- `proxyNumber` takes a 12-digit proxy number or a 16-digit card number and
  is echoed back as sent, like 4.3.
- `expiryDate` uses the sample's format (`31-JUL-29`), not the `DDMMYYYY`
  the table gives, whose wording is copied from an ID proof's expiry date.
- `nameOnCard` is optional and left out when the card has none (the seed
  card has none).
- `reftext1`-`3` are future use and ignored; the sample spells them
  `refText1`-`3`.
- Any card status qualifies, including locked, hot-listed and closed, as
  with Get Card Details. An unknown or missing card → `INVCRD`.

Get CSC Enquiry (4.29):
- The spec limits it to American Express virtual cards. The simulator's
  cards have no scheme, so every card qualifies.
- The `csc` is derived from the card number, so it's the same on every call.
- `expiryDate` is checked against the card's expiry in `YYMM` (`2907` for
  `31-JUL-29`). A wrong or missing one → `DATERR`.
- `proxyNumber` takes a 12-digit proxy or 16-digit card number and is echoed
  back as sent. Any card status qualifies. An unknown card → `INVCRD`.

Card Order Status (4.30):
- `invoiceNo` matches the order's invoice number or its order reference
  number, as the spec allows. Invoice numbers here are 16 digits, not the
  spec's 13. It's echoed back as sent.
- `invoiceDate` uses the sample's format (`05-JUL-24`), not the table's
  `DDMMYYYY`.
- `orderedBy` is the order's branch, or the `:api_user_branch` config;
  `plasticName` is the card design and `cardOrdered` the order quantity.
- The spec doesn't list `orderStatus` codes. The simulator returns `IA` (the
  sample's) while cards are still to be delivered and `DL` once the received
  and damaged-on-arrival cards add up to the quantity.
- An unknown invoice → `17` (No records found); a missing `invoiceNo` → `11`.

IVR PIN Set (4.31):
- The spec says `ivrPin` is a SHA-256 hash in base64 and 6 characters, but
  its sample sends `0629`. Any non-blank string is accepted and stored as
  sent; a blank or missing one → `11`.
- `dob` (8 digits, else `11`) is checked as in PIN Retrieval: a card with
  none recorded accepts any; a wrong one → `103`.
- Set stores the PIN, replacing any earlier one. A card with none set has
  a default of 4 digits derived from the card number (`Pins.ivr_pin/1`), as
  the spec says it's generated with the card; 4.32 and 4.34 read it.
- The same card statuses qualify as for PIN Retrieval. An unknown card →
  `INVCRD`.

IVR PIN Change (4.32):
- PINs are compared as sent, hashed or not. A card with no IVR PIN set by
  4.31 has the derived default (see IVR PIN Set).
- The spec has no code for a wrong old PIN, so it gets `104` ("Invalid
  EPinBlock"), as a wrong ATM PIN does. A blank or missing old or new PIN
  → `11`.
- The sample sends a `dob` the table doesn't list. It's optional: when sent
  it must be 8 digits (else `11`) and the card holder's (else `103`), as in
  PIN Retrieval.
- The same card statuses qualify as for PIN Retrieval. The new PIN may
  equal the old one.

IVR PIN Validation (4.34):
- PINs are compared as sent, against the PIN set by 4.31 or 4.32, else the
  derived default (see IVR PIN Set). A wrong PIN → `104`, as in 4.32; a
  blank or missing one → `11`.
- `dob` is optional, as the table says. When sent it must be 8 digits (else
  `11`) and the card holder's (else `103`).
- The same card statuses qualify as for PIN Retrieval, and there are no
  retry limits.

Reset Web Password (4.35):
- The request names no user, so the web profile is the one whose `userId`
  equals the `netid` header (`CUSTOMER1` in the default config). No such
  profile → `INVUSR`. This is separate from Change Password's API user,
  which is also looked up by `netid`.
- Nothing checks the web password afterwards (there is no web login), so it
  is only stored, as sent, in the profile's `password_hash`.
- As in Change Password, passwords are compared and stored as hashes, and
  the 8–16 character rule can't be checked. A blank or missing password →
  `11`; the spec has no code for a `confirmPassword` mismatch, so that is
  `11` too.
- There's no password history rule, as the spec gives none for this call.
  Profiles go back to the config on a restart or `/_sim/reset`.

Retrieve Web Profile (4.36):
- The REST spec has no link between a card and a web profile, so each
  profile in `:web_profiles` lists the cards it covers in `proxy_numbers`
  (the default `CUSTOMER1` covers the seed card). A known card no profile
  covers → `INVUSR`; an unknown card → `INVCRD`. Purchase Card doesn't
  create a profile.
- `emailId` and `mobileNumber` come from `customerInfo.emailAddress` and
  `mobileNumber`, as in Get Card Details, and are left out when the card has
  none (the seed card has none, so the default response is just `userId`).
- The response has no `proxyNumber`, as the table says; errors echo it.
- Any card status qualifies, as in 4.3. `reftext1`-`3` are ignored.

ATM PIN Set (4.37):
- `expiryDate` (MMYY), `cvv2` and `dob` are optional, as the table says.
  Each one sent is checked as in PIN Retrieval: malformed → `11`, wrong →
  `103`. With none sent, the PIN is set on the card number alone.
- An `epinBlock` that is missing, or isn't a valid format-0 block for the
  card → `104`, as in 4.25.
- The same card statuses qualify as for PIN Retrieval. The new PIN may equal
  the old one.

New OTP Request (4.38):
- The simulator sends no SMS, so the OTP is returned by `GET /_sim/otps`
  instead. It is random, 6 digits, and has no expiry yet.
- It's saved under the request's `txnRefNo`, because the 4.39 request has no
  `proxyNumber` (see OTP Validation). A new OTP for a card replaces its earlier one.
- `expiryDate` is MMYY and required: malformed or missing → `11`, wrong →
  `103`. The response has no `proxyNumber`, as the table says; errors echo it.
- Active (`I`) and inactive (`M`) cards qualify, as in PIN Retrieval. An
  unknown card → `INVCRD`.

OTP Validation (4.39):
- The request has only `txnRefNo` and `otp`, and the spec's sample reuses
  4.38's `txnRefNo`, so that is how the OTP is found. The `txnRefNo` isn't
  claimed (like Status Request), so it doesn't return `TIDEXT`.
- A correct OTP succeeds once and is then used up; validating it again →
  `TXNNRV`, as does a `txnRefNo` no OTP was issued under.
- The spec has no code for a wrong OTP, so it gets `11`, as does an `otp`
  that isn't 6 digits. A wrong OTP leaves the real one valid. There are no
  retry limits and OTPs don't expire.
- No card is involved, so card status isn't checked.

Set Limit Details (4.41):
- The appendix lists no apikey for 4.41 or 4.42, so the simulator uses
  `ASTLMT` for 4.41 (and `AGTLMT` for 4.42).
- The sample sends all 40 limit fields with `""` for those not being set. A
  blank, `null` or missing field is left unchanged, so a call only changes
  what it names; a limit can't be cleared, only changed.
- Values are digits only, at most 10 (15 for `spendPOSLife`, as the table
  says), else `11`, and then nothing is changed. No relation between periods
  is enforced (a daily limit may exceed the monthly one), and the limits
  aren't applied to any transaction.
- Any card status but closed (`CRDCLD`) qualifies. An unknown card →
  `INVCRD`. Limits are kept with the card, so a restart or `/_sim/reset`
  clears them.

Get Limit Details (4.42):
- Like the sample, the response has all of the table's fields, `null` where
  unset: 40 card limits (`spendPOSLife` …), 40 `avail…` and 40 `prd…`.
- `avail…` equals the card limit, since the simulator doesn't count
  transactions by channel, so nothing is ever spent against a limit.
- `prd…` is always `null`: the simulator has no product-level limits (the
  appendix's `LMTNOT` isn't used).
- `proxyNumber` is echoed as sent (12 or 16 digits). Any card status
  qualifies, as in 4.3. An unknown card → `INVCRD`.
- The spec's own sample is inconsistent (its `txnPOS…` fields are cut off
  and its `spendPOSYear` is `null` while `availSpendPOSYear` is `"40"`); the
  table is followed.
