> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thedecard.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Managing a Card's PIN

> Why setting and updating a PIN in the DeCard-Managed model runs through a hosted guidance page rather than a direct API, plus how to obtain the PIN guidance link (action=UPDATE_PIN), the full sequence, and how to handle errors.

## 📄 Guide

Cardholders need a PIN to withdraw cash at an ATM and to pay at some offline POS terminals. As a licensed issuer with its own BINs, DCS treats setting a PIN as a sensitive operation that has to happen inside a trusted page: in the DeCard-Managed model, **PINs are not set or updated through a direct API**. Instead you send the user to a **DCS-hosted H5 guidance page** where they set the PIN themselves, so PIN entry and encryption both happen inside the DCS-hosted page and never touch your backend.

> **Prerequisite**: you must already have issued the card and hold its `cardId`. If you are not yet sure how to apply for a card, read [Issuing Cards](./issuing-cards) first.

### Mental model: why the PIN goes through a guidance page instead of an API

The DeCard-Managed model groups PIN setting with the operations an end user must complete in person inside a trusted page, alongside KYC, viewing sensitive card details and activating a physical card. All of them run through the same **redirect guidance page (guidanceLink)**:

1. Your backend calls the guidance page endpoint with the operation type (`action` / `type`) and the target card identifier, and receives a single-use guidance link.
2. You redirect the user to that link.
3. The user enters and submits the new PIN inside the DCS-hosted H5 page, which validates and encrypts it.
4. When they are done, the page returns the user to your app at the redirect URL you supplied.

That way **neither your client nor your backend ever handles the PIN in plaintext**, which keeps your PCI and compliance burden low.

## Obtaining the PIN guidance link

The PIN page reuses the common guidance page endpoint, which identifies the card precisely with `cardId`.

| Endpoint                          | Card identifier field | Value that triggers the PIN flow |
| :-------------------------------- | :-------------------- | :------------------------------- |
| `POST /redirect/v2/guidance-link` | `cardId`              | `action = UPDATE_PIN`            |

> The **full parameter table and redirect mechanics** for the guidance page endpoint are documented in one place, [H5 KYC / Card Application Guidance Page](../../integration-resources/h5-kyc-guidance). This page lists only the fields that matter for the PIN flow, to avoid duplication.

### Request fields (PIN flow)

| Field                | Type   | Required | Description                                                                                                                                                  |
| :------------------- | :----- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `action`             | string | Yes      | Always `UPDATE_PIN` for the PIN flow                                                                                                                         |
| `externalUserId`     | string | Yes      | User ID, max length 50                                                                                                                                       |
| `cardId`             | string | Yes      | Target card ID, required for any action that operates on a specific card, `UPDATE_PIN` included                                                              |
| `successRedirectUrl` | string | Yes      | Redirect URL used after the PIN is set, max length 300                                                                                                       |
| `errorRedirectUrl`   | string | Yes      | Redirect URL used if setting the PIN fails, max length 300                                                                                                   |
| `referer`            | string | No       | Referrer, used for security checks, max length 300                                                                                                           |
| `userAgent`          | string | No       | User agent, used for security checks, max length 300                                                                                                         |
| `language`           | string | No       | Language of the customer-facing `guidance-link`, lowercase hyphenated and case-sensitive: `zh` / `en` / `ko` / `ja` / `zh-Hant` / `th` / `vi`, max length 10 |
| `selectCardPageShow` | string | No       | Whether to skip the card selection page when the user holds several cards: `0` = do not skip, `1` = skip, max length 1                                       |
| `theme`              | string | No       | Theme, for example `blue`, max length 10                                                                                                                     |
| `mode`               | string | No       | Light or dark mode, for example `dark` / `light`, max length 10                                                                                              |

> The required fields are `action` / `externalUserId` / `successRedirectUrl` / `errorRedirectUrl` / `cardId`. `theme` and `mode` are optional, but sending them every time is recommended, in line with the sibling page [Viewing Encrypted Card Details](./viewing-encrypted-card-details).
>
> Four further fields belong to the full guidance page contract but are not used by the PIN flow: `nationality` (nationality, honoured only by `KYC_GUIDE`), `selectNationalityShow` (nationality selection page, honoured only by `KYC_GUIDE`), `primaryColor` (primary colour, a hex value starting with `#`) and `applyId` (required when uploading extra documents). For the complete field table, see [H5 KYC / Card Application Guidance Page](../../integration-resources/h5-kyc-guidance).

### Request example (V2, masked)

```bash theme={null}
curl -X POST "{{dicard-server}}/redirect/v2/guidance-link" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "UPDATE_PIN",
    "externalUserId": "<external-user-id>",
    "cardId": "<card-id>",
    "successRedirectUrl": "https://your-app.example.com/pin/done",
    "errorRedirectUrl": "https://your-app.example.com/pin/error",
    "language": "en",
    "theme": "blue",
    "mode": "light"
  }'
```

> **Authentication**: the example omits the authentication headers to keep the focus on the business fields. A real call must carry `X-DAPI-API-KEY` / `X-DAPI-SIGN` / `X-DAPI-TIMESTAMP` / `X-DAPI-NONCE` (HMAC-SHA256 signature); for the rules, see the [Authentication Guide](../../integration-resources/overview).

