m2pfintech

Update Card Status (Lock / Unlock / Block)

Changes the status of a prepaid card. This is the primary API for card lifecycle management.

Supported Operations

Target StatusActionReversible?Use Case
LOCKEDTemporarily freeze card✅ Yes (unlock)Suspected fraud, temporary travel hold
UNLOCKEDRestore from locked stateN/ACustomer confirmation that card is safe
BLOCKEDPermanently disable card❌ NoLost/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

ScenarioSend reasonCode?Why
LOCKED✅ RecommendedNeeded for fraud/risk investigation and support traceability
BLOCKED✅ Strongly recommendedPermanent impact operation; reason should always be auditable
UNLOCKED⚠️ OptionalUseful 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.
POST
/v1/cards/update/status

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

Card identification and target status

mobile*

Cardholder's registered mobile number

status*string

Target card status

Value in"LOCKED" | "UNLOCKED" | "BLOCKED"
entityId?string

Unique entity identifier for the cardholder

kit?string

Card kit number

reasonCode?string

Reason code for status-change audit classification.

Usage guidance:

  • Recommended for LOCKED
  • Strongly recommended for BLOCKED
  • Optional for UNLOCKED

Keep this field short and machine-readable; use reasonMsg for narrative details.

Suggested codes:

  • 01 / CUST_REQ — Customer request
  • 02 / FRAUD_SUSPECTED — Suspected fraud
  • 03 / LOST_CARD — Lost card
  • 04 / STOLEN_CARD — Stolen card

Reserved/terminal semantic:

  • Card Closure should be used only when the business intent is final closure.
  • Do not use Card Closure for replaceable scenarios (lost/stolen/damaged), as replacement eligibility may be restricted.

Note: status determines the operation; reasonCode does not drive status transitions.

reasonMsg?string

Human-readable reason for the status change (for audit trail)

requestLetterPPF?object
rule?

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

skipDocumentNeedsCheck?boolean
updatedBy?string
userOverridden?

Domestic and international preference categories

Response Body

application/json

application/json

application/json

curl -X POST "https://sandbox-api.m2pprepaid.com/prepaid/customer/v1/cards/update/status" \  -H "X-TENANT-ID: ACME_CORP" \  -H "Content-Type: application/json" \  -d '{    "mobile": {      "value": "9609388730",      "countryCode": 91    },    "status": "LOCKED",    "entityId": "476843769320000001160925",    "kit": "320000001",    "reasonCode": "01",    "reasonMsg": "Customer requested card lock due to security concerns"  }'

{
  "result": {
    "message": "Card was LOCKED 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": "Customer does not exists for id :9609388731",
  "status": 409,
  "detail": "Customer does not exists for id :9609388731",
  "message": "error.business",
  "businessCode": "PPCUST_002"
}

Update Card Transaction Preferences POST

Configures transaction preferences for a prepaid card. Allows enabling/disabling specific transaction channels and setting daily limits for both **domestic** and **international** usage. ### Preference Types Each of the following can be independently configured: - `ATM` — Cash withdrawal from ATMs - `E-com` — Online/e-commerce purchases - `POS` — Point-of-sale merchant purchases - `ContactLess` — NFC tap-and-pay transactions - `Cash-PoS` — Cash withdrawal at POS terminals - `Tokenization` — Digital wallet tokens (Apple Pay, Google Pay, Samsung Pay) - `Recurring Transactions` — Standing instructions, subscriptions, auto-debits ### Limit Configuration For each preference type, you can set: - `enabled` — Toggle on/off - `maxTransaction` — Maximum number of transactions per day - `maxTransactionAmountPerDay` — Maximum total amount per day - `perTransactionLimit` — Maximum amount per single transaction - `upperLimitMaxTransaction` / `upperLimitMaxTransactionAmountPerDay` — Product-level upper bounds (read-only reference) ### Important Notes - Card must be in **ACTIVE** status to update preferences - Only send the preferences you want to change — others remain unchanged - `upperLimit*` fields are read-only max bounds set at product level - Setting a value higher than the upper limit will be rejected

Update Card PIN (Change Existing PIN) POST

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`