# API blockwallets compatible Cryptomus

> L’API blockwallets compatible Cryptomus : factures et portefeuilles statiques, signature, webhooks et vérification, mode test, réseaux, erreurs et migration depuis Cryptomus en changeant le domaine.
>
> HTML: https://blockwallets.io/docs/cryptomus?lang=fr · English: https://blockwallets.io/docs/cryptomus.md?lang=en

## API compatible Cryptomus

blockwallets vous permet d’accepter l’USDT et l’USDC, ainsi que BTC, LTC, DOGE, BCH et des cryptos natives (créditées en dollars américains à un taux verrouillé) : le client paie, nous le confirmons on-chain, puis nous vous notifions. L’API, les signatures et les webhooks sont les mêmes que ceux de **Cryptomus** : si vous avez déjà intégré Cryptomus, changez le domaine et c’est fini. Le fonctionnement d’abord, l’API ensuite.

### Deux façons d’encaisser

Les deux acceptent **n’importe quel montant** : commandes à prix fixe et recharges où le client saisit le montant. Une fois payé, vous expédiez ou créditez le solde du client. La seule différence est **que chaque paiement reçoive ou non une adresse neuve**.

Recommandé · la plupart des intégrations**Factures**
Le client choisit un produit ou saisit un montant sur votre page, vous créez une facture et il envoie le montant affiché sur la page de paiement. Chaque facture a une adresse neuve et un compte à rebours ; à l’arrivée du paiement, nous vous notifions avec le montant réellement reçu.

`POST /v1/payment` → webhook `type: payment`

Facultatif**Portefeuilles statiques**
Pas de montant à l’avance : chaque client reçoit une adresse permanente par réseau, à enregistrer dans son portefeuille et à utiliser quand il veut, pour n’importe quel montant. Chaque transfert déclenche son propre webhook.

`POST /v1/wallet` → webhook `type: wallet`

