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.

Common questions and solutions gathered from real integration experiences. If you don’t find your answer here, contact your UQPAY account manager.

Sandbox testing

The sandbox simulation endpoint only accepts cards with a specific BIN. The currently supported BIN for simulation is 40963608. Cards with other BINs will return this error.Also check:
  • The card has not been cancelled. Cancelled cards cannot process authorizations.
  • You are using the correct sandbox base URL: https://api-sandbox.uqpaytech.com/api
This means the pre-allocated card pool for your BIN is exhausted. Contact your UQPAY account manager to request additional card allocation for the specific BIN.The card count shown in the dashboard reflects only active cards, not the total allocated pool. You cannot self-service replenish the pool.
In sandbox, simulated deposits require manual approval by UQPAY staff before the balance is credited. Submit the deposit reference ID in your support group and staff will approve it. This approval step does not exist in production.
You cannot use random card numbers for the Assign Card API. UQPAY provisions a set of physical card numbers for sandbox use and sends them to you. Request these from your UQPAY account manager.

Authentication and API setup

Access tokens are valid for 30 minutes. Cache only one token at a time — generating a new token immediately invalidates all previously issued tokens, regardless of their remaining expiry time.Use the expired_at field in the token response to determine when to refresh. See Request Access Token.
The x-on-behalf-of header requires strict validation:
  • Must be a valid UUID format (e.g., 18523f72-f4de-4f9c-bb8e-ec7d1c4f32be)
  • Must correspond to a valid Issuing sub-account ID
  • Empty or malformed values return an error
If you receive sub_account_not_found, verify the account ID belongs to the Issuing business line (not Banking), and that the sub-account is activated.
The IP restriction on the API Key is matched against your server’s actual outbound IP reaching UQPAY. If you are behind a VPN or proxy, ensure the configured IP matches your real outbound IP. Local/private IPs (e.g., 192.168.x.x) are not routable and will always fail.
Submitting the same x-idempotency-key on a repeat request returns the cached result of the original request — no new operation is created. Important behaviors:
  • The cached response persists for 24 hours
  • If the original request failed (e.g., insufficient balance), retrying with the same key returns the same failure — even if conditions have changed. Use a new key when retrying after fixing the root cause.
  • If you receive a 504 timeout, retry with the same key — the server may have already processed the request
Two common causes:
  1. Missing Content-Type: Always include Content-Type: multipart/form-data for file uploads
  2. Reused idempotency key: The x-idempotency-key must be a valid UUID and unique for each new request

Cardholders

first_name and last_name must be in English (Latin characters). Chinese or other non-Latin characters are not accepted. Address fields within delivery_address do accept Chinese.
The phone number must match the country_code format. Pass the country_code matching the phone number’s dialing region, not the cardholder’s nationality. Numbers should be in international format without the leading zero.See Phone Number Validation Rules for details.
Uniqueness is enforced per account. Within the same account_id, email and phone number must each be unique — no two cardholders under that account can share either value. The same email or phone can be reused under a different account_id.
No. There is no Delete Cardholder API. Cardholders cannot be removed once created.

Card creation and configuration

The risk_controls parameter (including allow_3ds_transactions) is only supported on specific BINs. Passing this parameter for unsupported BINs returns an error. The same restriction applies to no_pin_payment_amount.See Supported BINs for Risk Control Configurations for the full list.
Your account has reached its maximum card creation limit. Contact your UQPAY account manager to increase the quota.
The BIN or sub-BIN has not been configured for your account. Provide your account ID to UQPAY support and they will assign the appropriate sub-BIN pool. This error also recurs when the sub-BIN pool is exhausted.
Cards are created in PENDING status and transition to ACTIVE once provisioning completes. To detect activation, either listen for the card.create.succeeded webhook or poll the Retrieve Card endpoint — both are supported.
Each card has a maximum single-transaction spending cap enforced by the platform. The specific cap depends on your account configuration, and higher caps are available via a VIP whitelist on a per-card basis. Contact your UQPAY account manager to confirm or adjust the limit for your account.
There is a cap on the number of sub-accounts you can create under a main account. The specific limit depends on your account configuration — contact your UQPAY account manager to confirm or adjust it for your account.

Card status and lifecycle

StatusDescriptionControlled by
ACTIVECard is active and can process transactionsMerchant
FROZENCard is temporarily frozen — can be unfrozen via APIMerchant
BLOCKEDCard is blocked by risk controls — requires UQPAY to unlockSystem
PRE_CANCELCard is scheduled for cancellation (30-day wait)
CANCELLEDCard is permanently cancelled
See Card Lifecycle for the full state transition diagram.
FROZEN is merchant-controlled: you can freeze and unfreeze a card via the API without contacting UQPAY.BLOCKED is system-triggered by risk controls (e.g., consecutive failed PIN or expiry attempts). BLOCKED cards can only be unlocked by UQPAY operations — submit an email to support@uqpay.com with the cardholder name, card ID, current status, and reason for unlock.Refunds and reversals can still post to both FROZEN and BLOCKED cards.
Yes. You can transition a card from FROZEN directly to CANCELLED in a single API call without first reverting to ACTIVE.
After cancellation is requested, the card enters PRE_CANCEL status for a 30-day waiting period, then automatically transitions to CANCELLED. During PRE_CANCEL:
  • The card cannot process new transactions
  • Previously authorized transactions may still settle
  • For Single cards, UQPAY automatically sweeps remaining balance back to the merchant account after the waiting period
