Cards

Card Request

Create a new card request and track its latest request status.

Flow Summary

The current card request flow is:

Step 1. Complete KYC and cardholder setup Use KYC first

Step 2. Create the card requestPOST /api/v1/card-request

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

Authorization: Bearer <access_token>

Important Prerequisite

The backend does not allow a card request unless the current mobile user already has a card_holder record with:

card_status = SUCCESS

In practice, that means the user must already have completed the KYC/cardholder flow successfully before POST /api/v1/card-request can work.

If no successful cardholder exists, the service returns a not-found style error.

1. Create Card Request

POST /api/v1/card-request

This route is protected and also IP-rate-limited to 60 requests per minute.

Request

{
  "card_type": "VIRTUAL",
  "country_id": 114,
  "address": "Phnom Penh",
  "post_code": "120101"
}

URL Query Parameters:

  • method (optional): Payment method
    • agent-pay: Agent pays on behalf of user using agent's prepaid balance
    • user-pay: User pays directly via payment gateway (default)

Request rules

  • card_type is required
  • Current enum values are VIRTUAL and PHYSICAL
  • country_id is required
  • address is required
  • post_code is required
  • post_code must be sent as a string
  • post_code must contain 4 to 10 digits
  • method is optional URL parameter, defaults to user-pay if not provided

Important backend behavior

  • agent_id and mobile_user_id are not accepted from the client; the backend fills them from the auth token
  • The service generates a unique merchant_order_sn in the format HTP-<uuid>
  • The initial record is created with:
    • card_status = AWAITING_PAYMENT
    • admin_status = PENDING
    • request_by = MOBILE
  • After the DB row is created, the service makes a synchronous RPC call to create a payment order
  • If that payment-order RPC fails, the API returns an error and the card request flow is treated as failed
  • A user notification is created in the background after successful creation

Payment Methods

Agent Payment (agent-pay):

  • Payment is automatically deducted from agent's prepaid balance
  • Card request is immediately approved
  • Card creation starts right away
  • No payment order processing required

User Payment (user-pay):

  • User must complete payment through payment gateway
  • A payment order is created with merchant_order_sn
  • Use the payment order endpoint to check payment status:
    • GET /api/v1/payment-orders/{merchant_order_sn}
  • After successful payment, card request is processed based on system settings

Success response

{
  "status_code": 201,
  "message": "Success",
  "data": {
    "id": 42,
    "uuid": "5e5d4990-2241-46dc-9dbd-8abcf97e6061",
    "card_status": "AWAITING_PAYMENT",
    "payment_status": "PENDING",
    "admin_status": "PENDING",
    "merchant_order_sn": "HTP-8c2af6ac-7d58-4b1e-8bb7-3ee80f7a9d64",
    "card_type": "VIRTUAL",
    "country_id": 114,
    "address": "Phnom Penh",
    "post_code": 120101
  }
}

Response when method=agent-pay (card already approved):

{
  "status_code": 201,
  "message": "Success",
  "data": {
    "id": 42,
    "uuid": "5e5d4990-2241-46dc-9dbd-8abcf97e6061",
    "card_status": "PROCESSING",
    "payment_status": "SUCCESS",
    "admin_status": "APPROVED",
    "merchant_order_sn": "HTP-8c2af6ac-7d58-4b1e-8bb7-3ee80f7a9d64",
    "card_type": "VIRTUAL",
    "country_id": 114,
    "address": "Phnom Penh",
    "post_code": 120101
  }
}

2. List Card Requests

GET /api/v1/card-request

Lists the current user’s card requests with pagination.

Query parameters

NameRequiredNotes
pageNoDefault 1
limitNoDefault 10
statusNoFilters by card_status

Success response shape

{
  "status_code": 200,
  "message": "Success",
  "data": [
    {
      "id": 42,
      "card_status": "AWAITING_PAYMENT",
      "created_at": "2026-02-28T10:00:00Z",
      "card_type": "VIRTUAL",
      "payment_status": "PENDING"
    }
  ],
  "metadata": {
    "current_page": 1,
    "limit": 10,
    "total": 1
  }
}

Notes

  • The list is filtered to the authenticated mobile user
  • Results are sorted by created_at DESC
  • The status filter applies to the raw card_status field, not the computed summary status from /status

3. Get Card Request By UUID

