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

# Claude Code

> Configure Claude Code to generate correct LigdiCash integration code on the first try

Claude Code is Anthropic's CLI tool. By adding a `CLAUDE.md` file at the root of your project, you give it the LigdiCash context once — it will then follow the API conventions in every response.

## LigdiCash skill

<Card title="LigdiCash skill for Claude Code" icon="brain-circuit" color="#e11d48" href="/en/sdk/ai-skill">
  Install the skill so Claude Code knows the LigdiCash API out of the box — ZIP download, install via `npx skills`, and ready-to-use prompts.
</Card>

## Requirements

* [Claude Code installed](https://docs.anthropic.com/en/claude-code) (`npm install -g @anthropic-ai/claude-code`)
* A Claude Pro, Max, or Anthropic API subscription

## `CLAUDE.md` file to create

Create a `CLAUDE.md` file at the root of your project with the following content:

````markdown theme={null}
# LigdiCash integration

## Context

LigdiCash is a mobile money payment aggregator in West Africa.
API base URL: https://app.ligdicash.com

## Mandatory headers on every request

```
Apikey: {API_KEY}
Authorization: Bearer {AUTH_TOKEN}
Accept: application/json
Content-Type: application/json
```

## Data format

- Phone numbers: E.164 format without `+` or spaces — e.g. `22670000000`
- Amounts: integers (CFA francs have no sub-unit) — e.g. `5000`
- Currency: `XOF` exclusively
- API keys in examples: always `{API_KEY}` and `{AUTH_TOKEN}`, never real values

## Golden rule — transaction identification

The `token` returned at creation is different from the `token` received in the callback.
Never use that token to identify a transaction.

Always pass a merchant identifier in `custom_data` at creation:
```json
"custom_data": { "transaction_id": "ORD-2025-00042" }
```

In the callback, `custom_data` comes back as an array of objects. LigdiCash adds its own fields (`hash`, `logfile`). Extract with:
```javascript
const entry = custom_data.find(e => e.keyof_customdata === "transaction_id");
const transactionId = entry?.valueof_customdata;
```

## Hosted payin — pitfalls

- `customer` must stay `""` — otherwise LigdiCash filters the visible operators
- Never open the payment URL in an `<iframe>` — use the same tab, a new tab, a popup, or a native WebView
- Popup: open `about:blank` before the `await fetch`, then navigate once the URL is received

## Callback

- LigdiCash sends two POSTs: one `application/x-www-form-urlencoded` + one `application/json`. Deduplicate.
- Re-verify each callback by calling the `confirm` endpoint with the token stored at creation. Never trust the received payload.
````

## Ready-to-use prompts

Copy and paste these messages into Claude Code for the most common use cases.

<AccordionGroup>
  <Accordion title="Hosted payin (checkout-invoice)">
    ```
    Implement a LigdiCash hosted payin in [language].

    - Endpoint: POST https://app.ligdicash.com/pay/v01/redirect/checkout-invoice/create
    - Amount: variable (function parameter)
    - customer must stay "" (empty)
    - Pass transaction_id in custom_data (object): { "transaction_id": "..." }
    - Open the returned URL in a new tab (no iframe)
    - Handle HTTP errors and response_code != "00"

    Return the payment URL or throw an exception.
    ```
  </Accordion>

  <Accordion title="Secure callback handler">
    ```
    Write a LigdiCash callback handler in [language/framework].

    Required behavior:
    1. Accept POST in application/json AND application/x-www-form-urlencoded
    2. Deduplicate by token (idempotency)
    3. Re-verify the status by calling the confirm endpoint with the token stored in the database
    4. custom_data in the callback is an array of objects — extract via keyof_customdata === "transaction_id"
    5. Update the order in the database only if the confirm status is "00"
    ```
  </Accordion>

  <Accordion title="Payout to mobile money">
    ```
    Implement a direct LigdiCash payout to mobile money in [language].

    - Endpoint: POST https://app.ligdicash.com/pay/v01/straight/payout
    - Parameters: amount, phone number (22670XXXXXXX format), description
    - Pass transaction_id in custom_data (object): { "transaction_id": "..." }
    - Handle errors and log the wiki URL on failure
    ```
  </Accordion>

  <Accordion title="Direct payin (USSD OTP)">
    ```
    Implement a LigdiCash direct payin (USSD OTP mode) in [language].

    - Endpoint: POST https://app.ligdicash.com/pay/v01/straight/checkout-invoice/create
    - external_id must stay "" (empty)
    - The user generates their OTP via their operator's USSD menu BEFORE submission
    - Pass transaction_id in custom_data (object): { "transaction_id": "..." }
    - The final confirmation comes through the callback (do not implement polling)
    ```
  </Accordion>
</AccordionGroup>

## Good practices

<Tip>
  Run `claude` at the root of your project — Claude Code reads `CLAUDE.md` automatically at startup and knows the LigdiCash conventions right away.
</Tip>
