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

# Sdk

# TumiPay Cards JS

JavaScript/TypeScript SDK for secure credit and debit card tokenization.

## Installation

```bash theme={null}
npm install tumipay-cards-js
```

## Quick Start

```typescript theme={null}
import { TumiPayCardPaymentSDK } from 'tumipay-cards-js';

const sdk = new TumiPayCardPaymentSDK({
  environment: 'staging',
  currency: 'COP',
});

await sdk.initialize({ merchantId: 'your-merchant-id' });

const validation = sdk.validateCard({
  cardNumber: '4111111111111111',
  cardHolderName: 'John Doe',
  expirationMonth: '12',
  expirationYear: '29',
  cvv: '123',
});

if (validation.status) {
  const tokenResult = await sdk.generateSubscriptionToken({
    cardNumber: '4111111111111111',
    cardHolderName: 'John Doe',
    expirationMonth: '12',
    expirationYear: '29',
    cvv: '123',
  });
  // tokenResult.data.token → subscription token
}
```

***

## Standard Response

All methods return the same envelope:

```typescript theme={null}
{
  code: string;      // "SUCCESS" or error code
  status: boolean;   // true = success
  message: string;   // Human-readable description
  data?: T;          // Payload (when status is true)
  errors?: Array<{   // Only in validateCard when status is false
    code: string;
    field: string;
    message: string;
  }>;
}
```

***

## Constructor

```typescript theme={null}
new TumiPayCardPaymentSDK({
  environment: 'staging' | 'production',
  currency: string,   // e.g. "COP", "USD"
})
```

Does not make network calls. Only configures the instance.

***

## `initialize({ merchantId })`

Fetches merchant configuration from the TumiPay server and prepares the SDK for operation.

**Must be called before** `generateSubscriptionToken` and `getBinInfo`.

```typescript theme={null}
const result = await sdk.initialize({ merchantId: 'your-merchant-id' });
```

### Response

```json theme={null}
{
  "initialized": true,
  "code": "SUCCESS",
  "status": true,
  "message": "Configuración obtenida correctamente",
  "data": {
    "payment_provider": {
      "external_merchant_id": "1c038e84ed014abb94eb229447f3684d",
      "public_key": "e7c352d9a067475f90bfd92301265efe",
      "environment": "uat"
    },
    "otp_config": {
      "id_credentials": "9c642a3e5034468693fbf2830146c08c",
      "public_key": "55ced6048f19446aa0f0ae26dcf10abf",
      "private_key": "6aaa48606fde4a10aef6833627c9677f"
    }
  }
}
```

### Error Codes

| Code                      | Description                                  | How to Fix                                                     |
| ------------------------- | -------------------------------------------- | -------------------------------------------------------------- |
| `INVALID_MERCHANT_ID`     | `merchantId` is empty or not provided        | Ensure a valid `merchantId` is passed                          |
| `APP_CONFIGURATION_ERROR` | Failed to retrieve configuration from server | Check connectivity and that the `merchantId` exists in TumiPay |
| `SDK_INIT_ERROR`          | Generic initialization error                 | Check the error message for more details                       |

***

## `validateCard(request)`

Validates card data **locally** — no network calls. Does not require initialization.

### Parameters

| Field             | Type     | Required | Description                         |
| ----------------- | -------- | -------- | ----------------------------------- |
| `cardNumber`      | `string` | ✅        | Card number (13–19 digits)          |
| `cardHolderName`  | `string` | ✅        | Cardholder name (min. 2 characters) |
| `expirationMonth` | `string` | ✅        | Expiry month: `"01"`–`"12"`         |
| `expirationYear`  | `string` | ✅        | Expiry year: `"YY"` or `"YYYY"`     |
| `cvv`             | `string` | ✅        | CVV: 3 digits (4 for Amex)          |

### Response — success

```json theme={null}
{
  "code": "SUCCESS",
  "status": true,
  "message": "Tarjeta válida",
  "data": {
    "bin": "411111",
    "brand": "visa",
    "lastFourDigits": "1111",
    "maskedCard": "****1111"
  }
}
```

### Response — validation error

```json theme={null}
{
  "code": "CARD_EXPIRED",
  "status": false,
  "message": "La validación de la tarjeta falló",
  "errors": [
    { "code": "CARD_EXPIRED", "field": "expiration", "message": "La tarjeta ha expirado" }
  ]
}
```

### Supported Brands

| Brand        | Pattern                                          |
| ------------ | ------------------------------------------------ |
| `visa`       | Starts with `4`, 13–16 digits                    |
| `mastercard` | Starts with `51`–`55`, 16 digits                 |
| `amex`       | Starts with `34` or `37`, 15 digits              |
| `discover`   | Starts with `6011` or `65`, 16 digits            |
| `diners`     | Starts with `300`–`305`, `36` or `38`, 14 digits |
| `jcb`        | Starts with `2131`, `1800` or `35`, 15–16 digits |

### Error Codes