<Warning>
  Every example value is a placeholder. **Never** put a real `externalUserId`, `cardId`, API key or secret, or any cardholder personal data into a request or a log.
</Warning>

### Response

The guidance page endpoint returns the common envelope `{ code, message, messageDetail, data }`. On success `code = SYS_SUCCESS` and `data` is the guidance page link, as a string. `messageDetail` is a **message object** (its schema has seven sub-fields: `message` / `title` / `type` / `icon` / `action` / `linkTitle` / `linkUrl`) used to carry structured messaging on failure; on success it is normally `null`.

```json theme={null}
{
  "code": "SYS_SUCCESS",
  "message": "...",
  "messageDetail": null,
  "data": "https://<dcs-hosted-guidance-page>/...?token=<one-time-token>"
}
```

> On failure, `messageDetail` may come back in this shape (every sub-field is a string):
> `{ "message": "...", "title": "...", "type": "...", "icon": "...", "action": "...", "linkTitle": "...", "linkUrl": "..." }`

Redirect the user to the link in `data` and they land on the DCS-hosted PIN page.

## The full PIN-setting sequence

<Frame>
  <img className="block dark:hidden" src="https://mintcdn.com/dcs-0bf7a937/oUoeUKtwWWK2o-Li/imgs/en/diagrams/va-pin-setup-light.svg?fit=max&auto=format&n=oUoeUKtwWWK2o-Li&q=85&s=951208cb1f771f0bcc5af205697882ad" alt="The full sequence for setting a PIN" width="560" height="474" data-path="imgs/en/diagrams/va-pin-setup-light.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/dcs-0bf7a937/oUoeUKtwWWK2o-Li/imgs/en/diagrams/va-pin-setup-dark.svg?fit=max&auto=format&n=oUoeUKtwWWK2o-Li&q=85&s=f813f7a66d5ab2fb48bdf8b33bcfa559" alt="The full sequence for setting a PIN" width="560" height="474" data-path="imgs/en/diagrams/va-pin-setup-dark.svg" />
</Frame>

### Screenshots of the H5 PIN page

Once the user follows the guidance link, they set the PIN inside the DCS-hosted page. The flow looks like this (`action=UPDATE_PIN`):

<Columns cols={4}>
  <Frame>
    <img src="https://mintcdn.com/dcs-0bf7a937/U5My61eeN1_eDSDM/imgs/en/resetPin1.png?fit=max&auto=format&n=U5My61eeN1_eDSDM&q=85&s=fe2126410c4e575f3deb317e190ecbc9" width="246" height="538" data-path="imgs/en/resetPin1.png" />
  </Frame>

  <Frame>
    <img src="https://mintcdn.com/dcs-0bf7a937/U5My61eeN1_eDSDM/imgs/en/resetPin2.png?fit=max&auto=format&n=U5My61eeN1_eDSDM&q=85&s=af40e0ca9d9a70a6c6fc7fdd49b3bce4" width="248" height="538" data-path="imgs/en/resetPin2.png" />
  </Frame>

  <Frame>
    <img src="https://mintcdn.com/dcs-0bf7a937/U5My61eeN1_eDSDM/imgs/en/resetPin3.png?fit=max&auto=format&n=U5My61eeN1_eDSDM&q=85&s=6ab2b37f1939b3adfa5ed1565132e84e" width="247" height="538" data-path="imgs/en/resetPin3.png" />
  </Frame>

  <Frame>
    <img src="https://mintcdn.com/dcs-0bf7a937/U5My61eeN1_eDSDM/imgs/en/resetPin4.png?fit=max&auto=format&n=U5My61eeN1_eDSDM&q=85&s=4ba8ae6143d7e0e3853869a00fe0fe9b" width="248" height="538" data-path="imgs/en/resetPin4.png" />
  </Frame>
</Columns>

## Error handling

| Situation                                              | What to do                                                                                                                                  |
| :----------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ |
| `code` in the response is not `SYS_SUCCESS`            | Follow the hint in `message` and check your parameters (`action`, `cardId`, and whether both redirect URLs are present and valid)           |
| The user fails to set a PIN inside the page            | The DCS guidance page redirects them to `errorRedirectUrl`; offer a retry entry point on that page, which can request a fresh guidance link |
| The guidance link has expired or has already been used | Guidance links are single-use; call the endpoint again to obtain a new one                                                                  |

> Whether the PIN was set successfully is determined by which URL the guidance page redirects to, `successRedirectUrl` or `errorRedirectUrl`. If you need server-side asynchronous confirmation, see the card events in [Webhook + WebSocket notifications](../../integration-resources/webhook-websocket).

## About PIN rules

PIN complexity and length rules (permitted number of digits, whether simple sequences or repeated digits are rejected, and so on) are enforced inside the DCS-hosted guidance page and are transparent to the partner, so you do not need to reimplement the validation in your own system. If the user enters a PIN that breaks the rules, the page tells them straight away and asks for another.

## Next steps

* [Managing Cards · Overview](./overview) — freezing and unfreezing, card replacement, the state machine
* [H5 KYC / Card Application Guidance Page](../../integration-resources/h5-kyc-guidance) — the complete guidance page parameters and redirect mechanics
* [Viewing Encrypted Card Details](./viewing-encrypted-card-details) — also delivered through a guidance page (`action = CARD_INFO`)