GET /api/v1/card-request/{uuid}

Returns the full request details for one specific card request owned by the current user, including card details if the card has been successfully created.

Response structure

The response has two parts:

  1. Card Request Details (always returned):
    • id: Local database ID
    • uuid: Card request UUID
    • payment_status: Payment status (PENDING, SUCCESS, EXPIRED, FAILED)
    • card_status: Card request status (AWAITING_PAYMENT, PROCESSING, SUCCESS, FAILED)
    • admin_status: Admin approval status
    • card_type: VIRTUAL or PHYSICAL
    • merchant_order_sn: Merchant order serial number
    • country_id, address, post_code: Request details (post_code is returned as an integer in this API contract)
  2. Card Details (included only when card_status = SUCCESS):
    • id: Card local database ID
    • uuid: Card UUID
    • card_number: 16-digit card number
    • card_id: Card identifier from payment provider
    • card_type: VIRTUAL or PHYSICAL
    • card_provider: MASTER, VISA, etc.
    • first_name, last_name, name_on_card: Cardholder details
    • card_limit: Card limit formatted as string
    • available_balance: Current available balance
    • limit_per_transaction: Per-transaction limit
    • status: ACTIVE, BLOCKED, FROZEN, etc.
    • created_at, updated_at: Timestamps

Success response examples

When card is still being processed (card_status ≠ SUCCESS):

{
  "status_code": 200,
  "message": "Success",
  "data": {
    "id": 42,
    "uuid": "5e5d4990-2241-46dc-9dbd-8abcf97e6061",
    "payment_status": "SUCCESS",
    "card_status": "PROCESSING",
    "admin_status": "APPROVED",
    "merchant_order_sn": "HTP-8c2af6ac-7d58-4b1e-8bb7-3ee80f7a9d64",
    "card_type": "VIRTUAL",
    "country_id": 114,
    "address": "Phnom Penh",
    "post_code": 120101
  }
}

When card has been successfully created (card_status = SUCCESS):

{
  "status_code": 200,
  "message": "Success",
  "data": {
    "id": 42,
    "uuid": "5e5d4990-2241-46dc-9dbd-8abcf97e6061",
    "payment_status": "SUCCESS",
    "card_status": "SUCCESS",
    "admin_status": "APPROVED",
    "merchant_order_sn": "HTP-8c2af6ac-7d58-4b1e-8bb7-3ee80f7a9d64",
    "card_type": "VIRTUAL",
    "country_id": 114,
    "address": "Phnom Penh",
    "post_code": 120101,
    "card": {
      "id": 508,
      "uuid": "550e8400-e29b-41d4-a716-446655440000",
      "card_number": "4111111111111111",
      "card_id": "card_abc123",
      "card_type": "VIRTUAL",
      "card_provider": "MASTER",
      "first_name": "John",
      "last_name": "Doe",
      "name_on_card": "JOHN DOE",
      "card_limit": "5000.00",
      "available_balance": "5000.00",
      "limit_per_transaction": "1000.00",
      "status": "ACTIVE",
      "card_currency": "USD",
      "created_at": "2026-02-28T10:05:00Z",
      "updated_at": "2026-02-28T10:05:00Z"
    }
  }
}

Important behavior notes

  • Card details are conditional: The card object is only included when card_status = SUCCESS
  • For PENDING/PROCESSING/FAILED requests: The card field will be null or omitted
  • Card creation flow:
    1. Request created → card_status = AWAITING_PAYMENT
    2. Payment completed → payment_status = SUCCESS
    3. Approvals granted → admin_status = APPROVED
    4. Card successfully created → card_status = SUCCESS (now card details are available)
  • Physical cards: May have additional PROCESSING state while activation code is being generated
  • Idempotency: Calling this endpoint multiple times with the same UUID will return consistent data

Common failures

  • 404: request not found for this user/agent
  • 401: auth context missing

Integration Notes

  1. Do not treat POST /card-request as the whole card issuance result; it only creates the request and payment order.
  2. Use /card-request/{uuid} to get the full detail screen for a specific request.
  3. Poll card creation status:
    • For agent-pay: Card creation starts immediately after request
    • For user-pay: Check payment order status first, then poll /card-request/{uuid}
    • When card.status = SUCCESS, the response will include full card details
    • Recommended polling interval: 2-5 seconds
Copyright © 2026