m2pfintech
API LibraryCard Tokenization

Generate Shared Secret (Per-Session)

Generate an ECDH shared secret and receive a one-time tokenization URL for this session. Called from your backend server once per card-entry session before rendering the card input UI.

What this does:

  1. Accepts your ephemeral ECDH public key
  2. Performs ECDH key agreement server-side to derive a shared secret
  3. Returns the M2P server public key, shared secret, and a signed one-time URL to be used in Step 3 (createCardToken)

Security model:

  • The sharedSecret returned here is used by the frontend to derive the AES encryption key for card data. It must be passed to the browser/app securely (e.g., embedded in page state, not logged).
  • The url in the response is a signed, single-use endpoint for card tokenization. It encodes session context via the key query parameter and expires after a short TTL.

Note: This endpoint is on the Auth/Tokenization Service. The exact base URL is provided during onboarding. Use the token header with the API token provisioned for your integration.

POST
/bitUrl/v2/generateSharedSecret

Authorization

BasicAuth
AuthorizationBasic <token>

Partner credentials (username/password) provisioned during onboarding

In: header

Header Parameters

token*string

API token provisioned for your partner integration (provided during onboarding)

TENANT*string

Tenant identifier (sponsor bank)

Request Body

application/json

publicKey*string

Client's ephemeral ECDH public key (hex, P-256 uncompressed format). Generate a fresh ephemeral key pair for each tokenization session.

tenant*string

Tenant/business identifier (same value as TENANT header)

entityId*string

Customer entity ID in the M2P platform

kitNo*string

Kit number associated with the customer's card

Response Body

application/json

application/json

application/json

application/json

curl -X POST "https://secure.yappay.in/Yappay/bitUrl/v2/generateSharedSecret" \  -H "token: YOUR_API_TOKEN" \  -H "TENANT: TENANT_NAME" \  -H "Content-Type: application/json" \  -d '{    "publicKey": "04605a53e4d1a8c6a8b4d3e9f7c2a1b8e5d4f3c2a1b8e5d4f3c2a1b8e5d4f3c2a1b8e5d4f3c2a1b8e5d4f3c2a1b8e5d4f3c2a1b8e5d4f3c2a1b8e5d4",    "tenant": "TENANT_NAME",    "entityId": "1234567890",    "kitNo": "KIT123456"  }'
{
  "serverPublicKey": "04605a53e4d1a8c6a8b4d3e9f7c2a1b8e5d4f3c2a1b8e5d4f3c2a1b8e5d4f3c2a1b8e5d4f3c2a1b8e5d4f3c2a1b8e5d4f3c2a1b8e5d4f3c2a1b8e5d4",
  "sharedSecret": "b3954c44f2a1d8e6c9b3a7f2e1d8c6b4a3f2e1d8c6b4a3f2e1d8c6b4a3f2e1",
  "url": "https://auth.secure.yappay.in/visadirect/createCardToken?key=eyJhbGciOiJIUzI1NiJ9..."
}
{
  "result": null,
  "error": {
    "errorCode": "VALIDATION_ERROR",
    "shortMessage": "Invalid request",
    "detailMessage": "recipientPan is required",
    "fieldErrors": [
      "recipientPan: must not be blank"
    ]
  }
}
{
  "result": null,
  "error": {
    "errorCode": "AUTH_FAILED",
    "shortMessage": "Authentication failed",
    "detailMessage": "Invalid credentials"
  }
}
{
  "result": null,
  "error": {
    "errorCode": "INTERNAL_ERROR",
    "shortMessage": "Internal server error",
    "detailMessage": "An unexpected error occurred. Please contact support."
  }
}

Create Card Token (Frontend Only) POST

Tokenize a customer's card by submitting AES-encrypted card data directly from the **customer's browser or mobile app**. Returns an `altId` (M2P card token) that can be used in AFT pull and OCT push calls with `tokenType: "01"`. > ⚠️ **This call MUST originate from the customer's frontend (browser/app), NOT > from your backend server.** If your backend relays this call, card data enters > PCI scope on your systems, violating the non-PCI compliance boundary. **Use the `url` returned by `POST /bitUrl/v2/generateSharedSecret`** as the full endpoint for this request (it contains a signed session `key` query parameter). ### Encryption Flow (JavaScript example) ```js const { CryptoJS } = window; // load from cdnjs // Keys derived from the generateSharedSecret response const cvvAESKey = CryptoJS.SHA256(serverPublicKey); const payloadKey = CryptoJS.SHA256(sharedSecret); const iv = CryptoJS.enc.Hex.parse("00000000000000000000000000000000"); // 1. Encrypt CVV using serverPublicKey-derived key const encryptedCvv = CryptoJS.AES.encrypt( cvv, cvvAESKey, { iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 } ).toString(); // 2. Build payload and encrypt the whole thing using sharedSecret-derived key const payload = { cardNumber: "4012001037141112", cardExpiry: "2027-12", cvv: encryptedCvv, // CVV is double-encrypted networkType: "VISA", business: "YOUR_BUSINESS_CODE", entityId: "1234567890" }; const encryptedReq = CryptoJS.AES.encrypt( JSON.stringify(payload), payloadKey, { iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 } ).toString(); ``` The `encryptedReq` string above is the value to submit in the request body. ### Token Lifecycle - Token state: `ACTIVE` → `CONSUMED` (after one successful transaction) or `EXPIRED` (after ~15 min TTL) - Tokens are **single-use** — each AFT/OCT transaction consumes the token

Pair ECDH Public Key (One-Time Setup) POST

Register your ECDH public key with M2P. This is a **one-time setup step** performed during partner onboarding — not per-session. The public key is generated using the **P-256 (secp256r1)** elliptic curve and submitted as a hex-encoded string. M2P stores this key and uses it as the base for ECDH shared secret derivation in subsequent `generateSharedSecret` calls. > **Note:** This endpoint is on the Core VDMS API server (`/Yappay` context), not the > Auth/Tokenization service. Use the servers `https://secure.yappay.in/Yappay` (production) > or `https://sit-secure.yappay.in/Yappay` (sandbox).