Skip to main content
This page walks you through issuing your first working card in the sandbox using the recommended best-practice path. As a licensed card issuer with its own BINs, DCS closes the loop on issuing, KYC, authorization and settlement inside a single API set — you do not need to build any card-core capability yourself. This page follows one minimal path only (mobile registration, hosted guidance page, a single virtual card, a single deposit currency). The full KYC flow, chain/currency matrix, card management and reconciliation are covered on their own pages.

Before you start

Make sure the following are in place (see First Steps for details):
  • You understand the DeCard-Managed model: authorization decisions are made inside DCS; cardholders move funds into DCS custody and DCS derives the card’s spending limit from their available assets in real time (see Overview).
  • You have received your API Key / Secret Key.
  • You have given DCS your network egress IP (DCS enforces an API whitelist).
  • Webhook callback URL (required): the card-issuing result in this flow is delivered by Webhook. Without it you cannot complete Step 4.
  • WebSocket connection (optional): configure it if you want real-time pushes of balance changes, transaction results, etc. See Webhook & WebSocket.
Environments — Sandbox: https://api.thedecard-sandbox.com; Production: https://api.thedecard.com.
Authentication: every request must carry the four headers X-DAPI-API-KEY / X-DAPI-TIMESTAMP / X-DAPI-NONCE / X-DAPI-SIGN with an HMAC-SHA256 signature. The full rules (signature concatenation formula, replay protection, code samples) are in the Authentication Guide. The examples below omit the auth headers to keep the focus on business fields — they are mandatory in real calls. SecretKey is only used locally to compute the signature and is never sent over the wire.
Path prefix: DeCard-Managed modules use the /account/, /card/, /crypto/, /user-asset/, /redirect/ and /simulation/ prefixes directly (no /open-api/ prefix).
All mobile numbers, user IDs and addresses below are masked placeholders — replace them with your own values.

📄 Guide

Six steps in total. The overall shape is: you call the API to initiate, the cardholder completes sensitive operations on a DCS-hosted page, and the result comes back to you over Webhook.
Quickstart six-step sequence diagramQuickstart six-step sequence diagram
The diagram shows the production path. In the sandbox, the deposit and purchase in Step 6 use simulator endpoints instead — see that step for details.

Step 1: Send the SMS verification code

In the DeCard-Managed model, users register in two stages with “mobile number + SMS OTP”. First request a code for the target mobile number:
mobileCode is the ISO 2-letter country code (e.g. SG / CN / US); mobile is the local number without the dialing prefix. Leave externalUserId empty when registering a new user. behavioral is a scenario enum identifying what the code is for: REGISTER (registration) / CARD_UNFROZEN (unfreeze a card) / WITHDRAW (withdrawal). Use REGISTER here.
Successful response (the envelope is always {code, message, messageDetail, data}, success code code = SYS_SUCCESS):
data is always an empty string for this endpoint — the code is delivered by SMS, not in the response body. Judge success by code = SYS_SUCCESS. About the envelope: messageDetail is usually null on success; on failure, or when the end user needs to be prompted, it is an object (with message / title / type / icon / action / linkTitle / linkUrl). To keep the focus on business fields, the remaining examples on this page show the envelope in its success form only.

Step 2: Register the user

Complete registration with the SMS code from the previous step:
Mobile registration requires mobileCode + mobile + smsCode all three together. DCS also supports an email registration path (email + emailCode), which is strictly mutually exclusive with the mobile path — sending smsCode and emailCode in the same request is rejected with SMS_EMAIL_CODE_MUTUALLY_EXCLUSIVE. This page uses the mobile path only; for the email path see Signing Up a Customer.
The data field of the response returns externalUserId directly (the user ID, a plain string). Every later endpoint identifies the user by it — store it:
This is the recommended way to issue a card. Both KYC and the card application happen inside a DCS-hosted H5 page — the cardholder’s documents and selfie go straight to DCS without passing through your backend, so you do not take on that compliance and storage burden.
action, externalUserId, successRedirectUrl and errorRedirectUrl are all required. language uses the lower-case hyphenated form and is case-sensitive: zh / en / ko / ja / zh-Hant / th / vi. A value outside this whitelist is silently downgraded to the default language rather than rejected — stick to this list exactly. For the full parameter set (theme / mode / primaryColor / selectCardPageShow, etc.) see H5 KYC / Card Onboarding Guidance Page.
The data field of the response is the one-time guidance link (a plain string). Hand it to the cardholder to open in a browser:
The link is valid for 5 minutes (the server-side secret has a 300-second TTL); once expired the page stops working and you must request a new one. Therefore do not deliver the link over asynchronous channels such as email or support tickets — generate it and redirect while the cardholder is in an active session. If the user abandons and comes back, call this endpoint again for a fresh link rather than caching and reusing one.
Two pre-checks will reject the request outright — handle them during integration:
  • If the user’s KYC is already PASS or PENDING, the API returns OPERATION_UNSUPPORTED — re-initiation is not allowed.
  • If the daily application rate limit is hit, the API returns KYC_APPLY_LIMIT_EXCEEDED — throttle your retries and surface a message to the user.

