Cards

Card Activation

Complete the physical-card activation flow with OTP verification and final activation.

Flow Summary

The current activation flow is:

Step 1. Resend the activation OTP
POST /api/v1/cards/resend-activation-otp

Step 2. Verify the OTP
POST /api/v1/cards/verify-activation-otp

Step 3. Activate the card
POST /api/v1/cards/activate

All routes below should be treated as protected routes and sent with:

Authorization: Bearer <access_token>

All three routes below also pass through DecryptField(), so they accept either plain JSON or the encrypted wrapper described in Overview.

1. Resend Card Activation OTP

POST /api/v1/cards/resend-activation-otp

Sends a fresh OTP for physical-card activation.

Important backend behavior

  • Requires the latest physical card request still in processing
  • Requires the current user to already have an email address
  • The service stores the OTP in Redis for 5 minutes
  • The response always includes remaining_seconds: 60
  • The handler message implies a 60-second resend cooldown, but the current service does not actually enforce that cooldown before issuing a new OTP

Success response shape

{
  "status_code": 200,
  "message": "Card activation OTP sent successfully",
  "data": {
    "success": true,
    "remaining_seconds": 60
  }
}

2. Verify Card Activation OTP

POST /api/v1/cards/verify-activation-otp

Verifies the OTP and returns the activation payload needed for the final activation call.

Request

{
  "otp_code": "123456"
}

Important backend behavior

  • The OTP is checked against Redis key otp:card_activation:<mobileUserID>
  • The stored OTP is six digits
  • On success, the service returns the latest processing physical card request's activation payload

Success response shape

{
  "status_code": 200,
  "message": "Success",
  "data": {
    "card_id": "5e5d4990-2241-46dc-9dbd-8abcf97e6061",
    "activation_code": "12345678"
  }
}

3. Activate Card

POST /api/v1/cards/activate

Completes physical-card activation with the upstream card UUID, activation code, and a new card PIN.

Request

{
  "card_id": "5e5d4990-2241-46dc-9dbd-8abcf97e6061",
  "activation_code": "12345678",
  "pin": "123456",
  "confirm_pin": "123456"
}

Request rules

  • card_id is required
  • card_id must be a UUID string
  • activation_code is required and must be exactly 8 digits
  • pin is required and must be exactly 6 digits
  • confirm_pin is required and must exactly match pin

Important backend behavior

  • This route is synchronous, not queued
  • It calls UQPay directly and returns the upstream activation result
  • On upstream validation failure, the API returns a business error with the parsed upstream metadata in the payload
Copyright © 2026