No. You must unfreeze the card (set to ACTIVE) before assigning or modifying its limit.
Virtual cards are active immediately upon successful creation — no activation step is required. See Issue Virtual Cards.Physical cards require activation via /api/v1/issuing/cards/activate, using the activation code delivered by the card.activation.code webhook after assignment. See Issue Physical Cards.

Card funding and limits

BehaviorSingle CardShare Card
FundingUse recharge / withdraw APIsDraws from merchant pool balance
card_limitCannot be changed after creationCan be modified via Update Card API
FeesDeducted from card balance (may go negative)Deducted from pool account
See Core Concepts for background on card types.
Single-mode cards do not support modifying card_limit after creation. To adjust a Single card’s spendable amount, use the recharge and withdraw APIs instead.
No. Currently there is no API for transferring funds between the Banking and Issuing business lines. This must be done manually via the Dashboard’s Deposit button in the Issuing section.
This means the Issuing transfer product has not been configured for the sub-account. Contact UQPAY operations to activate it.

Transactions and settlement

StatusDescription
APPROVEDTransaction approved
DECLINEDTransaction declined
PENDING is a transient state that exists only briefly during processing — do not act on it. Wait for the issuing.transaction.authorization webhook, which always carries a terminal state. The REFUNDED status was removed as of May 29, 2025.
The failure_reason field was renamed to description as of May 29, 2025. Update your integration to read the description field instead.This change affects:
  • List Cards Transactions API
  • Retrieve Cards Transaction API
  • card.transaction.* webhook events
  • Exported transaction reports
Both ATM withdrawals and regular purchases return AUTHORIZATION as the transaction_type. To differentiate, check merchant_data.category_code:
  • MCC 6011 = ATM cash withdrawal
  • MCC 6011 with billing_amount == 0 = ATM balance inquiry
  • Other MCC values = regular purchase
This means the card’s card_limit exceeds the platform’s maximum allowed single-transaction cap configured for your account. Contact your UQPAY account manager to raise the cap via a VIP whitelist, or keep per-card limits within the configured cap.
This decline indicates the transaction exceeded the configured contactless/no-PIN limit for the card. The cardholder should retry with PIN entry.
No. A 200 response only confirms UQPAY received your request. The actual business result is only guaranteed by the webhook callback. Always use webhooks as the authoritative source of truth.

Webhooks

Check these common causes:
  1. Event subscription: Verify you have subscribed to the specific event type. For example, wallet binding OTPs require card.verification.otp; transaction validation requires issuing.transaction.validation.
  2. HTTP 200 response: Your endpoint must return HTTP 200 within the timeout period.
  3. URL accessibility: Ensure your webhook URL is publicly accessible from UQPAY’s source IPs.
See Webhook Delivery Troubleshooting Guide for the full checklist.
See Retry logic for the current retry behavior.
See the IP whitelist section in Webhooks Overview for the current list of source IPs to allowlist on your firewall.
Yes. Re-send individual events yourself from the Dashboard using the Re-Trigger button. See Check previous webhooks or re-trigger for step-by-step instructions.

3D Secure and wallet payments

Whether 3D Secure is triggered for a transaction is decided on the acquirer side at checkout time, not on the issuer side. The issuer-side switch allow_3ds_transactions only controls how the cardholder authenticates once 3DS has been triggered — specifically, whether a frictionless (no interaction) flow is permitted, or whether a challenge flow with manual OTP entry is required.Because the trigger happens at the acquirer, a transaction can still enter the 3DS flow even when allow_3ds_transactions is N, which is why 3DS verification fees may still be incurred.To bypass 3DS entirely (and avoid the associated verification fees), set enable_3ds to N on the card. This unregisters the card from 3DS so the acquirer cannot trigger 3DS authentication on it. See 3D Secure for the full two-field model.
Wallet binding OTPs require subscribing to the card.verification.otp event type specifically. Standard ISSUING webhook subscriptions do not include this.
Yes. UQPAY can disable email sending to cardholders (activation codes, 3DS OTPs) at the account level. You then receive these via webhook and deliver them through your own channel. Contact your account manager to configure.

Secure iFrame and PCI

The /cards/:id/secure endpoint requires the card to be in ACTIVE status. Calling it on a PENDING card returns Card does not exists. Wait for the card to activate first.

Physical cards

If the card has already been assigned successfully, a second Assign Card call returns this error. The assign operation is not idempotent — use the error response to detect duplicates.
The physical card number being assigned belongs to a batch not allocated to your account. Physical card inventory is account-specific. Verify that the card batch was registered under the correct merchant account.