Aller au contenu
Crypto Merchant

Développeurs

Portefeuilles fixes

Donnez à chacun de vos clients ses propres adresses de dépôt, qui ne changent jamais, une par réseau. Chaque dépôt est ajouté à votre solde Crypto Merchant, et votre serveur est informé du client qui l’a envoyé, pour que vous puissiez recharger le bon compte.

Comment obtenir les portefeuilles fixes

Choisissez les portefeuilles clients à l’inscription, ou demandez au support d’activer les portefeuilles fixes sur un compte existant. Tant qu’ils ne sont pas activés, ces endpoints répondent 403 sticky_wallets_unavailable. Ils utilisent la même URL de base, les mêmes clés secrètes et le même format d’erreur que le reste de l’API.

Avant de commencer

  1. 1

    Terminez la configuration et choisissez vos cryptos. Chaque client reçoit une adresse sur les réseaux des cryptos que vous acceptez (portail, Paramètres).

  2. 2

    Créez une clé secrète. Dans le portail, ouvrez Développeurs et créez une clé API. Elle n’est affichée qu’une seule fois : conservez-la sur votre serveur, par exemple dans CM_SECRET_KEY, jamais dans une page web ou une application.

  3. 3

    Ajoutez un endpoint de webhook. Toujours sous Développeurs, ajoutez votre URL avec les événements deposit.pending, deposit.confirmed et deposit.dropped (ou tous les événements). Conservez son secret de signature, whsec_…, pour vérifier chaque requête.

Comment ça marche

  1. 1

    Un client ouvre la page de dépôt de votre site.

  2. 2

    Votre serveur appelle POST /sticky-wallets avec votre propre ID pour ce client. Le premier appel crée les adresses ; chaque appel suivant renvoie les mêmes.

  3. 3

    Vous affichez l’adresse, avec un code QR, pour la crypto choisie par le client.

  4. 4

    Quand les cryptos arrivent, vous recevez deposit.pending, puis deposit.confirmed une fois qu’elles sont confirmées par le réseau.

  5. 5

    Sur deposit.confirmed, vous créditez le client indiqué dans sticky_wallet.reference.

Obtenir le portefeuille d’un client

POST/sticky-wallets

Crée le portefeuille du client au premier appel et renvoie le même à chaque appel suivant : 201 s’il vient d’être créé, 200 ensuite. Vous pouvez l’appeler sans risque à chaque ouverture de la page de dépôt.

Paramètres du corps

referenceObligatoirestring
Votre ID pour ce client : de 1 à 120 lettres, chiffres ou . _ : @ + -, commençant par une lettre ou un chiffre. Un portefeuille par référence, définitivement.
labelFacultatifstring
Un nom que vous verrez dans le portail. Le renvoyer le remplace.
metadataFacultatifobject
Un objet de votre choix, jusqu’à 4 Ko. Le renvoyer le remplace.
curl
curl https://cryptomerchant.online/api/v1/sticky-wallets \
  -H "Authorization: Bearer $CM_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reference": "user-1042",
    "label": "Jane Doe",
    "metadata": { "plan": "pro" }
  }'
Node.js
// On your server, when a customer opens their deposit page
export async function depositAddresses(userId) {
  const res = await fetch("https://cryptomerchant.online/api/v1/sticky-wallets", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.CM_SECRET_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ reference: String(userId) }),
  });
  if (!res.ok) {
    const { error } = await res.json();
    throw new Error(`${error.code}: ${error.message}`);
  }
  const wallet = await res.json();
  return wallet.addresses; // [{ network, address, coins: [...] }, …]
}

L’objet portefeuille fixe

