> For the complete documentation index, see [llms.txt](https://developers.doku.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.doku.com/accept-payments/direct-api/non-snap/cards/tokenization.md).

# Tokenization

Want to make your checkout experience faster? You can combine this integration with the Tokenization, so the next time your customers purchase, they don't need to input the credit card anymore.

* Tokenization

### Get Token List

If you've previously made payment and you or your customer choose to save the credit card info\
You may use this Get Token List API show the saved card of your customers.\
this API can be used to obtain token from other payment method such as OVO, BRI Direct Debit, Allobank, etc that also uses tokenization feature.

| Type                          | Value                                                    |
| ----------------------------- | -------------------------------------------------------- |
| **HTTP Method**               | POST                                                     |
| **API endpoint (Sandbox)**    | `https://api-sandbox.doku.com/tokenization/v2/get-token` |
| **API endpoint (Production)** | `https://api.doku.com/tokenization/v2/get-token`         |

## Get Token List

> Returns all active tokens for a customer.<br>

```json
{"openapi":"3.1.0","info":{"title":"Tokenization Core System — Get Token","version":"1.0.0"},"servers":[{"url":"http://localhost:8080","description":"Local"}],"paths":{"/tokenization/v2/get-token":{"post":{"operationId":"tokenizationV3GetTokenPost","summary":"Get Token List","description":"Returns all active tokens for a customer.\n","tags":["Token Management"],"parameters":[{"name":"Client-Id","in":"header","required":true,"description":"Merchant client identifier issued by DOKU","schema":{"type":"string"}},{"name":"Accept","in":"header","required":true,"description":"Must be `application/json`","schema":{"type":"string","default":"application/json"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTokenRequest"}}}},"responses":{"200":{"description":"Token list retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTokenResponse"}}}},"400":{"description":"Bad request.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDTO"}}}},"500":{"description":"Internal server error — e.g., decryption failure or downstream service error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDTO"}}}}}}}},"components":{"schemas":{"GetTokenRequest":{"type":"object","required":["customer"],"properties":{"customer":{"type":"object","required":["id"],"description":"Customer identification","properties":{"id":{"type":"string","description":"Merchant customer identifier. Must not be blank."}}},"channel":{"type":"object","description":"Optional channel filter. Omit to return tokens across all channels.","properties":{"id":{"type":"string","enum":["CREDIT_CARD","DIRECT_DEBIT","EMONEY","KARTU_KREDIT_INDONESIA"],"description":"Payment channel identifier"}}},"issuer":{"type":"object","description":"Optional issuer filter.","properties":{"id":{"type":"string","description":"Issuer identifier (e.g., bank code or e-wallet name)"}}}}},"GetTokenResponse":{"type":"object","description":"List of active tokens for the customer","properties":{"customer":{"type":"object","description":"Echoes back the resolved customer identifier","properties":{"id":{"type":"string","description":"Merchant customer identifier"}}},"tokens":{"type":"array","description":"List of active tokens. Each item is one of:\n- `TokenCC` — for `CREDIT_CARD` channel\n- `Token` — for `DIRECT_DEBIT`, `EMONEY`, and `KARTU_KREDIT_INDONESIA` channels\n","items":{"oneOf":[{"$ref":"#/components/schemas/TokenCC"},{"$ref":"#/components/schemas/Token"}]}}}},"TokenCC":{"type":"object","description":"Credit card network token. Always returned for CREDIT_CARD channel.\n`metadata` is null when VTS metadata is not available for this token.\nFields with null values are omitted from the response (`@JsonInclude(NON_NULL)`).\n","properties":{"id":{"type":"string","description":"Token identifier (Visa network token value stored as gateway token ID)"},"masked_account":{"type":"string","description":"Masked PAN. First 6 and last 4 digits visible, middle masked (e.g., `411111xxxxxx1111`)."},"metadata":{"nullable":true,"description":"VTS card metadata. Null when VTS has not enrolled this PAN or metadata retrieval failed.\nContains VTS provisioned token IDs, card display metadata (colors, issuer contact), and PAN status.\n","allOf":[{"$ref":"#/components/schemas/VtsCardMetadata"}]},"card":{"$ref":"#/components/schemas/TokenCCCard"}}},"VtsCardMetadata":{"type":"object","description":"Subset of VTS GetCardMetadata response stored against the token","properties":{"vPanEnrollmentID":{"type":"string","description":"VTS PAN enrollment identifier"},"status":{"type":"string","description":"Overall VTS enrollment status for this PAN"},"paymentInstrument":{"type":"object","description":"Payment instrument details from VTS","properties":{"last4":{"type":"string","description":"Last 4 digits of the PAN"},"expirationDate":{"type":"object","properties":{"month":{"type":"string"},"year":{"type":"string"}}},"paymentAccountReference":{"type":"string","description":"Payment Account Reference (PAR)"}}},"tokens":{"type":"array","description":"VTS provisioned token entries for this PAN","items":{"type":"object","properties":{"vProvisionedTokenID":{"type":"string","description":"VTS Provisioned Token ID"},"tokenStatus":{"type":"string","description":"VTS token status (e.g., ACTIVE, INACTIVE, SUSPENDED)"}}}},"cardMetaData":{"type":"object","description":"Card display metadata (branding colors, issuer contact information)","properties":{"backgroundColor":{"type":"string"},"foregroundColor":{"type":"string"},"labelColor":{"type":"string"},"contactWebsite":{"type":"string"},"contactEmail":{"type":"string"},"contactNumber":{"type":"string"},"contactName":{"type":"string"},"shortDescription":{"type":"string"}}}}},"TokenCCCard":{"type":"object","description":"Card details attached to a credit card token","properties":{"name":{"type":"string","description":"Cardholder name"},"expiry":{"type":"string","description":"Masked expiry date. Month is visible, year is masked (e.g., `12/**`)."},"bin":{"type":"string","description":"Bank Identification Number — first 6–8 digits of the PAN"},"brand":{"type":"string","description":"Card network brand"},"issuer":{"type":"string","description":"Card-issuing bank name"},"country":{"type":"string","description":"Card country code (ISO 3166-1 alpha-2)"},"encrypted_expiry":{"type":"string","description":"AU-Sec encrypted expiry date (original encrypted value from provisioning)"},"hashed_card_number":{"type":"string","description":"HMAC-SHA512 of the plaintext card number, keyed with merchant-specific secret. Empty string if hashing fails."},"payer_account_id":{"type":"string","description":"Same value as `hashed_card_number`. Used as the VTS Payer Account ID."}}},"Token":{"type":"object","description":"Token for non-credit-card channels (DIRECT_DEBIT, EMONEY, KARTU_KREDIT_INDONESIA).\n- `auth_code` is present only for DIRECT_DEBIT.\n- `encrypted_card_number` is present only for KARTU_KREDIT_INDONESIA.\nFields with null values are omitted from the response (`@JsonInclude(NON_NULL)`).\n","properties":{"id":{"type":"string","description":"Token identifier (SHA-512 hash stored as the gateway token)"},"masked_account":{"type":"string","description":"Masked account number. Format depends on channel:\n- DIRECT_DEBIT / EMONEY: first 6 digits visible, last 4 visible, middle masked (e.g., `123456xxxxxx7890`)\n- KARTU_KREDIT_INDONESIA: same masking pattern\n"},"auth_code":{"type":"string","nullable":true,"description":"Authorization code — 40-character string. Present for DIRECT_DEBIT only."},"encrypted_card_number":{"type":"string","nullable":true,"description":"AU-Sec encrypted card number. Present for KARTU_KREDIT_INDONESIA only."}}},"ErrorDTO":{"type":"object","description":"Standard error response envelope","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Machine-readable error code:\n- `INVALID_PARAMETER` — request validation failure (blank customer.id, invalid channel)\n- `data_not_found` — merchant / customer / tokens not found\n- `INTERNAL_SERVICE_ERROR` — decryption or downstream service failure\n"},"type":{"type":"string","description":"Error category returned by the service"},"message":{"type":"string","description":"Human-readable error message"}}}}}}}}
```

### Unbind Token

If you want to unbind the token, you can use the delete tokenization API below :

**API Request**

| Type                          | Value                                                       |
| ----------------------------- | ----------------------------------------------------------- |
| **HTTP Method**               | POST                                                        |
| **API endpoint (Sandbox)**    | `https://api-sandbox.doku.com`/tokenization/v2/delete-token |
| **API endpoint (Production)** | `https://api.doku.com`/tokenization/v2/delete-token         |

Here is the sample of request header to capture the transaction:

```
Client-Id: MCH-0001-10791114622547
Request-Id: 071a6a32-6785-4011-833d-d2c2049cf744
Request-Timestamp: 2021-08-24T08:46:42Z
Signature: HMACSHA256=9UPUFzOqJc47aJzD9ESOTcWg6TMsg3mqSP+DnUO8ENE=
```

Request Header Explanation

| Parameter             | Description                                                                                                                                                                                                                                                                                                                                           |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Client-Id**         | Client ID retrieved from DOKU Back Office                                                                                                                                                                                                                                                                                                             |
| **Request-Id**        | Unique random string (max 128 characters) generated from merchant side to protect duplicate request                                                                                                                                                                                                                                                   |
| **Request-Timestamp** | Timestamp request on UTC time in ISO8601 UTC+0 format. It means to proceed transaction on UTC+7 (WIB), merchant need to subtract time with 7. Ex: to proceed transaction on September 22th 2020 at 08:51:00 WIB, the timestamp should be 2020-09-22T01:51:00Z                                                                                         |
| **Signature**         | Security parameter that needs to be generated on merchant Backend and placed to the header request to ensure that the request is coming from valid merchant. Please refer to [this section](https://developers.doku.com/getting-started-with-doku-api/signature-component/non-snap/signature-component-from-request-header) to generate the signature |

Here is the sample request body to unbind the token:

```
{
  "token": {
    "id": "gateway-token"
  }
}
```

Request Body Explanation

| Parameter  | Type     | Mandatory | Description                            |
| ---------- | -------- | --------- | -------------------------------------- |
| `token.id` | `string` | Mandatory | Token ID that want to unbind or delete |

**API Response**

After hitting the above API request, DOKU will give the response.

| Type            | Value   |
| --------------- | ------- |
| **HTTP Status** | 200     |
| **Result**      | SUCCESS |

Here is the sample response header:

```
Client-Id: MCH-0001-10791114622547
Request-Id: b266c265-3d61-4708-9860-c0d5b9a98f8c
Response-Timestamp: 2020-08-11T08:45:42Z
Signature: HMACSHA256=1jap2tpgvWt83tG4J7IhEwUrwmMt71OaIk0oL0e6sPM=
```

Response Header Explanation

| Parameter              | Description                                                   |
| ---------------------- | ------------------------------------------------------------- |
| **Client-Id**          | Same as the request                                           |
| **Request-Id**         | Same as the request                                           |
| **Response-Timestamp** | Timestamp Response on UTC with format ISO8601 UTC+0 from DOKU |
| **Signature**          | Signature generated by DOKU based on the response body        |

Here is the sample of response body:

```json
{
  "token": {
    "id": "gateway-token",
    "status": "INACTIVE"
  }
}
```

Response Body Explanation

| Parameter      | Type     | Mandatory | Description                                                           |
| -------------- | -------- | --------- | --------------------------------------------------------------------- |
| `token.id`     | `string` | Mandatory | Token ID that want to unbind or delete                                |
| `token.status` | `string` | Mandatory | <p>Delete Process Status<br>Possible Value: <code>INACTIVE</code></p> |

{% hint style="info" %}
**Info**

To make sure the token has been unbinded, you can hit API Get token List.
{% endhint %}
