> ## 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.

# Authentication Guide

> This is the entry point for Integration Resources and the authoritative page on authentication: it covers API Key / Secret Key management and HMAC-SHA256 request signing end to end. Standalone capabilities such as IP whitelisting and the SessionId public key are covered in the sub-pages of this group.

Whether you are an exchange, a wallet or a platform, once DCS has issued you a key pair you can call every **DeCard-Managed** API with a single, uniform signing rule. This page gets authentication working in one pass. As a licensed issuer with its own BINs, DCS requires a verifiable request origin and replay protection on every API call.

<Note>
  Naming note: this documentation set covers the **DeCard-Managed** integration model, previously called the standard-authorization model. In this model DCS maintains a dedicated fiat / digital-asset account and balance for each user, and **no on-chain collateral is involved**.
</Note>

***

## What is in this group

Integration Resources brings together every technical asset and security credential you need, from integration development through to production go-live:

| Sub-page                                                     | Purpose                                                                                                                 |
| :----------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------- |
| **Authentication Guide (this page)**                         | API Key / Secret Key management and HMAC-SHA256 request signing                                                         |
| **[IP Whitelisting](./ip-whitelisting)**                     | Register your network egress addresses with DCS, both for API access and for secure retrieval of production credentials |
| **[SessionId Public Key / Encryption](./sessionid-keys)**    | The encryption and signing capabilities actually available in the DeCard-Managed model                                  |
| **[H5 KYC / Card Application Journey](./h5-kyc-guidance)**   | The embedded H5 flow for KYC and card application                                                                       |
| **[Web SDK Integration](../sdk/web-sdk)**                    | Front-end integration SDK                                                                                               |
| **[Webhook + WebSocket Notifications](./webhook-websocket)** | Event callbacks (Webhook) and **real-time WebSocket push** (a DeCard-Managed differentiator)                            |

## 1. Credentials and Request Headers

### What DCS gives you

| Field       | Description                                                                                              | Provided by |
| :---------- | :------------------------------------------------------------------------------------------------------- | :---------- |
| `apiKey`    | Globally unique identifier for API calls, used for identification and request-origin tracing             | DCS         |
| `secretKey` | The key used to compute the request signature. **Keep it safe and never disclose it to any third party** | DCS         |

The `apiKey` is a globally unique identifier that supports identification and analytics. To stop anyone else from issuing requests under your `apiKey`, it must be paired with the `secretKey`: you generate a signature according to the agreed rules and submit it alongside the request for DCS to verify. DCS delivers this key pair to you privately, and every API call a partner makes must follow the agreed signing protocol.

