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

# Créer une transaction

> Endpoint POST /pay/v01/straight/checkout-invoice/create — paramètres, exemples par mode de validation et réponse.

Cet endpoint initie un paiement directement depuis votre interface. Vous fournissez le numéro de téléphone du client et, selon le [mode de validation](/api-paiement/payin-sans-redirect/modes-validation) de l'opérateur, l'OTP ou un champ vide. LigdiCash retourne un token à stocker et déclenche le processus de validation côté opérateur.

```
POST https://app.ligdicash.com/pay/v01/straight/checkout-invoice/create
```

<Note>
  Le Wallet LigdiCash utilise des endpoints distincts (`/pay/v02/debitotp` et `/pay/v02/debitwallet/withotp`). Consultez la [page dédiée au Wallet LigdiCash](/api-paiement/payin-sans-redirect/operateurs/wallet-ligdicash) pour son intégration spécifique.
</Note>

## Headers

<ParamField header="Apikey" type="string" required>
  La clé API de votre projet LigdiCash.
</ParamField>

<ParamField header="Authorization" type="string" required>
  Votre API TOKEN précédé de `Bearer `. Exemple : `Bearer eyJ0eXAiOiJKV1Qi...`
</ParamField>

<ParamField header="Accept" type="string" required>
  Doit être `application/json`.
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Doit être `application/json`.
</ParamField>

## Body

<ParamField body="commande" type="object" required>
  Objet racine de la requête.

  <Expandable title="Champs de commande" defaultOpen={true}>
    <ParamField body="invoice" type="object" required>
      Détails de la transaction.

      <Expandable title="Champs de invoice" defaultOpen={true}>
        <ParamField body="items" type="array" required>
          Liste des articles. Peut être vide (`[]`) — dans ce cas, seul `total_amount` est pris en compte.

          <Expandable title="Champs d'un item">
            <ParamField body="name" type="string" required>Nom de l'article.</ParamField>
            <ParamField body="description" type="string">Description de l'article.</ParamField>
            <ParamField body="quantity" type="integer" required>Quantité.</ParamField>
            <ParamField body="unit_price" type="integer" required>Prix unitaire en XOF.</ParamField>
            <ParamField body="total_price" type="integer" required>Prix total de la ligne (`unit_price × quantity`) en XOF.</ParamField>
          </Expandable>
        </ParamField>

        <ParamField body="total_amount" type="integer" required>
          Montant total en XOF (entier, sans décimales).
        </ParamField>

        <ParamField body="devise" type="string" required>
          Devise. Toujours `XOF`.
        </ParamField>

        <ParamField body="description" type="string" required>
          Description de la commande.
        </ParamField>

        <ParamField body="customer" type="string" required>
          Numéro de téléphone mobile money du client, sans `+` ni espaces. Format : `22670XXXXXXX`.
        </ParamField>

        <ParamField body="customer_firstname" type="string">
          Prénom du client.
        </ParamField>

        <ParamField body="customer_lastname" type="string">
          Nom du client.
        </ParamField>

        <ParamField body="customer_email" type="string">
          Email du client.
        </ParamField>

        <ParamField body="external_id" type="string" required>
          Doit toujours être vide (`""`).
        </ParamField>

        <ParamField body="otp" type="string" required>
          Code OTP selon le mode de validation de l'opérateur :

          * **OTP USSD** : OTP généré par le client via son menu USSD, à renseigner avant l'appel.
          * **USSD Push**, **USSD guidé**, **OTP SMS (1ère requête)** : laisser vide (`""`).
          * **OTP SMS (2ème requête)** : OTP reçu par SMS par le client.
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="store" type="object" required>
      Informations sur votre boutique.

      <Expandable title="Champs de store" defaultOpen={true}>
        <ParamField body="name" type="string" required>Nom de votre boutique ou application.</ParamField>
        <ParamField body="website_url" type="string" required>URL de votre site.</ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="actions" type="object" required>
      URLs de retour et de notification.

      <Expandable title="Champs de actions" defaultOpen={true}>
        <ParamField body="cancel_url" type="string" required>Laisser vide (`""`).</ParamField>
        <ParamField body="return_url" type="string" required>Laisser vide (`""`).</ParamField>

        <ParamField body="callback_url" type="string" required>
          URL de votre endpoint backend pour les notifications de statut. Doit être accessible publiquement.
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="custom_data" type="object">
      Objet libre pour vos métadonnées. LigdiCash vous le retourne dans le callback. Utilisez-le pour passer votre `transaction_id`.
    </ParamField>
  </Expandable>
</ParamField>

## Exemples de requête

Les exemples ci-dessous montrent deux cas selon le mode de validation. Seul le champ `otp` change.

