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

# JavaScript / TypeScript SDK

> Install and use the LigdiCash JavaScript SDK for Node.js, TypeScript, and NestJS. TypeScript types included.

The LigdiCash JavaScript SDK works in Node.js and TypeScript environments. Every network call is asynchronous (`async/await`). TypeScript types are bundled with the package.

## Installation

```bash theme={null}
npm install ligdicash
```

**Requirements**: Node.js. The `cross-fetch` dependency is installed automatically.

## Initialization

<CodeGroup>
  ```typescript TypeScript theme={null}
  import Ligdicash from "ligdicash";

  const client = new Ligdicash({
    apiKey: "{API_KEY}",
    authToken: "{AUTH_TOKEN}",
    platform: "live",
    baseUrl: "https://app.ligdicash.com",
  });
  ```

  ```javascript JavaScript (CommonJS) theme={null}
  const Ligdicash = require("ligdicash").default;

  const client = new Ligdicash({
    apiKey: "{API_KEY}",
    authToken: "{AUTH_TOKEN}",
    platform: "live",
    baseUrl: "https://app.ligdicash.com",
  });
  ```
</CodeGroup>

Get your `apiKey` and `authToken` from the [LigdiCash dashboard](https://dashboard.ligdicash.com) by creating an API project.

***

## Hosted payin

The customer is redirected to the LigdiCash-hosted payment page. This is the recommended flow for online stores.

```typescript TypeScript theme={null}
// 1. Create the invoice
const invoice = client.Invoice({
  currency: "xof",
  description: "Order #ORD-20240512",
  customer_firstname: "Amadou",
  customer_lastname: "Ouedraogo",
  customer_email: "amadou@example.com",
  store_name: "MySuperStore",
  store_website_url: "https://mysuperstore.com",
});

// 2. Add items
invoice.addItem({ name: "Kente shirt", description: "Size M", quantity: 2, unit_price: 15000 });
invoice.addItem({ name: "Shipping fee", description: "", quantity: 1, unit_price: 1500 });

// 3. Start the payment
const response = await invoice.payWithRedirection({
  return_url: "https://mysuperstore.com/order/success",
  cancel_url: "https://mysuperstore.com/order/cancel",
  callback_url: "https://backend.mysuperstore.com/ligdicash/callback",
  custom_data: { transaction_id: "ORD-20240512" },
});

// 4. Redirect the customer
const paymentUrl = response.response_text;
```

<Warning>
  Every network call (`payWithRedirection`, `payWithoutRedirection`, `send`, `getTransaction`) returns a `Promise`. A missing `await` causes a silent comparison against a `Promise` object instead of the real result.
</Warning>

<Warning>
  Never open `paymentUrl` in an iframe — LigdiCash blocks it. Redirect in the same tab, a new tab, or a popup. On native mobile, use a WebView.
</Warning>

<Tip>
  **Popup pattern that bypasses blockers:** open `window.open("about:blank")` on the user click (before the `await`), then navigate to `paymentUrl` once the response is received. This sidesteps browser popup blockers.
</Tip>

***

## Direct payin

The customer pays directly from your interface. You must collect their phone number and, depending on the operator, their OTP code.

```typescript TypeScript theme={null}
// 1. Create the invoice
const invoice = client.Invoice({
  currency: "xof",
  description: "Order #ORD-20240512",
  customer_firstname: "Amadou",
  customer_lastname: "Ouedraogo",
  customer_email: "amadou@example.com",
  store_name: "MySuperStore",
  store_website_url: "https://mysuperstore.com",
});
invoice.addItem({ name: "Kente shirt", description: "Size M", quantity: 2, unit_price: 15000 });

// 2. Start the payment (with OTP provided by the customer)
const response = await invoice.payWithoutRedirection({
  otp: "123456",            // OTP code entered by the customer
  customer: "22670123456",  // Customer phone number, no + or spaces
  callback_url: "https://backend.mysuperstore.com/ligdicash/callback",
  custom_data: { transaction_id: "ORD-20240512" },
});

// 3. Store the token for later verification
const token = response.token;
```

<Note>
  The OTP mode varies by operator. For example, with a USSD operator, the customer generates the OTP on their phone **before** you submit. For an approval-mode operator (e.g. Moov Africa), send `otp: ""` — the customer approves directly in their app. See the [operator page](/en/payment-api/direct-payin/introduction) for details.
</Note>

***

## Payout

Send money to a customer — refund, salary, payout.

### To the customer's LigdiCash wallet

```typescript TypeScript theme={null}
const withdrawal = client.Withdrawal(5000, "Refund for order ORD-20240510", "22670123456");

const response = await withdrawal.send({
  type: "client",
  to_wallet: false,  // false = automatic transfer to the linked mobile money account
  callback_url: "https://backend.mysuperstore.com/ligdicash/callback-payout",
  custom_data: { transaction_id: "REFUND-20240512" },
});

const token = response.token;
```

### Directly to mobile money

```typescript TypeScript theme={null}
const response = await withdrawal.send({
  type: "merchant",  // Direct payout, no intermediate wallet
  callback_url: "https://backend.mysuperstore.com/ligdicash/callback-payout",
  custom_data: { transaction_id: "PAY-20240512" },
});
```

<Note>
  `type: "client"` uses `POST /pay/v01/withdrawal/create` (via the LigdiCash wallet). `type: "merchant"` uses `POST /pay/v01/straight/payout` (direct mobile money, slower). See [Payout — Introduction](/en/payment-api/payout/introduction).
</Note>

***

## Status verification

Call `getTransaction` with the token stored at **creation** (not the callback token, which is different).

```typescript TypeScript theme={null}
const token = "eyJ0eXAiOiJ...";  // Token returned at creation

// Payin
const transaction = await client.getTransaction(token, "payin");

// Client payout (withdrawal/create)
// const transaction = await client.getTransaction(token, "client_payout");

// Merchant payout (straight/payout)
// const transaction = await client.getTransaction(token, "merchant_payout");

if (transaction.status === "completed") {
  // Deliver the order / validate the payment
} else if (transaction.status === "pending") {
  // Payment in progress — retry in a few seconds
} else {
  // Payment failed or cancelled
}
```

**Fields available on `transaction`:**

| Property        | Type       | Description                               |
| --------------- | ---------- | ----------------------------------------- |
| `status`        | `string`   | `"completed"`, `"pending"`, `"cancelled"` |
| `response_code` | `string`   | `"00"` success, `"01"` failure            |
| `amount`        | `number`   | Transaction amount                        |
| `operator_id`   | `string`   | Operator identifier                       |
| `operator_name` | `string`   | Operator name                             |
| `customer`      | `string`   | Customer phone number                     |
| `token`         | `string`   | Transaction token                         |
| `custom_data`   | `object`   | Custom data sent at creation              |
| `wiki`          | `string[]` | Links to the endpoint's error codes       |

<Warning>
  Never deliver an order solely based on an incoming callback. Always call `getTransaction` with the token stored at creation to confirm the status on the LigdiCash server side. See [Callback security](/en/payment-api/callback/security).
</Warning>

***

## TypeScript types

The SDK exports the following types for your function signatures and interfaces:

```typescript TypeScript theme={null}
import type {
  InvoiceParam,
  InvoiceItemParam,
  PayWithRedirectionParam,
  PayWithoutRedirectionParam,
  BaseResponseType,
} from "ligdicash";
```

| Type                         | Use                                     |
| ---------------------------- | --------------------------------------- |
| `InvoiceParam`               | Parameters of the `Invoice` constructor |
| `InvoiceItemParam`           | Parameters of `addItem`                 |
| `PayWithRedirectionParam`    | Parameters of `payWithRedirection`      |
| `PayWithoutRedirectionParam` | Parameters of `payWithoutRedirection`   |
| `BaseResponseType`           | Response returned by payin/payout calls |

***

## Error handling

```typescript TypeScript theme={null}
try {
  const response = await invoice.payWithRedirection({
    return_url: "https://mysuperstore.com/success",
    cancel_url: "https://mysuperstore.com/cancel",
    callback_url: "https://backend.mysuperstore.com/callback",
    custom_data: { transaction_id: "ORD-20240512" },
  });
} catch (error) {
  // The SDK throws on HTTP errors or API errors
  console.error(error);
}
```

<Note>
  Also check `response.response_code` after every call: `"00"` indicates success, `"01"` an error. On error, read `response.wiki` to get the URL with sub-code details.
</Note>

***

## Useful links

* [Hosted payin — Introduction](/en/payment-api/hosted-payin/introduction)
* [Direct payin — Authentication modes](/en/payment-api/direct-payin/validation-modes)
* [Payout — Introduction](/en/payment-api/payout/introduction)
* [Callback security](/en/payment-api/callback/security)
* [transaction\_id pattern](/en/concepts/transaction-id-pattern)
* [ligdicash npm package](https://www.npmjs.com/package/ligdicash)