| Code                         | Field             | Description                    | How to Fix                                          |
| ---------------------------- | ----------------- | ------------------------------ | --------------------------------------------------- |
| `CARD_NUMBER_EMPTY`          | `cardNumber`      | Card number is empty           | Provide the card number                             |
| `CARD_NUMBER_INVALID_FORMAT` | `cardNumber`      | Non-numeric characters found   | Use digits only, no spaces or dashes                |
| `CARD_NUMBER_INVALID_LENGTH` | `cardNumber`      | Length outside 13–19 range     | Verify the full card number is entered              |
| `CARD_NUMBER_LUHN_FAILED`    | `cardNumber`      | Fails Luhn algorithm           | The card number is invalid; double-check it         |
| `CARDHOLDER_NAME_EMPTY`      | `cardHolderName`  | Cardholder name is empty       | Provide the name as shown on the card               |
| `CARDHOLDER_NAME_TOO_SHORT`  | `cardHolderName`  | Name shorter than 2 characters | Enter the cardholder's full name                    |
| `EXPIRY_MONTH_INVALID`       | `expirationMonth` | Month outside 01–12            | Use format `"01"` to `"12"`                         |
| `EXPIRY_YEAR_INVALID`        | `expirationYear`  | Year not provided              | Provide the expiration year                         |
| `CARD_EXPIRED`               | `expiration`      | Card is expired                | Use a card with a valid expiration date             |
| `CVV_EMPTY`                  | `cvv`             | CVV is empty                   | Provide the security code                           |
| `CVV_INVALID_LENGTH`         | `cvv`             | CVV has wrong length           | Use 3 digits (4 for American Express)               |
| `BRAND_NOT_ALLOWED`          | `cardNumber`      | Unsupported card brand         | Use Visa, Mastercard, Amex, Discover, Diners or JCB |

***

## `generateSubscriptionToken(card)`

Generates a subscription token via Kushki. **Requires prior initialization.**

Kushki credentials are sourced automatically from the context loaded in `initialize()`.

### Parameters

| Field             | Type     | Required | Description                                          |
| ----------------- | -------- | -------- | ---------------------------------------------------- |
| `cardNumber`      | `string` | ✅        | Card number                                          |
| `cardHolderName`  | `string` | ✅        | Cardholder name                                      |
| `expirationMonth` | `string` | ✅        | Expiry month                                         |
| `expirationYear`  | `string` | ✅        | Expiry year                                          |
| `cvv`             | `string` | ✅        | CVV                                                  |
| `documentNumber`  | `string` | ➖        | Document number (optional, required in some markets) |
| `email`           | `string` | ➖        | Email address (optional)                             |

### Response

```json theme={null}
{
  "code": "SUCCESS",
  "status": true,
  "message": "Token de suscripción generado correctamente",
  "data": {
    "token": "2da0dd03c6e54ebd80b1a09a2d17ea9e"
  }
}
```

### Error Codes

| Code                  | Description                                    | How to Fix                                               |
| --------------------- | ---------------------------------------------- | -------------------------------------------------------- |
| `SDK_NOT_INITIALIZED` | `initialize()` was not called first            | Call `sdk.initialize({ merchantId })` before this method |
| `MISSING_PUBLIC_KEY`  | `public_key` missing in configuration response | Verify the merchant has a payment provider configured    |
| `MISSING_CURRENCY`    | `currency` not set in constructor              | Pass `currency` when creating the SDK instance           |

***

## `getBinInfo(bin)`

Fetches bank, brand, and card type from Kushki. **Requires prior initialization.**

```typescript theme={null}
const result = await sdk.getBinInfo('411111');
```

### Parameters

| Field | Type     | Required | Description                                        |
| ----- | -------- | -------- | -------------------------------------------------- |
| `bin` | `string` | ✅        | First 6 digits of the card number (or full number) |

### Response

```json theme={null}
{
  "code": "SUCCESS",
  "status": true,
  "message": "Información de BIN obtenida correctamente",
  "data": {
    "brand": "visa",
    "bank": "JPMORGAN CHASE BANK, N.A.",
    "cardType": "credit"
  }
}
```

### Error Codes

| Code                  | Description                         | How to Fix                                               |
| --------------------- | ----------------------------------- | -------------------------------------------------------- |
| `SDK_NOT_INITIALIZED` | `initialize()` was not called first | Call `sdk.initialize({ merchantId })` before this method |
| `INVALID_BIN`         | BIN has fewer than 6 digits         | Provide at least the first 6 digits of the card number   |

***

## Helper Methods

```typescript theme={null}
sdk.isInitialized()  // boolean — true if initialize() succeeded
sdk.getConfig()      // { environment, currency }
```

***

## TypeScript Types

```typescript theme={null}
import type {
  SdkConfig,
  SdkInitOptions,
  SdkInitializationResult,
  ValidateCardRequest,
  ValidateCardResult,
  ValidateCardError,
  ValidateCardSuccessData,
  GenerateTokenResult,
  GetBinInfoResult,
} from 'tumipay-cards-js';
```

***

## Utility Functions

```typescript theme={null}
import {
  validateCardNumber,
  validateCard,
  detectCardBrand,
  getCardBrand,
  luhnCheck,
  formatCardNumber,
  formatExpiry,
  maskCardNumber,
  ALLOWED_CARD_BRANDS,
} from 'tumipay-cards-js';
```