Step 4: Receive the card-application Webhook

Once the cardholder submits on the hosted page, the result is pushed to you as a CARD_APPLY Webhook. In this flow the partner never initiates the card application, so this is the only way to obtain applyId (once issuing succeeds, cardId can also be read from the card query endpoint in Step 5).
The same event is delivered over both Webhook and WebSocket (the server pushes WS first, then the Webhook), with identical payloads. Consuming the Webhook alone is enough for this flow; if you also consume WebSocket, de-duplicate on your side.
The data structure of the CARD_APPLY event: status has only three external values (internal intermediate states such as KYC-passed and card-created are all collapsed into PENDING):
Return 2xx within 2 seconds of receiving the Webhook (DCS uses a 2000 ms connect timeout and a 2000 ms socket timeout). Persist first and process asynchronously, otherwise the delivery is treated as a timeout and retried. See Webhook & WebSocket.

Branch: needExtraInfo = true

When KYC requires additional documents from the cardholder, the Webhook carries needExtraInfo = true. Request a second guidance link with the same applyId:
For KYC_EXTRA_DOC, applyId is required — omitting it returns OPERATION_UNSUPPORTED; an applyId that does not belong to the user returns PERMISSION_DENIED; and an application whose needExtraInfo is not true also returns OPERATION_UNSUPPORTED. Drive this off the Webhook’s needExtraInfo — do not call it speculatively.
After the cardholder submits the documents, DCS pushes CARD_APPLY again until status reaches the terminal SUCCEED or FAILED.

Step 5: Card management

Once you have cardId, day-to-day card management is available. List cards / query a single card
externalUserId is required; cardId is optional — leave it empty to return all of the user’s cards, or pass it to query one. The response includes cardStatus (NORMAL / FROZEN / CANCELLED), cardNo (masked), cardHolder, physicalCardStatus and more.
Show the full card number to the cardholder For PCI compliance, the full PAN, CVV and expiry are never returned to your backend by the API. Use the CARD_INFO guidance page so the cardholder views them directly on the DCS-hosted page:
The four actions CARD_INFO / CREATE_PHYSICAL_CARD / ACTIVE_PHYSICAL_CARD / UPDATE_PIN must carry cardId, and the user must already hold a card — otherwise the request is rejected.
Freeze / unfreeze
block = true freezes, false unfreezes. In the response, data is a boolean indicating whether this freeze or unfreeze operation succeeded (true = success / false = failure).
Unfreezing requires second-factor verification: when block = false you must also supply smsCode or emailCode. Issue it first with the Step 1 endpoint using behavioral = CARD_UNFROZEN. Freezing does not require it.
Physical card application and activation, PIN reset and the remaining capabilities are covered in Managing Cards.

Step 6: Fund the account and simulate a purchase

Deposit — production Fetch the user’s crypto deposit address and transfer on-chain to it:
All three parameters are required. v2 returns network / address / coin / fxRate / status.
This endpoint does not return the minimum deposit amount or the required on-chain confirmation count. If you need to tell the cardholder either of those, read them from the network-coin configuration (minConfirm and related fields) or maintain that configuration yourself. The supported chain and currency matrix is in Crypto Deposit.
Deposit — sandbox In the sandbox, use the simulator to credit the user’s account directly, which keeps integration testing simple:
This simulates funds arriving at the user’s crypto deposit address. Take address from the previous step.
Confirm the balance
Balance fields: free = available, freeze = frozen, total = total (these are the actual API field names). The response is an array — iterate by asset.
Simulate a purchase Use the simulator to raise a card authorization and verify your Webhook handling and limit changes:
Prefer v2 — it locates the card by cardId, which chains directly off the cardId from Step 4. v1 locates the card by cardMantissa (last four digits) and is kept for compatibility only. authType enum: EXPEND (purchase) | REFUND (refund) | REVERSAL (purchase reversal). Authorization is decided inside DCS against the user’s available assets; approved is the result. Sandbox simulation produces real transaction records, triggers Webhooks and updates balances, but involves no real funds. Full scenarios in Simulating Transactions.
Your first working card is now issued, funded, and has completed a simulated purchase.

Next steps

  • Full KYC flow and state machineCompliance — the complete swimlane for application, review, POA supplementation and AML handling
  • All guidance-page actions and parametersH5 KYC / Card Onboarding Guidance Page — the seven actions, language and theme customization, link validity
  • Physical cards, replacement, PIN resetManaging Cards — full card lifecycle management
  • Crypto deposit chain/currency matrix and on-chain withdrawalVirtual Accounts — multi-chain deposit and withdrawal
  • All sandbox simulation scenariosSimulating Transactions — purchase, refund, reversal and every other transaction type
  • Auth headers and the HMAC-SHA256 signature ruleAuthentication Guide — required headers, concatenation formula, replay protection and code samples
  • Webhook & WebSocket real-time pushWebhook & WebSocket — payload structures for all 9 event types, retry and idempotency handling