idstring
L’ID du portefeuille, commençant par sw_.
referencestring
Votre ID pour le client.
addressesarray
Une entrée par réseau : network (tron, evm, sol, btc ou ltc), l’address et les coins qu’elle accepte. L’adresse evm est la même sur Ethereum, BNB Smart Chain, Polygon, Base et Arbitrum.
pending_networksarray
Les réseaux dont l’adresse est encore en préparation, ce qui est rare. Rappelez l’endpoint dans quelques minutes et ils apparaîtront dans addresses.
created_atstring
La date de création du portefeuille.
sticky_wallet
{
  "id": "sw_8Kd2pQx7Vb1mNc3T",
  "object": "sticky_wallet",
  "reference": "user-1042",
  "label": "Jane Doe",
  "metadata": { "plan": "pro" },
  "addresses": [
    {
      "network": "tron",
      "address": "TXbajeGHq4Vb…",
      "coins": [
        { "id": "TRX.TRON", "symbol": "TRX", "network": "Tron" },
        { "id": "USDT.TRON", "symbol": "USDT", "network": "Tron" }
      ]
    },
    {
      "network": "evm",
      "address": "0xE550EC6d…",
      "coins": [
        { "id": "ETH.ETH", "symbol": "ETH", "network": "Ethereum" },
        { "id": "BNB.BSC", "symbol": "BNB", "network": "BNB Smart Chain" },
        { "id": "USDT.BSC", "symbol": "USDT", "network": "BNB Smart Chain" }
      ]
    }
  ],
  "pending_networks": [],
  "created_at": "2026-10-29T18:20:41.000Z"
}

Indiquez aux clients quoi envoyer

Affichez chaque adresse avec les cryptos indiquées pour elle. Les cryptos envoyées sur un autre réseau, ou les tokens non listés, ne sont pas crédités automatiquement : contactez le support si un client en envoie.

Trouver des portefeuilles

GET/sticky-wallets

GET/sticky-wallets/{id}

Recherchez un portefeuille par votre référence, récupérez-en un par son ID ou parcourez-les tous, des plus récents aux plus anciens : limit de 1 à 100, starting_after avec l’ID du dernier portefeuille que vous avez, et has_more indique s’il en reste.

curl
# By your reference
curl "https://cryptomerchant.online/api/v1/sticky-wallets?reference=user-1042" \
  -H "Authorization: Bearer $CM_SECRET_KEY"

# By id
curl https://cryptomerchant.online/api/v1/sticky-wallets/sw_8Kd2pQx7Vb1mNc3T \
  -H "Authorization: Bearer $CM_SECRET_KEY"

# All of them, 50 at a time
curl "https://cryptomerchant.online/api/v1/sticky-wallets?limit=50&starting_after=sw_8Kd2pQx7Vb1mNc3T" \
  -H "Authorization: Bearer $CM_SECRET_KEY"
Réponse
{
  "object": "list",
  "data": [ { "id": "sw_8Kd2pQx7Vb1mNc3T", "object": "sticky_wallet", … } ],
  "has_more": false
}

Lister les dépôts

GET/deposits

Tous les dépôts sur les portefeuilles de vos clients, des plus récents aux plus anciens. Filtrez par sticky_wallet (un ID de portefeuille) et status (pending, confirmed ou dropped), et paginez avec limit et starting_after (un ID de dépôt). Utilisez-le pour rattraper le retard si votre serveur a manqué des webhooks.

curl
curl "https://cryptomerchant.online/api/v1/deposits?sticky_wallet=sw_8Kd2pQx7Vb1mNc3T&status=confirmed&limit=20" \
  -H "Authorization: Bearer $CM_SECRET_KEY"

L’objet dépôt

idstring
L’ID du dépôt. Utilisez-le pour ne créditer chaque dépôt qu’une seule fois.
statusstring
pending : détecté sur le réseau, en attente de confirmations. confirmed : définitif et ajouté à votre solde. dropped : il n’a jamais été confirmé.
sticky_walletobject
Le portefeuille auquel il a été envoyé : id et votre reference.
coinobject
La crypto et son réseau.
amountstring
Ce que le client a envoyé, dans la crypto.
feestring
Les frais, dans la crypto.
net_amountstring
Ce qui a été ajouté à votre solde (montant moins frais), une fois confirmé.
amount_usdstring
Sa valeur en dollars américains à son arrivée.
tx_hashstring
Le hash de la transaction ; explorer_url l’ouvre dans un explorateur de blocs.
deposit
{
  "id": "cmvu1x9a0000l10u8k2f3h7q",
  "object": "deposit",
  "status": "confirmed",
  "sticky_wallet": { "id": "sw_8Kd2pQx7Vb1mNc3T", "reference": "user-1042" },
  "coin": { "id": "USDT.TRON", "symbol": "USDT", "network": "Tron" },
  "address": "TXbajeGHq4Vb…",
  "amount": "250",
  "amount_usd": "250.00",
  "fee": "2.5",
  "net_amount": "247.5",
  "from_address": "TQn9Y2khEsLJ…",
  "tx_hash": "36423ec5…f00d4a",
  "explorer_url": "https://tronscan.org/#/transaction/36423ec5…f00d4a",
  "confirmations": 19,
  "detected_at": "2026-10-29T18:31:02.000Z",
  "confirmed_at": "2026-10-29T18:32:01.000Z"
}

