m2pfintech

Update Card PIN (Change Existing PIN)

Changes the card PIN from an existing PIN to a new PIN. Requires the current PIN and OTP verification.

Difference from Set PIN

  • Set PIN (v2): For first-time PIN setup or reset. Uses RSA-encrypted PIN.
  • Update PIN: For changing an existing PIN. Uses plain-text PIN (4 digits).

PIN Lock Protection

After 3 consecutive failed OTP attempts, the PIN change operation is locked for 10 minutes. This prevents brute-force attacks.

Flow

  1. Generate OTP → receive traceNumber
  2. Call this API with oldPin, newPin, OTP, and traceNumber
POST
/v1/cards/update/pin

Authorization

bearerAuth tenantId
AuthorizationBearer <token>

JWT Bearer token from the Authentication API

In: header

X-TENANT-ID<token>

Your unique tenant identifier assigned during onboarding

In: header

Header Parameters

X-TENANT-ID*string

Your unique tenant identifier

Request Body

application/json

Current PIN, new PIN, and OTP verification

mobile*

Phone number with country code

kit*string

Card kit number

entityId*string

Entity identifier

expiryDate?string

Card expiry date in MM/YY format

otp?string

One-time password received via SMS

newPin*string

RSA-encrypted new PIN. Use the public key provided during onboarding to encrypt the 4-digit PIN. The encrypted value will be a long base64-encoded string.

otpDetails?

OTP verification details — obtain traceNumber from Generate OTP API

rule?

Security validation rules for card operations. The required fields depend on the product configuration. Common fields used for validation:

oldPin?string

Response Body

application/json

application/json

application/json

curl -X POST "https://sandbox-api.m2pprepaid.com/prepaid/customer/v1/cards/update/pin" \  -H "X-TENANT-ID: ACME_CORP" \  -H "Content-Type: application/json" \  -d '{    "mobile": {      "value": "9600389470",      "countryCode": 91    },    "entityId": "621643170420004195030925",    "kit": "20004195",    "expiryDate": "10/27",    "otp": "123456",    "oldPin": "1212",    "newPin": "4545",    "otpDetails": {      "traceNumber": "09176cdf-b704-4ab1-94bd-b1b8fd5ac2d1",      "mobileNumber": "9600389470",      "otp": "123456"    },    "rule": {      "expiryDate": "10/27",      "otp": "123456",      "traceNumber": "09176cdf-b704-4ab1-94bd-b1b8fd5ac2d1"    }  }'
{
  "result": {
    "message": "Card pin change Successfully"
  },
  "pagination": null
}

{
  "type": "https://www.m2pfintech.com/problem/constraint-violation",
  "title": "Method argument not valid",
  "status": 400,
  "message": "error.validation",
  "fieldErrors": [
    {
      "field": "mobile",
      "message": "Invalid contact",
      "objectName": "changeCardPin"
    }
  ]
}

{
  "type": "https://www.m2pfintech.com/problem/problem-with-message",
  "title": "Change/Pin is Locked for 10 minutes, due to invalid OTPs being entered in attempts 3",
  "status": 409,
  "detail": "Change/Pin is Locked for 10 minutes, due to invalid OTPs being entered in attempts 3",
  "message": "error.business",
  "businessCode": "PPCUST_042"
}

Update Card Status (Lock / Unlock / Block) POST

Changes the status of a prepaid card. This is the primary API for card lifecycle management. ### Supported Operations | Target Status | Action | Reversible? | Use Case | |--------------|--------|-------------|----------| | `LOCKED` | Temporarily freeze card | ✅ Yes (unlock) | Suspected fraud, temporary travel hold | | `UNLOCKED` | Restore from locked state | N/A | Customer confirmation that card is safe | | `BLOCKED` | Permanently disable card | ❌ No | Lost/stolen card, confirmed fraud | ### Important Rules - A card must be **ACTIVE** to be locked or blocked - A card must be **LOCKED** to be unlocked - **BLOCKED** cards cannot be recovered — a card replacement must be initiated - If the card is already in the requested status, the API returns a success message like `"Card was already LOCKED"` without error ### Reason Codes Partners should provide meaningful `reasonCode` and `reasonMsg` for audit trail purposes. Common reason codes: `01` (Customer request), `02` (Suspected fraud), `03` (Lost), `04` (Stolen) ### reasonCode: When to Use vs Not Use | Scenario | Send `reasonCode`? | Why | |---------|---------------------|-----| | `LOCKED` | ✅ Recommended | Needed for fraud/risk investigation and support traceability | | `BLOCKED` | ✅ Strongly recommended | Permanent impact operation; reason should always be auditable | | `UNLOCKED` | ⚠️ Optional | Useful when unlock is policy-driven or investigation outcome based | #### Correct Usage - Keep `reasonCode` short and stable (machine-readable), e.g. `CUST_REQ`, `FRAUD_SUSPECTED`, `LOST_CARD`, `STOLEN_CARD`. - Put human-readable context in `reasonMsg`. - Reuse a controlled reason catalog across channels and environments. #### Avoid - Do not use `reasonCode` to imply operation type (operation is controlled by `status`). - Do not send paragraph text in `reasonCode`. - Do not rely on `reasonCode` for status transition logic. #### Special Restriction: `Card Closure` - Treat `Card Closure` as a terminal closure intent, not as a regular block reason. - If `Card Closure` is used explicitly as `reasonCode`, the card may be treated as closure/terminal in downstream business handling. - In such cases, card replacement eligibility can be impacted (replacement may be blocked by policy). - For replaceable scenarios (lost/stolen/damaged), use non-closure reason codes such as `LOST_CARD`, `STOLEN_CARD`, `DAMAGED_CARD`.

Validate Card PIN POST

Verifies whether the provided PIN is correct for the given card. This is a read-only check — it does not modify the PIN. ### When to Use - Pre-validate PIN before a sensitive operation (e.g., viewing card details) - Implement "confirm PIN" flows in your mobile/web app - PIN-based authentication for in-app transactions ### Important Notes - Returns `{ valid: true/false }` — never reveals the actual PIN - Uses the same `ChangeCardPinDto` as Set/Update PIN but only reads `oldPin` - No OTP required for validation