> For sandbox `apiKey`/`secretKey`, contact the DCS team. Production credentials must be obtained through [Secure Retrieval of Production Credentials](#3-secure-retrieval-of-production-credentials).

### Headers required on every request

Every API call from a partner must carry the following HTTP headers:

| Header             | Required | Description                                                                                                                       |
| :----------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------- |
| `Content-Type`     | REQUIRED | Fixed to `application/json` when the request body is JSON. If absent, DCS returns HTTP 400 with business code `SYS_ILLEGAL_PARAM` |
| `X-DAPI-API-KEY`   | REQUIRED | The `apiKey` issued by DCS                                                                                                        |
| `X-DAPI-TIMESTAMP` | REQUIRED | Request timestamp in milliseconds, used for replay protection                                                                     |
| `X-DAPI-NONCE`     | REQUIRED | Random number in the range `[10000, 99999]`, making each request single-use                                                       |
| `X-DAPI-SIGN`      | REQUIRED | The HMAC-SHA256 signature computed as described below (lowercase hexadecimal)                                                     |

<Note>
  the `secretKey` is used only to compute the signature locally. **Never** transmit it in a request header.
</Note>

Typical response when `Content-Type: application/json` is missing:

```json theme={null}
{"code":"SYS_ILLEGAL_PARAM","message":"illegal param","messageDetail":null,"data":null,"success":false}
```

> This `success=false` comes from the framework-level error response triggered by the missing Content-Type; it does not mean that every business response reliably includes `success`. In normal integration, always decide success or failure from `code` and do not depend on the `success` field.

***

## 2. Request Signing (HMAC-SHA256)

### Signing rule

Sign the concatenated string using the **HmacSHA256** algorithm with the `secretKey` as the key:

```
X-DAPI-SIGN = HmacSHA256( apiKey + timestamp + nonce + payload , secretKey )
```

The output is a lowercase hexadecimal string.

**The segments of the concatenated string:**

| Segment     | Value                                                                                       |
| :---------- | :------------------------------------------------------------------------------------------ |
| `apiKey`    | Same as `X-DAPI-API-KEY`                                                                    |
| `timestamp` | Same as `X-DAPI-TIMESTAMP` (millisecond timestamp)                                          |
| `nonce`     | Same as `X-DAPI-NONCE`                                                                      |
| `payload`   | **GET** requests: the URL-encoded query string; **all other methods**: the raw request body |

```text theme={null}
if method is GET:
    payload = url.encodedQuery()     // e.g. externalUserId=<externalUserId>&cardMantissa=1670
else:
    payload = body                   // the raw JSON request body string
```

> The signing algorithm is fixed to HmacSHA256. Always use this algorithm.

### Replay protection (DCS verifies, the partner generates)

* **TIMESTAMP**: must be a **13-digit millisecond timestamp** (for example `Date.now()`, not a 10-digit second timestamp). A malformed value returns `DAPI_TIMESTAMP_FORMAT_ERROR`. DCS only accepts requests within a **5-second validity window**; beyond that it returns `DAPI_TIMESTAMP_EXPIRED`, so regenerate the timestamp from the current time, recompute the signature, and keep your local clock in sync.
* **NONCE**: generate a fresh random number in `[10000, 99999]` for every request so that each request is valid only once. Do not reuse nonces.

> If authentication fails, check the timestamp, the nonce and the string you signed first. For exact error codes, rely on what the API actually returns and on the dictionary DCS provides for this product.

### Signing examples

**JavaScript (Postman pre-request script)**

```javascript theme={null}
const CryptoJS = require('crypto-js');

const apiSecret = '<your-secret-key>';
const apiKey    = '<your-api-key>';

// GET uses the query string; other methods use the request body. Concatenate whichever applies
const queryParams  = '<your-query-param>';   // e.g. externalUserId=<externalUserId>&cardMantissa=1670
const requestBody  = '<your-request-body>';  // the raw body for POST/PUT
const nonce        = 10010;
const timestamp    = Date.now().toString();

const dataToSign = apiKey + timestamp + nonce + queryParams + requestBody;
const signature  = CryptoJS.HmacSHA256(dataToSign, apiSecret).toString(CryptoJS.enc.Hex);
```

**Java**

```java theme={null}
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;

public final class HmacSignature {
    private static final String HMAC_SHA256 = "HmacSHA256";

    public static String getSignature(String apiSecret, String data) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(apiSecret.getBytes(), HMAC_SHA256);
        Mac mac = Mac.getInstance(HMAC_SHA256);
        mac.init(keySpec);
        byte[] hmac = mac.doFinal(data.getBytes());
        return Hex.encodeHexString(hmac);
    }
}
```

### Full request example (GET)

```bash theme={null}
curl --location 'https://{domain}/card/v2/detail?externalUserId=<externalUserId>&cardId=<cardId>' \
  --header 'Content-Type: application/json' \
  --header 'X-DAPI-API-KEY: <your-api-key>' \
  --header 'X-DAPI-SIGN: <calculated-signature>' \
  --header 'X-DAPI-TIMESTAMP: <millis-timestamp>' \
  --header 'X-DAPI-NONCE: <random-10000-99999>'
```

> In this example `payload = externalUserId=<externalUserId>&cardId=<cardId>`, the GET query string. To validate your implementation before go-live, take the same `apiKey/timestamp/nonce/payload` set that DCS provides and confirm you reproduce the identical `X-DAPI-SIGN`.

<Warning>
  Every `externalUserId`, `apiKey`, `X-DAPI-SIGN`, `TIMESTAMP` and `NONCE` in the examples is a placeholder and must not be treated as a real value. The DeCard-Managed model handles a large volume of end-user personal data, so debug logs must not record real credentials or PII either.
</Warning>

### Common response envelope

Every API returns the same envelope:

```json theme={null}
{
  "code": "SYS_SUCCESS",
  "message": "",
  "messageDetail": {
    "message": "",
    "title": "",
    "type": "",
    "icon": "",
    "action": "",
    "linkTitle": "",
    "linkUrl": ""
  },
  "data": ""
}
```

| Field           | Type   | Description                                                                                                                                                                                                                                                                   |
| :-------------- | :----- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `code`          | string | Business status code. `SYS_SUCCESS` on success, a specific error code on failure                                                                                                                                                                                              |
| `message`       | string | Short message, normally empty on success                                                                                                                                                                                                                                      |
| `messageDetail` | object | Structured display object containing `message` / `title` / `type` / `icon` / `action` / `linkTitle` / `linkUrl`, usable for front-end prompts. Its fields are normally empty on success. **Do not use it to decide success or failure**; always judge the outcome from `code` |
| `data`          | object | The business payload                                                                                                                                                                                                                                                          |

> Treat `code == "SYS_SUCCESS"` as the sole success condition. The response envelope does **not** include a `success` boolean, so do not depend on that field.

***

## 3. Secure Retrieval of Production Credentials

To keep production `apiKey`/`secretKey` from leaking in transit, **production credentials are never sent to you directly**. They are collected through a one-time secure retrieval flow.

> The sandbox environment does not need this flow; simply contact the DCS team.

### The flow (and who does what)

1. **The partner provides**: one secure email address plus one source IP for retrieval.
   * The email address receives the retrieval instructions; the IP is added to the credential-retrieval whitelist.
2. **DCS sends**: an email to that secure address containing a temporary secure link that is valid for **one use only**.
3. **The partner retrieves**: concatenate `extractUrl` with `extractSecretKey` and **run it from the machine at the registered IP** to receive the `apiKey`/`secretKey`.

### Fields in the email

| Field              | Type   | Description                                               |
| :----------------- | :----- | :-------------------------------------------------------- |
| `expireTime`       | string | Validity period of the retrieval security code            |
| `extractSecretKey` | string | Credential-retrieval security code                        |
| `extractUrl`       | string | Credential-retrieval URL                                  |
| `howToUse`         | string | Usage instructions                                        |
| `notes`            | string | Reminder that the link can be used for one retrieval only |

**Success response**

```json theme={null}
{
  "code": "SYS_SUCCESS",
  "message": null,
  "messageDetail": null,
  "data": {
    "expireTime": "2024-10-21T16:52+08:00[Asia/Shanghai]",
    "extractSecretKey": "<one-time-extract-secret>",
    "extractUrl": "https://{domain}/internal/open-api/v1/secret-extract/",
    "howToUse": "Please concatenate the url with the secret-key and execute it on the specified machine.",
    "notes": "This link is only valid for one AKSK extraction, if the content is not properly accessed, the AKSK may have been compromised, please contact us promptly."
  }
}
```

**Failure response**

```json theme={null}
{
  "code": "ERROR-CODE",
  "message": "simple describe, see error-code list",
  "messageDetail": null,
  "data": null
}
```

> Only the failure envelope is shown here. For exact error codes, rely on what the API actually returns and on the dictionary DCS provides for this product; this version does not reuse error-code tables from other products.

<Warning>
  **If retrieval fails**: the link may already have been used inside its validity window, which means the credentials could be compromised. Contact your DCS business contact immediately and repeat the email flow to have them reissued.

  The retrieval IP does not have to be the same as your day-to-day API calling IP; declare each purpose to DCS separately. For how to submit them, see [IP Whitelisting](./ip-whitelisting).
</Warning>

***

## Next steps / Related

With authentication working, go to [Quickstart](../getting-started/quickstart) to issue your first card, or start from [First Steps](../getting-started/first-steps) to confirm that your account and callbacks are ready.

The remaining technical assets in Integration Resources:

* **[IP Whitelisting](./ip-whitelisting)**: register your network egress addresses with DCS, both for API access and for secure retrieval of production credentials.
* **[SessionId Public Key / Encryption](./sessionid-keys)**: the encryption and signing capabilities actually available in the DeCard-Managed model.
* **[H5 KYC / Card Application Journey](./h5-kyc-guidance)**: the embedded flow for KYC and card application.
* **[Web SDK Integration](../sdk/web-sdk)**: front-end integration SDK.
* **[Webhook + WebSocket Notifications](./webhook-websocket)**: event callbacks (Webhook) and **real-time WebSocket push** (a DeCard-Managed differentiator).
