Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developers-sandbox.uqpaytech.com/llms.txt

Use this file to discover all available pages before exploring further.

The standard card issuance flow is two calls — Create Cardholder first, then Create Card with the returned cardholder_id. One-step mode collapses the two into one call: omit cardholder_id and put the cardholder data into cardholder_required_fields. The system creates the cardholder and issues the card in the same request. Use one-step mode when you issue cards on demand — for example, right after a user signs up, or in a single-screen onboarding flow. If you manage a pool of pre-built cardholders, stay with the traditional two-call flow; passing cardholder_id works exactly as before.

Prerequisites

  • A UQPAY sandbox account with Card Issuance enabled
  • An API token from Access Token
  • The target card product’s card_product_id, obtained via List Products

Step 1: Check which fields the product requires

Different card products (BINs) require different cardholder data. List card products and read the required_fields array on your target product — that is the exact list of cardholder fields you must supply to the create-card call.
curl "https://api-sandbox.uqpaytech.com/api/v1/issuing/products?page_number=1&page_size=10" \
  -H "x-auth-token: Bearer {your_auth_token}"
Response (key fields only):
{
  "product_id": "467e993f-317a-49fc-9ea0-bf49de7d1f76",
  "card_bin": "40963608",
  "required_fields": [
    { "name": "first_name",    "type": "string", "required": true },
    { "name": "last_name",     "type": "string", "required": true },
    { "name": "email",         "type": "string", "required": true },
    { "name": "country_code",  "type": "string", "required": true },
    { "name": "phone_number",  "type": "string", "required": true },
    { "name": "date_of_birth", "type": "string", "required": false }
  ]
}
Fields marked required: true must be provided; required: false fields are optional. Object-typed fields such as identity, residential_address, and kyc_verification follow a nested structure — their sub-field rules are given in the product’s fields array.

Step 2: Create the card with cardholder data inline

Put the product’s required fields into cardholder_required_fields and omit cardholder_id:
curl -X POST "https://api-sandbox.uqpaytech.com/api/v1/issuing/cards" \
  -H "Content-Type: application/json" \
  -H "x-auth-token: Bearer {your_auth_token}" \
  -H "x-idempotency-key: {unique_uuid}" \
  -d '{
    "card_product_id": "467e993f-317a-49fc-9ea0-bf49de7d1f76",
    "card_currency": "USD",
    "card_limit": "500.00",
    "cardholder_required_fields": {
      "email": "alex.chen@example.com",
      "first_name": "Alex",
      "last_name": "Chen",
      "country_code": "SG",
      "phone_number": "90851548"
    }
  }'
Response:
{
  "card_order_id": "86411dab-9820-4042-b103-39989deb957d",
  "card_id": "b52e93a8-3c1d-453e-81ac-ec7268fad082",
  "cardholder_id": "a32835fe-141e-41fd-bcce-9fe88b3e8cbd",
  "card_status": "PENDING",
  "order_status": "PROCESSING",
  "create_time": "2026-04-24T18:07:49+08:00",
  "cardholder_status": "SUCCESS",
  "cardholder_created": true,
  "verification_status": "VERIFIED",
  "message": "card creation in progress"
}
A few fields to note:
  • cardholder_id — the newly-created cardholder. Save this value if you need to manage the cardholder later.
  • card_status: PENDING + order_status: PROCESSING — the card is being provisioned asynchronously. This is not a failure; wait for the card.create.succeeded webhook before treating the card as active.
  • cardholder_created: true — the cardholder was created inline as part of this request.

Special case: Sumsub IDV

If the product’s required_fields list kyc_verification, and you ask UQPAY to run identity verification through Sumsub (method: SUMSUB_REDIRECT), the response carries an IDV URL:
{
  "card_id": "ef5c44df-8c31-4adf-88b2-22ff7ce0e6d8",
  "cardholder_id": "9cb41553-e186-4e43-a17a-07f0772c6c75",
  "card_status": "PENDING",
  "cardholder_status": "INCOMPLETE",
  "idv_verification_url": "https://in.sumsub.com/websdk/p/sbx_xxx",
  "idv_url_expires_at": "2026-04-25T18:09:19+08:00",
  "kyc_method": "SUMSUB_REDIRECT",
  "verification_status": "ACTION_REQUIRED"
}
Redirect the cardholder to idv_verification_url before idv_url_expires_at. Once Sumsub confirms the verification, UQPAY activates the card automatically and notifies you by webhook. If you have already run KYC on your side and want to submit a proof directly, use method: THIRD_PARTY with a kyc_proof block; the response returns verification_status: VERIFIED without any redirect. See Enhanced KYC Card Issuance for the full details.

Waiting for async completion

For every one-step request, the initial HTTP response is only an acknowledgement. The card’s real activation (and the cardholder’s final state) happens asynchronously. Subscribe to these two webhooks before calling the endpoint:

Error handling

Two errors are specific to one-step mode. Both return HTTP 400.

cardholder_missing_info

Neither cardholder_id nor cardholder_required_fields was provided.
{
  "type": "cardholder_error",
  "code": "cardholder_missing_info",
  "message": "either cardholder_id or complete cardholder_required_fields must be provided"
}

cardholder_incomplete_fields

cardholder_required_fields was provided but missing one or more required keys (for example, email, first_name). The response carries a missing_fields array so you can display a targeted error to your user.
{
  "type": "cardholder_error",
  "code": "cardholder_incomplete_fields",
  "message": "cardholder_required_fields is incomplete for one-step card issuance",
  "missing_fields": ["email", "first_name", "last_name", "country_code"]
}
Other common errors (email_duplicated, phone_number_duplicated, invalid_phone_number, etc.) are the standard cardholder_error codes. See the Create Card API reference for the full list.