En cas de doute, utilisez les factures. Sans code, les [liens de paiement](https://blockwallets.io/docs/cryptomus?lang=fr#links) du tableau de bord sont des factures créées pour vous. Pas encore marchand ? Demandez l’accès sur la [page d’accueil](https://blockwallets.io/?lang=fr#join) ; une fois approuvé, connectez-vous au [tableau de bord marchand](https://blockwallets.io/dashboard) et commencez par « Tester un paiement » sur la page d’accueil du tableau de bord, avec un petit montant (l’argent va sur votre propre solde).

### Le cycle d’une facture

Un paiement fait intervenir quatre parties : le client, votre site, blockwallets et la blockchain. Le schéma se lit de haut en bas dans le temps ; la colonne de droite indique le statut de la facture à chaque étape.

En bref, cinq étapes :

- Vous créez une facture (un lien de paiement le fait pour vous, ou votre serveur appelle `/v1/payment`), obtenez l’`url` de la page de paiement et y redirigez le client.

- Sur la page de paiement, le client choisit une crypto et un réseau, reçoit une adresse et un montant dédiés, et paie depuis un portefeuille ou une plateforme d’échange.

- Nous voyons le transfert on-chain, attendons assez de confirmations, puis le recoupons avec un second fournisseur de nœuds (pour qu’un nœud ne puisse pas le falsifier).

- La facture passe à `paid` et nous envoyons aussitôt un webhook signé en POST à votre `url_callback` ; quelques secondes plus tard, la page de paiement renvoie le client vers votre `url_success`.

- L’argent est crédité sur votre solde ; retirez-le vers votre propre portefeuille depuis le tableau de bord marchand.

#### Statut de la facture

| status | Signification | Ce que vous faites |
| --- | --- | --- |
| `check` | En attente de paiement | — |
| `confirm_check` | Transfert vu, en attente de confirmations | — |
| `wrong_amount_waiting` | Reçu mais insuffisant ; le client peut compléter à la même adresse (si `is_payment_multiple` vaut true ; notifié une fois) | — (vous recevez `paid` une fois complété) |
| `paid` | Payée | Expédiez / créditez selon `payment_amount_usd` |
| `paid_over` | Payée, avec un trop-perçu | Pareil (`payment_amount_usd` est le montant reçu) |
| `wrong_amount` | Expirée avec moins que le montant total (avec `is_payment_multiple` à false : le premier transfert insuffisant) | Les activités de recharge peuvent créditer le `payment_amount_usd` reçu ; les boutiques demandent au client de payer le reste |
| `cancel` | Expirée sans rien recevoir | — (l’argent qui arrive plus tard est quand même crédité et notifié) |

Quand `is_final` vaut `true`, le statut ne changera plus (sauf paiements tardifs).

### Liens de paiement (sans code)

Tableau de bord marchand → « Encaissements › Liens de paiement » → saisissez une description et un montant (imposez un réseau ou laissez le client choisir) → créez. Chaque lien a une URL et un QR code.

- Chaque fois que quelqu’un ouvre le lien, une nouvelle facture est créée : un même lien peut donc être réutilisé (p. ex. « Abonnement 99 $ »).

- Chaque paiement apparaît dans « Encaissements › Transactions » ; retirez-le vers votre portefeuille depuis « Fonds › Solde et retraits ».

- Si vous avez créé des identifiants et une URL de webhook dans « Développeurs › Intégration et clés », les paiements par lien sont aussi notifiés au format ci-dessous.

- Pour arrêter d’encaisser, cliquez sur « Désactiver » : le lien cesse de fonctionner immédiatement.

### Intégration par API

#### 1. Identifiants et signature

Tableau de bord marchand → « Développeurs › Intégration et clés » → générez un **merchant** (UUID) et une **API key**. Il y a un jeu pour Live et un pour Test : Live manipule de l’argent réel, Test fonctionne sur des testnets. Ajoutez aussi vos **domaines du site web** : `url_callback`, `url_return` et `url_success` doivent s’y trouver. L’API key n’est affichée qu’une fois : conservez-la en lieu sûr, et uniquement sur votre serveur.

URL de base `https://blockwallets.io`. Tous les endpoints sont en `POST` + JSON, avec ces en-têtes :

- `merchant` : l’UUID de votre merchant (c’est lui qui détermine Live ou Test)

- `sign` : `md5(base64(request body) + API key)`, où le corps est exactement la chaîne JSON que vous envoyez

En cas de succès, la réponse est `{"state": 0, "result": {…}}` ; en cas d’échec, `{"state": 1, "message": "…"}` (voir [Erreurs](https://blockwallets.io/docs/cryptomus?lang=fr#errors)).

Les principaux endpoints ci-dessous ont un panneau « Essayer » : saisissez votre merchant et votre API key de Test, et la page signe la requête dans votre navigateur, appelle l’endpoint et affiche la requête et la réponse complètes (les identifiants restent dans la mémoire de la page). Si une signature ne correspond pas, comparez-la étape par étape avec le [vérificateur de signature](https://blockwallets.io/docs/sign?lang=fr).

```nodejs
import crypto from "node:crypto";

async function call(path, data) {
  const body = JSON.stringify(data);
  const sign = crypto.createHash("md5").update(Buffer.from(body).toString("base64") + process.env.BW_API_KEY).digest("hex");
  const res = await fetch("https://blockwallets.io" + path, {
    method: "POST",
    headers: { merchant: process.env.BW_MERCHANT, sign, "Content-Type": "application/json" },
    body,
  });
  return res.json();
}
```

```php
function bw_call(string $path, array $data): array {
    $body = json_encode($data, JSON_UNESCAPED_UNICODE);
    $sign = md5(base64_encode($body) . getenv('BW_API_KEY'));
    $ch = curl_init('https://blockwallets.io' . $path);
    curl_setopt_array($ch, [
        CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => ['merchant: ' . getenv('BW_MERCHANT'), 'sign: ' . $sign, 'Content-Type: application/json'],
    ]);
    return json_decode(curl_exec($ch), true);
}
```

```python
import base64, hashlib, json, os, requests

def bw_call(path: str, data: dict) -> dict:
    body = json.dumps(data, separators=(",", ":"), ensure_ascii=False)
    sign = hashlib.md5((base64.b64encode(body.encode()).decode() + os.environ["BW_API_KEY"]).encode()).hexdigest()
    headers = {"merchant": os.environ["BW_MERCHANT"], "sign": sign, "Content-Type": "application/json"}
    return requests.post("https://blockwallets.io" + path, data=body.encode(), headers=headers).json()
```

#### 2. Créer une facture POST /v1/payment

Quand le client passe commande, ou saisit un montant sur votre page de recharge, appelez `https://blockwallets.io/v1/payment` et redirigez-le vers le `result.url` renvoyé.

```json
{
  "amount": "42.00",
  "currency": "USD",
  "order_id": "order_1042",
  "url_callback": "https://shop.example/webhooks/crypto",
  "url_return": "https://shop.example/cart",
  "url_success": "https://shop.example/thanks?order=1042"
}
```

| Paramètre | Obligatoire | Description |
| --- | --- | --- |
| `amount` | Oui | Montant sous forme de chaîne, avec au plus deux décimales : `"42.00"`. Votre prix ou un nombre saisi par le client ; pas en dessous du minimum du réseau choisi (voir [réseaux](https://blockwallets.io/docs/cryptomus?lang=fr#networks)) |
| `currency` | Oui | `USD`, `USDT` ou `USDC`, toutes à 1:1 |
| `order_id` | Oui | Votre numéro de commande : lettres, chiffres, `-`, `_`, ≤ 100 caractères. Un nouvel appel avec le même order_id renvoie la facture existante (pas de commande en double) |
| `url_callback` | Non | URL du webhook. Sans elle, aucun webhook n’est envoyé |
| `url_return` | Non | Où mène « Retour » avant le paiement |
| `url_success` | Non | Où le client est envoyé après le paiement |
| `network` | Non | Présélectionner un réseau : `tron` / `bsc` / `eth` / `base` / `polygon` / `arbitrum` / `optimism` / `avalanche` / `xlayer` / `btc` / `ltc` / `doge` / `bch` / `sol` / `ton` ; sans ce paramètre, le client choisit sur la page de paiement |
| `to_currency` | Non | Crypto sur ce réseau : `USDT` / `USDC` ; sur `btc` / `ltc` / `doge` / `bch`, c’est `BTC` / `LTC` / `DOGE` / `BCH` (facultatif) |
| `lifetime` | Non | Durée de vie de la facture en secondes, de 300 à 43200, 3600 par défaut ; toute valeur inférieure à 600 compte pour 600 |
| `accuracy_payment_percent` | Non | Quel montant manquant est encore considéré comme payé, de 0 à 5, 0 par défaut. `100` = accepter ce qui arrive : `paid` dès la confirmation (`paid_over` si plus), crédit selon `payment_amount_usd` dans le webhook — idéal pour les recharges. Si omis, la « Règle de montant » de « Réglages › Règles d’encaissement et tarifs » du tableau de bord s’applique : « créditer ce qui arrive » équivaut à 100 |
| `subtract` | Non | Part des frais de plateforme payée par le client, de 0 à 100, ajoutée à `payer_amount` (les frais de plateforme sont de 1%, moins avec un volume plus élevé ; à 1%, avec 100, une facture de 100 $ coûte 101,00 $ au client ; voir les [tarifs](https://blockwallets.io/pricing?lang=fr)). Si omis, le réglage « Frais et paiements partiels » de « Réglages › Règles d’encaissement et tarifs » du tableau de bord s’applique (0 par défaut) |
| `is_payment_multiple` | Non | Si un paiement insuffisant peut être complété, true par défaut : statut `wrong_amount_waiting`, payer le reste à la même adresse la fait passer à `paid` (s’il reste moins de 30 minutes au premier paiement insuffisant, l’échéance est repoussée à 30 minutes plus tard). false : le premier transfert insuffisant la fait passer à `wrong_amount`. Si omis, le réglage du tableau de bord s’applique |
| `additional_data` | Non | N’importe quelle chaîne (≤ 255), renvoyée telle quelle dans les requêtes et les webhooks |

```json
{
  "state": 0,
  "result": {
    "uuid": "6f1c2a7e-…",
    "order_id": "order_1042",
    "amount": "42.00",
    "currency": "USD",
    "network": null,
    "address": null,
    "payer_amount": null,
    "payment_amount": null,
    "url": "https://blockwallets.io/pay/inv_01J8…",
    "expired_at": 1760965200,
    "status": "check",
    "is_final": false
  }
}
```

`network`, `address` et `payer_amount` sont renseignés une fois que le client a choisi un réseau.

#### 3. Consulter les factures

- `POST /v1/payment/info` `{"order_id": "…"}` ou `{"uuid": "…"}` : récupère une facture et interroge la chaîne au passage (au plus une fois toutes les 10 secondes).

- `POST /v1/payment/list` : liste, 15 par page, avec `date_from` / `date_to` facultatifs ; page suivante via le `paginate.nextCursor` renvoyé (`?cursor=…`).

- `POST /v1/payment/services` : réseaux disponibles et montant minimum de chacun.

- `POST /v1/payment/resend` `{"order_id": "…"}` : renvoie le webhook d’une facture payée / insuffisante.

Les webhooks sont le canal principal ; les requêtes servent de secours (par exemple si votre serveur était en panne et a manqué un webhook).

#### 4. Portefeuilles statiques POST /v1/wallet

Ouvre une adresse permanente pour un client sur un réseau. Le même `order_id` (en général votre identifiant d’utilisateur) + réseau donne toujours la même adresse ; toutes les chaînes EVM (BNB Chain, Ethereum, Base, Polygon, Arbitrum, Optimism, Avalanche, X Layer) partagent une adresse, tandis que TRON, BTC, LTC, DOGE, BCH, Solana et TON ont chacune la leur. Tout ce que le client envoie est crédité, avec un webhook par transfert ; les transferts BTC / LTC / DOGE / BCH / TRX / BNB / ETH / POL / AVAX / OKB / SOL / TON sont convertis en dollars américains au taux du moment où chacun a été vu (`payment_amount_usd`).

```json
{
  "order_id": "user_42",
  "currency": "USDT",
  "network": "tron",
  "url_callback": "https://shop.example/webhooks/crypto"
}
```

```json
{
  "state": 0,
  "result": {
    "wallet_uuid": "0b9d…",
    "uuid": "5e2f…",
    "order_id": "user_42",
    "currency": "USDT",
    "network": "tron",
    "address": "TXy4…8kQ2",
    "url": "https://blockwallets.io/deposit/dac_01J8…"
  }
}
```

`result.url` est une page de dépôt hébergée (adresse + QR code + dépôts récents) que vous pouvez remettre au client. Les transferts inférieurs au minimum du réseau (généralement $1, BTC $5) ne sont pas crédités automatiquement ; contactez-nous pour les faire créditer. Le blocage d’adresses (`/v1/wallet/block-address`) n’est pas encore pris en charge.

### Webhooks

Quand le statut d’une facture change (`paid`, `paid_over`, `wrong_amount_waiting`, `wrong_amount`, `cancel`) et à chaque transfert vers un portefeuille statique, nous envoyons un POST JSON à `url_callback`. Une réponse 2xx compte comme livrée ; sinon nous réessayons après 1 minute, 5 minutes, 30 minutes, 2 heures, 12 heures, 24 heures et 24 heures. Vous pouvez aussi renvoyer depuis le tableau de bord ou avec `/v1/payment/resend`.

```json
{
  "type": "payment",
  "uuid": "6f1c2a7e-…",
  "order_id": "order_1042",
  "amount": "42.00",
  "payment_amount": "42",
  "payment_amount_usd": "42.00",
  "merchant_amount": "41.58",
  "commission": "0.42",
  "is_final": true,
  "status": "paid",
  "from": "TQ8m…",
  "wallet_address_uuid": null,
  "network": "tron",
  "currency": "USD",
  "payer_currency": "USDT",
  "payer_amount": "42",
  "payer_amount_exchange_rate": "1",
  "additional_data": null,
  "txid": "9c1e…",
  "sign": "5f0c9b…"
}
```

| type | Quand | Crédit |
| --- | --- | --- |
| `payment` | Le statut d’une facture a changé — voir `status` | Créditez `payment_amount_usd` sur `paid` / `paid_over` ; dédoublonnez par `uuid` |
| `wallet` | Un transfert est arrivé sur un portefeuille statique (`status` vaut toujours `paid` ; `order_id` est celui avec lequel vous avez ouvert le portefeuille) | Créditez `payment_amount_usd` ; chaque transfert a son propre `uuid` — dédoublonnez par lui |

#### Vérifier la signature (obligatoire)

La signature est le champ `sign` du corps du webhook : retirez `sign`, ré-encodez le reste comme le fait `json_encode` de PHP (compact, `/` échappé en `\/`, caractères non ASCII non échappés), et `md5(base64(encoded) + API key)` doit être égal à `sign`. Utilisez l’API key du même mode. Un même webhook peut arriver plusieurs fois — dédoublonnez par `uuid` + `status`.

Si la vérification échoue, collez le corps brut du webhook dans le [vérificateur de signature](https://blockwallets.io/docs/sign?lang=fr) : il affiche le résultat de chaque étape et marque l’endroit où le vôtre diffère (tout s’exécute dans votre navigateur ; l’API key n’est jamais envoyée). Chaque webhook de « Développeurs › Journal des webhooks » dans le tableau de bord s’ouvre dans le vérificateur en un clic.

```nodejs
import crypto from "node:crypto";

function verify(rawBody, apiKey) {
  const { sign, ...data } = JSON.parse(rawBody);
  const json = JSON.stringify(data).replaceAll("/", "\\/");
  const expected = crypto.createHash("md5").update(Buffer.from(json).toString("base64") + apiKey).digest("hex");
  return typeof sign === "string" && sign.length === expected.length && crypto.timingSafeEqual(Buffer.from(sign), Buffer.from(expected));
}
```

```php
$data = json_decode(file_get_contents('php://input'), true);
$sign = $data['sign'] ?? '';
unset($data['sign']);
$expected = md5(base64_encode(json_encode($data, JSON_UNESCAPED_UNICODE)) . $apiKey);
if (!hash_equals($expected, $sign)) {
    http_response_code(401); exit;
}
```

```python
import base64, hashlib, hmac, json

def verify(raw_body: bytes, api_key: str) -> bool:
    data = json.loads(raw_body)
    sign = data.pop("sign", "")
    encoded = json.dumps(data, separators=(",", ":"), ensure_ascii=False).replace("/", "\\/")
    expected = hashlib.md5((base64.b64encode(encoded.encode()).decode() + api_key).encode()).hexdigest()
    return hmac.compare_digest(expected, sign)
```

### Mode test

Les factures créées avec le merchant et l’API key de Test fonctionnent sur des testnets, sans argent réel. La page de paiement affiche un bouton « Simuler un paiement » (complet / moitié / trop-perçu), pour voir les changements de statut et les webhooks sans avoir de cryptos de testnet.

- `POST /v1/test-webhook/payment`, `/v1/test-webhook/wallet` : envoient un webhook d’exemple signé à `url_callback` (passez `url_callback`, obligatoire et sur l’un de vos domaines enregistrés, ainsi que `currency`, `network`, et éventuellement `status`, `order_id`) pour déboguer votre code de vérification.

- Tableau de bord « Développeurs › Intégration et clés » → « Envoyer une notification de test » : envoie un exemple à votre URL de webhook.

- Tableau de bord « Développeurs › Journal des webhooks » : chaque tentative de livraison avec son heure, l’URL cible, le statut HTTP, la durée, le corps de la requête et la réponse de votre serveur (les 4 premiers Ko) ; filtrez par commande ou statut et renvoyez en un clic. Conservé 30 jours.

### Migrer depuis Cryptomus

- Tableau de bord « Développeurs › Intégration et clés » → générez un merchant et une API key.

- Remplacez `https://api.cryptomus.com` dans votre code par `https://blockwallets.io`, et utilisez le nouveau merchant et la nouvelle API key.

- Ajoutez vos domaines dans « Domaines du site web » (`url_callback` / `url_return` / `url_success` n’acceptent que ceux-ci).

Pris en charge : `/v1/payment`, `/v1/payment/info`, `/v1/payment/list`, `/v1/payment/services`, `/v1/payment/resend`, `/v1/wallet`, `/v1/test-webhook/payment`, `/v1/test-webhook/wallet`. Différences : les factures sont libellées uniquement en USD / USDT / USDC (toutes à 1:1, sans écart de change) ; `commission` correspond à nos frais de plateforme (le montant reçu × le taux du marchand à la création de la facture — 1% en standard, jusqu’à 0.5% selon le volume ; rien n’est facturé deux fois sur la part que couvre le client) et `merchant_amount` = reçu − `commission` ; quand le client paie en BTC / LTC / DOGE / BCH / TRX / BNB / ETH / POL / AVAX / OKB / SOL / TON, nous cotons la médiane de plusieurs plateformes, verrouillée 30 minutes — `payer_amount` est le nombre de pièces à envoyer, `payer_amount_exchange_rate` la valeur en USD d’une pièce, et le paiement est converti en `payment_amount_usd` au taux verrouillé (les pièces restent chez nous, rien n’est échangé) ; réseaux `tron` / `bsc` / `eth` / `base` / `polygon` / `arbitrum` / `optimism` / `avalanche` / `xlayer` / `btc` / `ltc` / `doge` / `bch` / `sol` / `ton` ; durée de vie minimale de la facture 10 minutes ; pas de `is_refresh` ni de blocage des portefeuilles statiques ; par défaut, les webhooks proviennent d’IP changeantes ; si vous filtrez par IP, activez « Webhooks depuis une IP fixe » dans le tableau de bord, sous « Développeurs › Intégration et clés », et les webhooks ne viendront que de `18.163.145.41` — une liste d’autorisation est une couche supplémentaire, continuez de vérifier `sign`.

Vous venez de **NOWPayments** ou de **Coinbase Commerce** ? Nous avons des API compatibles avec les deux — changez l’URL de base et les clés ; voir le [guide de migration](https://blockwallets.io/docs/migrate?lang=fr).

### Réseaux et montants

| Crypto | Réseau | Paramètre network | Minimum | Arrivée |
| --- | --- | --- | --- | --- |
| USDT | TRON | `tron` | $1 | ~1 min |
| USDT | BNB Chain | `bsc` | $1 | ~1 min |
| USDC | BNB Chain | `bsc` | $1 | ~1 min |
| USDT | Ethereum | `eth` | $5 | ~1 min |
| USDC | Ethereum | `eth` | $5 | ~1 min |
| USDC | Base | `base` | $1 | ~1 min |
| USDT | Polygon | `polygon` | $1 | ~1 min |
| USDC | Polygon | `polygon` | $1 | ~1 min |
| USDT | Arbitrum | `arbitrum` | $1 | ~1 min |
| USDC | Arbitrum | `arbitrum` | $1 | ~1 min |
| USDT | Optimism | `optimism` | $1 | ~1 min |
| USDC | Optimism | `optimism` | $1 | ~1 min |
| USDT | Avalanche | `avalanche` | $1 | ~1 min |
| USDC | Avalanche | `avalanche` | $1 | ~1 min |
| USDT | X Layer | `xlayer` | $1 | ~1 min |
| USDC | X Layer | `xlayer` | $1 | ~1 min |
| USD1 | BNB Chain | `bsc` | $1 | ~1 min |
| FDUSD | BNB Chain | `bsc` | $1 | ~1 min |
| DAI | Ethereum | `eth` | $5 | ~1 min |
| DAI | Arbitrum | `arbitrum` | $1 | ~1 min |
| DAI | Base | `base` | $1 | ~1 min |
| BTC | Bitcoin | `btc` | $5 | ~10 min |
| LTC | Litecoin | `ltc` | $1 | ~3 min |
| DOGE | Dogecoin | `doge` | $1 | ~1 min |
| BCH | Bitcoin Cash | `bch` | $1 | ~10 min |
| TRX | TRON | `tron` | $1 | ~1 min |
| BNB | BNB Chain | `bsc` | $1 | ~1 min |
| ETH | Ethereum | `eth` | $5 | ~1 min |
| ETH | Base | `base` | $1 | ~1 min |
| ETH | Arbitrum | `arbitrum` | $1 | ~1 min |
| ETH | Optimism | `optimism` | $1 | ~1 min |
| POL | Polygon | `polygon` | $1 | ~1 min |
| AVAX | Avalanche | `avalanche` | $1 | ~1 min |
| OKB | X Layer | `xlayer` | $1 | ~1 min |
| USDT | Solana | `sol` | $1 | ~1 min |
| USDC | Solana | `sol` | $1 | ~1 min |
| SOL | Solana | `sol` | $1 | ~1 min |
| USDT | TON | `ton` | $1 | ~1 min |
| TON | TON | `ton` | $1 | ~1 min |

Les frais ERC-20 sont élevés, le minimum est donc de 5 $ ; ceux de Bitcoin ne sont pas bas non plus, minimum 5 $ ; tout le reste est à 1 $. Les clients doivent envoyer sur le réseau affiché sur la page de paiement — l’argent envoyé sur un autre réseau n’est pas crédité automatiquement. BTC / LTC / DOGE / BCH s’affichent « détecté » dès qu’ils sont dans le mempool et comptent une fois assez confirmés ; les transactions remplacées (RBF) ou abandonnées ne comptent pas. Les cryptos natives (TRX, BNB, ETH, POL, AVAX, OKB, SOL, TON) sont cotées à un taux verrouillé et créditées en dollars américains comme BTC / LTC / DOGE / BCH ; indiquez le réseau et la crypto : factures `network: "bsc", to_currency: "BNB"`, portefeuilles statiques `network: "bsc", currency: "BNB"`. Un réseau seul vaut par défaut l’USDT de cette chaîne (l’USDC sur Base). Les transferts effectués par des contrats (multisig, paiements groupés) sont aussi reçus ; sur certaines chaînes, leur hash de transaction n’est pas disponible et `txid` dans le webhook vaut `null`.

### Erreurs

```json
{ "state": 1, "message": "amount must be a number like 10.28" }
```

| HTTP | Causes fréquentes |
| --- | --- |
| 422 | Paramètres manquants ou mal formés ; montant inférieur au minimum du réseau ; URL de callback / de redirection hors de vos domaines enregistrés ; crypto / réseau non pris en charge sur `/v1/payment` |
| 401 | Mauvais merchant, mauvais `sign` (`Invalid Sign.`) ou API key renouvelée |
| 404 | La facture n’existe pas ou n’est pas la vôtre (`Payment not found`) ; sur `/v1/wallet`, combinaison crypto / réseau non prise en charge (`The service was not found`) |
| 503 | Le réseau est momentanément indisponible — choisissez-en un autre ou n’en présélectionnez pas |

Quand la signature est mauvaise (`Invalid Sign.`), la réponse contient un objet `debug` : `body_base64` est le base64 du corps de requête que nous avons reçu (votre propre contenu, jamais l’API key) et `body_bytes` sa longueur. Comparez-le au base64 que vous avez signé : s’ils diffèrent, le corps envoyé n’est pas la chaîne signée (votre framework l’a re-sérialisé, un proxy a changé l’encodage, un retour à la ligne final) ; s’ils sont identiques, l’API key est fausse. Collez-le dans le [vérificateur de signature](https://blockwallets.io/docs/sign?lang=fr) pour voir la première différence.

```json
{
  "state": 1,
  "message": "Invalid Sign.",
  "debug": {
    "body_base64": "eyJhbW91bnQiOiI0Mi4wMCIsImN1cnJlbmN5IjoiVVNEIiwi…",
    "body_bytes": 158,
    "sign_formula": "md5(body_base64 + API key)"
  }
}
```

### FAQ

#### Mes clients rechargent le montant qu’ils veulent — quel mode ?

Les factures. Laissez le client saisir un montant sur votre page de recharge, créez une facture pour ce montant et créditez `payment_amount_usd` à l’arrivée. N’utilisez les portefeuilles statiques que si les clients doivent enregistrer une adresse et lui envoyer des fonds à répétition.

#### Que se passe-t-il si un client paie trop peu ?

Avant l’expiration, le client peut envoyer la différence depuis la page de paiement (elle indique ce qui reste dû ; statut `wrong_amount_waiting`, et s’il reste moins de 30 minutes au premier paiement insuffisant, l’échéance est repoussée à 30 minutes plus tard). S’il manque encore quelque chose à l’expiration, la facture passe à `wrong_amount` et `payment_amount_usd` dans le webhook est le montant reçu ; les activités de recharge peuvent simplement le créditer.

#### Et si un client paie en retard, ou deux fois ?

L’argent qui arrive après l’expiration est quand même crédité et notifié ; l’argent qui arrive alors qu’une facture est déjà entièrement payée est aussi enregistré et visible dans le tableau de bord.

#### Et si un client envoie sur le mauvais réseau ?

Par exemple, la facture est sur TRON et il envoie depuis BNB Chain : ce n’est pas crédité automatiquement — contactez-nous et nous le traitons manuellement.

#### Combien ça coûte ?

1% de chaque paiement reçu, abaissé automatiquement selon le volume du mois précédent (0.9% dès $50,000, 0.8% dès $100,000, 0.7% dès $250,000, 0.6% dès $500,000 et 0.5% dès $1,000,000), sans abonnement ni frais d’ouverture. Le client paie les frais de réseau à l’envoi ; pour les lui répercuter, définissez `subtract` à la création d’une facture ou comme valeur par défaut dans le tableau de bord. Les retraits n’entraînent aucun frais supplémentaire. Voir les [tarifs](https://blockwallets.io/pricing?lang=fr).

#### Quand l’argent m’arrive-t-il ?

Il est crédité sur votre solde dès que le paiement est confirmé. Demandez un retrait vers votre propre portefeuille dans « Fonds › Solde et retraits » ; une fois que nous l’approuvons, nous effectuons le versement et la transaction on-chain apparaît dans votre historique de retraits.

Vous pouvez aussi activer le retrait automatique : quand votre solde disponible atteint un montant que vous fixez, ou une fois par jour à 00:00 UTC, tout le solde disponible est retiré. Les retraits automatiques sont examinés de la même façon, et chaque modification des réglages envoie un avis à votre e-mail.