Webhooks

Les événements de dépôt contiennent l’objet dépôt dans data. Vérifiez la signature, comme indiqué dans Webhooks, avant de vous y fier.

deposit.pending
Un dépôt sur le portefeuille fixe de l’un de vos clients a été détecté sur la blockchain et attend des confirmations.
deposit.confirmed
Un dépôt sur un portefeuille fixe a été confirmé et ajouté à votre solde, frais déduits : créditez ce client maintenant.
deposit.dropped
Un dépôt détecté sur un portefeuille fixe n’a jamais été confirmé (échec ou retrait de la blockchain).
server.js · créditer le client
import express from "express";
import { verifyWebhook } from "./verify-webhook.js"; // from the Webhooks page
import { db } from "./db.js"; // your database; table webhook_events as on the Webhooks page

const app = express();

app.post(
  "/webhooks/crypto-merchant",
  express.raw({ type: "application/json" }),
  async (req, res) => {
    let event;
    try {
      event = verifyWebhook(req.body, req.get("CM-Signature"), process.env.CM_WEBHOOK_SECRET);
    } catch {
      return res.sendStatus(400);
    }
    try {
      // Save first: a repeat delivery has the same event.id and is ignored
      await db.query(
        "INSERT INTO webhook_events (id, type, payload) VALUES ($1, $2, $3) ON CONFLICT (id) DO NOTHING",
        [event.id, event.type, event],
      );
    } catch {
      return res.sendStatus(500); // not saved: we send it again later
    }
    res.sendStatus(200); // stored, so confirm it
    processEvents().catch(console.error); // or run it from a background job
  },
);

async function processEvents() {
  const { rows } = await db.query(
    "SELECT payload FROM webhook_events WHERE processed_at IS NULL ORDER BY received_at",
  );
  for (const { payload: event } of rows) {
    const deposit = event.data;
    if (event.type === "deposit.pending") {
      // Optional: show "deposit on its way" to deposit.sticky_wallet.reference
    }
    if (event.type === "deposit.confirmed") {
      // Credit once: creditCustomer must skip a deposit.id it has already credited
      await creditCustomer({
        customerId: deposit.sticky_wallet.reference,
        depositId: deposit.id,
        coin: deposit.coin.id, // e.g. "USDT.TRON"
        amount: deposit.net_amount, // or deposit.amount to cover the fee yourself
        txHash: deposit.tx_hash,
      });
    }
    await db.query("UPDATE webhook_events SET processed_at = now() WHERE id = $1", [event.id]);
  }
}

Erreurs

400
invalid_request : un champ est manquant ou erroné ; le message indique lequel.
401
unauthorized : la clé secrète est manquante ou non valide.
403
sticky_wallets_unavailable : les portefeuilles fixes ne sont pas activés pour cette entreprise, ou sa configuration n’est pas terminée.
404
not_found : aucun portefeuille fixe ne correspond à cet ID.

Bonnes pratiques

  • Ne créditez un client que sur deposit.confirmed, et une seule fois par id de dépôt : un webhook peut arriver plusieurs fois.
  • Décidez qui paie les frais : créditez net_amount pour les répercuter, ou amount pour les prendre à votre charge.
  • Votre référence est la clé : rappeler POST /sticky-wallets est toujours sans risque, vous n’avez donc pas besoin de stocker les adresses.
  • Gardez la clé secrète sur votre serveur. Si elle a fuité, révoquez-la sous Développeurs et créez-en une nouvelle.
  • Si votre endpoint était indisponible, listez les dépôts confirmed et créditez ceux que vous n’avez pas encore traités.
  • Vous créez un solde pour vos clients ? Consultez comment ajouter des recharges en crypto aux comptes clients.