Cards

Card Transactions

Create top-ups, list top-ups, create card-to-card transfers, and fetch transfer details.

Flow Summary

The transaction flows are currently:

Step 1. Make sure the source card is active
Use Virtual Cards to confirm card status first

Step 2. Start a top-up or transfer
Use POST /api/v1/card-topup or POST /api/v1/cards/transfer

Step 3. Check the follow-up record
Use GET /api/v1/card-topup or GET /api/v1/cards/transfer/{id}

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

Authorization: Bearer <access_token>

The POST /api/v1/card-topup route also passes through DecryptField(), so it accepts either plain JSON or the encrypted wrapper described in Overview.

1. Create Card Top-Up

POST /api/v1/card-topup

Creates a new top-up order for a card.

Request

{
  "amount": 100,
  "card_id": 508
}

Request rules

  • amount is required
  • card_id is required
  • card_id is the local numeric card record ID

Important backend behavior

  • The card must belong to the current user
  • The card must currently be ACTIVE
  • The input amount is treated as the user's USDT funding amount
  • Fees, adjusted exchange rate, and the final net amount are calculated server-side
  • The new top-up row is created with status = PENDING
  • After the DB row is created, the service makes a synchronous RPC call to create a payment order

Success response notes

  • The response returns the new top-up entity
  • It includes derived payment fields such as rate, fee, and payable totals generated by the service

2. List Card Top-Ups

GET /api/v1/card-topup

Lists top-up records with pagination.

Query parameters

NameRequiredNotes
pageNoDefault 1
limitNoDefault 10
searchNoFree-text search
statusNoFilters by top-up status
from_dateNoDate range start
to_dateNoDate range end

Important backend caveat

  • The current repository implementation is not explicitly scoped to the authenticated mobile user
  • In practice, this behaves more like a shared top-up list filtered only by the provided query params
  • Clients should treat this as an implementation gap and avoid assuming strict user-only isolation until the backend is tightened

3. Create Card Transfer

POST /api/v1/cards/transfer

Transfers balance from one card to another.

Request

{
  "source_card_uuid": "5e5d4990-2241-46dc-9dbd-8abcf97e6061",
  "destination_card_uuid": "6f77454d-400f-4ec4-8e2c-7a7ebfa0bcfe",
  "amount": "25.50",
  "remark": "Split payment"
}

Request rules

  • source_card_uuid is required and must be a UUID
  • destination_card_uuid is required and must be a UUID
  • amount is required
  • amount must be sent as a JSON string, not a JSON number
  • amount must parse as a decimal value greater than 0
  • remark is optional, max length 255

Important backend behavior

  • The route is IP-rate-limited to 60 requests per minute
  • The source and destination cards cannot be the same card
  • The source card must belong to the current user
  • Both cards must be ACTIVE
  • The service checks the source-card balance before executing the transfer
  • If the transaction type is empty internally, the service defaults it to TRANSFER
  • A transfer row is created first with status = PENDING, then the transfer executes synchronously
  • If the downstream transfer fails, the API returns an error and includes transfer metadata such as transfer_uuid and status in the error payload

4. Get Transfer By ID

GET /api/v1/cards/transfer/{id}

Returns one transfer record by local numeric ID.

Notes

  • The lookup is scoped to the current mobile user
  • If the transfer belongs to another user or does not exist, the route returns not found
  • Use this endpoint as the follow-up record lookup after creating a transfer
Copyright © 2026