<CodeGroup>
  ```bash cURL — OTP USSD (otp renseigné) theme={null}
  curl -X POST https://app.ligdicash.com/pay/v01/straight/checkout-invoice/create \
    -H "Apikey: {API_KEY}" \
    -H "Authorization: Bearer {API_TOKEN}" \
    -H "Accept: application/json" \
    -H "Content-Type: application/json" \
    -d '{
      "commande": {
        "invoice": {
          "items": [],
          "total_amount": 5000,
          "devise": "XOF",
          "description": "Abonnement Pro — Janvier 2025",
          "customer": "22670000000",
          "customer_firstname": "Amadou",
          "customer_lastname": "Diallo",
          "customer_email": "amadou@exemple.com",
          "external_id": "",
          "otp": "123456"
        },
        "store": {
          "name": "MonApp",
          "website_url": "https://monapp.com"
        },
        "actions": {
          "cancel_url": "",
          "return_url": "",
          "callback_url": "https://monapp.com/api/callback/ligdicash"
        },
        "custom_data": {
          "transaction_id": "ORD-2025-00042"
        }
      }
    }'
  ```

  ```bash cURL — USSD Push / USSD guidé / OTP SMS 1ère requête (otp vide) theme={null}
  curl -X POST https://app.ligdicash.com/pay/v01/straight/checkout-invoice/create \
    -H "Apikey: {API_KEY}" \
    -H "Authorization: Bearer {API_TOKEN}" \
    -H "Accept: application/json" \
    -H "Content-Type: application/json" \
    -d '{
      "commande": {
        "invoice": {
          "items": [],
          "total_amount": 5000,
          "devise": "XOF",
          "description": "Abonnement Pro — Janvier 2025",
          "customer": "22670000000",
          "customer_firstname": "Amadou",
          "customer_lastname": "Diallo",
          "customer_email": "amadou@exemple.com",
          "external_id": "",
          "otp": ""
        },
        "store": {
          "name": "MonApp",
          "website_url": "https://monapp.com"
        },
        "actions": {
          "cancel_url": "",
          "return_url": "",
          "callback_url": "https://monapp.com/api/callback/ligdicash"
        },
        "custom_data": {
          "transaction_id": "ORD-2025-00042"
        }
      }
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
    "https://app.ligdicash.com/pay/v01/straight/checkout-invoice/create",
    {
      method: "POST",
      headers: {
        Apikey: process.env.LIGDICASH_API_KEY,
        Authorization: `Bearer ${process.env.LIGDICASH_API_TOKEN}`,
        Accept: "application/json",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        commande: {
          invoice: {
            items: [],
            total_amount: 5000,
            devise: "XOF",
            description: "Abonnement Pro — Janvier 2025",
            customer: "22670000000",
            customer_firstname: "Amadou",
            customer_lastname: "Diallo",
            customer_email: "amadou@exemple.com",
            external_id: "",
            otp: "", // ou l'OTP collecté pour le mode OTP USSD
          },
          store: { name: "MonApp", website_url: "https://monapp.com" },
          actions: {
            cancel_url: "",
            return_url: "",
            callback_url: "https://monapp.com/api/callback/ligdicash",
          },
          custom_data: { transaction_id: "ORD-2025-00042" },
        },
      }),
    }
  );

  const data = await response.json();
  ```

  ```php PHP theme={null}
  $otp = ""; // ou l'OTP collecté pour le mode OTP USSD

  $payload = [
    "commande" => [
      "invoice" => [
        "items" => [],
        "total_amount" => 5000,
        "devise" => "XOF",
        "description" => "Abonnement Pro — Janvier 2025",
        "customer" => "22670000000",
        "customer_firstname" => "Amadou",
        "customer_lastname" => "Diallo",
        "customer_email" => "amadou@exemple.com",
        "external_id" => "",
        "otp" => $otp,
      ],
      "store" => ["name" => "MonApp", "website_url" => "https://monapp.com"],
      "actions" => [
        "cancel_url" => "",
        "return_url" => "",
        "callback_url" => "https://monapp.com/api/callback/ligdicash",
      ],
      "custom_data" => ["transaction_id" => "ORD-2025-00042"],
    ],
  ];

  $ch = curl_init("https://app.ligdicash.com/pay/v01/straight/checkout-invoice/create");
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Apikey: " . $_ENV["LIGDICASH_API_KEY"],
    "Authorization: Bearer " . $_ENV["LIGDICASH_API_TOKEN"],
    "Accept: application/json",
    "Content-Type: application/json",
  ]);

  $data = json_decode(curl_exec($ch), true);
  curl_close($ch);
  ```
</CodeGroup>

## Réponse

<ResponseField name="response_code" type="string">
  `"00"` si la transaction a été créée avec succès, `"01"` en cas d'erreur.
</ResponseField>

<ResponseField name="token" type="string">
  Identifiant de la transaction côté LigdiCash. **À stocker en base immédiatement** — nécessaire pour appeler l'endpoint `confirm` et re-vérifier le statut.
</ResponseField>

<ResponseField name="response_text" type="string">
  En cas de succès : `"Votre requête est en cours de traitement"`. En cas d'échec : le sous-code d'erreur au format `Echec (CodeXX)`.
</ResponseField>

<ResponseField name="wiki" type="string">
  URL vers la documentation des codes d'erreur de cet endpoint. À consulter quand `response_code` vaut `"01"`.
</ResponseField>

## Exemple de réponse

<CodeGroup>
  ```json Succès theme={null}
  {
    "response_code": "00",
    "token": "eyJ0eXAiOiJKV1Qi...",
    "response_text": "Votre requête est en cours de traitement",
    "wiki": "https://client.ligdicash.com/wiki/createInvoice"
  }
  ```

  ```json Échec theme={null}
  {
    "response_code": "01",
    "token": "",
    "response_text": "Echec (Code00)",
    "wiki": "https://client.ligdicash.com/wiki/createInvoice"
  }
  ```
</CodeGroup>

<Warning>
  Stockez le `token` retourné dès la création. C'est lui que vous utiliserez pour appeler `confirm` et vérifier le statut final — ne vous fiez jamais au token présent dans le payload du callback.
</Warning>

## Pages associées

* [Modes de validation](/api-paiement/payin-sans-redirect/modes-validation) — choisir la valeur du champ `otp` selon l'opérateur
* [Vérifier le statut](/api-paiement/payin-sans-redirect/verifier-statut) — appeler `confirm` avec le token de création
* [Le pattern transaction\_id](/concepts/transaction-id-pattern) — bonnes pratiques pour `custom_data`
