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
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
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
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
Ajoutez un endpoint de webhook. Toujours sous Développeurs, ajoutez votre URL avec les événements
deposit.pending,deposit.confirmedetdeposit.dropped(ou tous les événements). Conservez son secret de signature,whsec_…, pour vérifier chaque requête.
Comment ça marche
- 1
Un client ouvre la page de dépôt de votre site.
- 2
Votre serveur appelle
POST /sticky-walletsavec votre propre ID pour ce client. Le premier appel crée les adresses ; chaque appel suivant renvoie les mêmes. - 3
Vous affichez l’adresse, avec un code QR, pour la crypto choisie par le client.
- 4
Quand les cryptos arrivent, vous recevez
deposit.pending, puisdeposit.confirmedune fois qu’elles sont confirmées par le réseau. - 5
Sur
deposit.confirmed, vous créditez le client indiqué danssticky_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 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" }
}'// 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,btcoultc), l’addresset lescoinsqu’elle accepte. L’adresseevmest 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.
{
"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
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.
# 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"{
"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 "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.
statusstringpending: 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é :
idet votrereference. 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_urll’ouvre dans un explorateur de blocs.
{
"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).
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
400invalid_request: un champ est manquant ou erroné ; le message indique lequel.401unauthorized: la clé secrète est manquante ou non valide.403sticky_wallets_unavailable: les portefeuilles fixes ne sont pas activés pour cette entreprise, ou sa configuration n’est pas terminée.404not_found: aucun portefeuille fixe ne correspond à cet ID.
Bonnes pratiques
- Ne créditez un client que sur
deposit.confirmed, et une seule fois paridde dépôt : un webhook peut arriver plusieurs fois. - Décidez qui paie les frais : créditez
net_amountpour les répercuter, ouamountpour les prendre à votre charge. - Votre référence est la clé : rappeler
POST /sticky-walletsest 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
confirmedet 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.