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

# Vendre de l'électricité VIRUNGA

> Une vente VIRUNGA suit le même contrat qu'une vente SOCODE. Sa confirmation prend plus de temps, et elle ne passe jamais en réconciliation.

## 1. Une première vente, tout en dur

```bash cURL icon="https://mintcdn.com/dommi10/MMGXqk_5twdsE4Rl/logos/langages/bash.svg?fit=max&auto=format&n=MMGXqk_5twdsE4Rl&q=85&s=c7cc496df6d82b1c6cdaa5c132b8d4bc" theme={"dark"}
curl -X POST "$UMEME_BASE_URL/ventes" \
  -H "Authorization: Bearer $UMEME_CLE" \
  -H "Content-Type: application/json" \
  -d '{
    "uuid": "94a223fe-fb34-47f2-aaa5-b80c4bf8a8eb",
    "compte": "VIRUNGA",
    "reference": "09900000000",
    "montant": 5
  }'
```

```javascript Node.js · fetch icon="https://mintcdn.com/dommi10/MMGXqk_5twdsE4Rl/logos/langages/nodejs.svg?fit=max&auto=format&n=MMGXqk_5twdsE4Rl&q=85&s=60e7eb54ba25d5cb5e9d62e0896b99c7" theme={"dark"}
// Node.js 18 et plus : fetch est intégré.
const baseUrl = process.env.UMEME_BASE_URL;

const corps = {
  uuid: "94a223fe-fb34-47f2-aaa5-b80c4bf8a8eb",
  compte: "VIRUNGA",
  reference: "09900000000",
  montant: 5,
};

const reponse = await fetch(`${baseUrl}/ventes`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.UMEME_CLE}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(corps),
});
const donnees = await reponse.json();
```

```javascript Node.js · Axios icon="https://mintcdn.com/dommi10/MMGXqk_5twdsE4Rl/logos/langages/axios.svg?fit=max&auto=format&n=MMGXqk_5twdsE4Rl&q=85&s=7e8bd7e79f903d3d1bffc290e52fcdc9" theme={"dark"}
// npm install axios
import axios from "axios";

const umeme = axios.create({
  baseURL: process.env.UMEME_BASE_URL,
  headers: { Authorization: `Bearer ${process.env.UMEME_CLE}` },
  timeout: 30000,
});

const corps = {
  uuid: "94a223fe-fb34-47f2-aaa5-b80c4bf8a8eb",
  compte: "VIRUNGA",
  reference: "09900000000",
  montant: 5,
};

const { data } = await umeme.post("/ventes", corps);
```

```python Python icon="https://mintcdn.com/dommi10/MMGXqk_5twdsE4Rl/logos/langages/python.svg?fit=max&auto=format&n=MMGXqk_5twdsE4Rl&q=85&s=41e570f5c5c97d07c3c878a6704f2bed" theme={"dark"}
import os

import requests

BASE_URL = os.environ["UMEME_BASE_URL"]
ENTETES = {"Authorization": f"Bearer {os.environ['UMEME_CLE']}"}

corps = {
    "uuid": "94a223fe-fb34-47f2-aaa5-b80c4bf8a8eb",
    "compte": "VIRUNGA",
    "reference": "09900000000",
    "montant": 5,
}

reponse = requests.post(
    f"{BASE_URL}/ventes",
    headers=ENTETES,
    json=corps,
    timeout=30,
)
donnees = reponse.json()
```

```php PHP icon="https://mintcdn.com/dommi10/MMGXqk_5twdsE4Rl/logos/langages/php.svg?fit=max&auto=format&n=MMGXqk_5twdsE4Rl&q=85&s=706823b5881c1d4e78720e369520cc78" theme={"dark"}
// composer require guzzlehttp/guzzle
$client = new GuzzleHttp\Client([
    'base_uri' => getenv('UMEME_BASE_URL') . '/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('UMEME_CLE')],
    'timeout' => 30,
]);

$corps = [
    'uuid' => '94a223fe-fb34-47f2-aaa5-b80c4bf8a8eb',
    'compte' => 'VIRUNGA',
    'reference' => '09900000000',
    'montant' => 5,
];

$reponse = $client->post('ventes', [
    'json' => $corps,
]);
$donnees = json_decode($reponse->getBody(), true);
```

```java Java icon="https://mintcdn.com/dommi10/MMGXqk_5twdsE4Rl/logos/langages/java.svg?fit=max&auto=format&n=MMGXqk_5twdsE4Rl&q=85&s=a99792afd2b2bcd5b3c64f5157b8469e" theme={"dark"}
// Java 15 et plus : java.net.http et blocs de texte.
var baseUrl = System.getenv("UMEME_BASE_URL");
var client = HttpClient.newHttpClient();

var corps = """
    {
      "uuid": "94a223fe-fb34-47f2-aaa5-b80c4bf8a8eb",
      "compte": "VIRUNGA",
      "reference": "09900000000",
      "montant": 5
    }
    """;

var requete = HttpRequest.newBuilder(URI.create(baseUrl + "/ventes"))
    .header("Authorization", "Bearer " + System.getenv("UMEME_CLE"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(corps))
    .build();

var reponse = client.send(requete, HttpResponse.BodyHandlers.ofString());
```

La réponse est `ACCEPTEE`. La vente est confirmée en une vingtaine de secondes, environ 23 s en production ; le rappel arrive alors avec le jeton.

## 2. Ce qui change avec VIRUNGA

| Point | SOCODE | VIRUNGA |
| :- | :- | :- |
| Délai en production | environ 4 s | environ 23 s |
| Vérifier le compteur | `GET /v1/compteurs/{reference}` | Pas de vérification : contrôlez le format, 11 chiffres |
| Réconciliation | Possible : `EN_RECONCILIATION` | Jamais |
| Numéro de reçu | `USD/…` | L'identifiant de la vente |

## 3. Éviter les rejets

Les mêmes rejets qu'une vente SOCODE, sauf `COMPTEUR_INCONNU` : sans vérification, un compteur inconnu échoue plus tard, à la confirmation. Voir [Codes d'erreur](https://docs.umeme.app/ressources/codes-erreur.md).

## 4. Gérer les échecs

| `motifEchec.code` | Ce qui s'est passé |
| :- | :- |
| `REFUS_COMPTEUR_FOURNISSEUR` | La vente est refusée pour ce compteur |
| `MINIMUM_FOURNISSEUR` | Le montant est sous le minimum de ce compteur |
| `NON_TRAITEE_DANS_LE_DELAI` | La vente n'a pas été confirmée dans le délai |

Dans chaque cas, le portefeuille est déjà remboursé.

## 5. Rester cohérent

Les règles de [Vendre de l'électricité SOCODE](https://docs.umeme.app/guides/vendre-socode.md) s'appliquent. Une vente VIRUNGA peut rester `EN_COURS` longtemps : votre tâche de reprise la consulte, sans jamais la relancer.

> [!TIP]
>
> Le compteur `09900000060` n'est jamais confirmé dans la sandbox : il sert à éprouver votre reprise.

## 6. Et ensuite ?

> [card] [Compteurs de test](https://docs.umeme.app/ressources/compteurs-de-test.md)
>
> Les scénarios VIRUNGA : 00, 01, 02, 11, 12, 40, 50 et 60.

> [card] [Recevoir et vérifier les rappels](https://docs.umeme.app/guides/rappels.md)
>
> Vérifier la signature des rappels.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.