Entwickler
Feste Wallets
Geben Sie jedem Ihrer Kunden eigene Einzahlungsadressen, die sich nie ändern, eine pro Netzwerk. Jede Einzahlung wird Ihrem Guthaben bei Crypto Merchant gutgeschrieben, und Ihr Server erfährt, welcher Kunde sie gesendet hat, damit Sie das richtige Konto aufladen können.
So erhalten Sie feste Wallets
403 sticky_wallets_unavailable. Sie verwenden dieselbe Basis-URL, dieselben geheimen Schlüssel und dasselbe Fehlerformat wie der Rest der API.Bevor Sie beginnen
- 1
Schließen Sie die Einrichtung ab und wählen Sie Ihre Coins. Jeder Kunde erhält eine Adresse in den Netzwerken der Coins, die Sie akzeptieren (Portal, Einstellungen).
- 2
Erstellen Sie einen geheimen Schlüssel. Öffnen Sie im Portal Entwickler und erstellen Sie einen API-Schlüssel. Er wird nur einmal angezeigt: Bewahren Sie ihn auf Ihrem Server auf, zum Beispiel als
CM_SECRET_KEY, niemals in einer Webseite oder einer App. - 3
Fügen Sie einen Webhook-Endpunkt hinzu. Fügen Sie ebenfalls unter Entwickler Ihre URL mit den Ereignissen
deposit.pending,deposit.confirmedunddeposit.dropped(oder allen Ereignissen) hinzu. Bewahren Sie sein Signaturgeheimniswhsec_…auf, um damit jede Anfrage zu prüfen.
So funktioniert es
- 1
Ein Kunde öffnet die Einzahlungsseite auf Ihrer Website.
- 2
Ihr Server ruft
POST /sticky-walletsmit Ihrer eigenen ID für diesen Kunden auf. Der erste Aufruf erstellt die Adressen, jeder spätere Aufruf liefert dieselben. - 3
Sie zeigen die Adresse mit QR-Code für den Coin an, den der Kunde wählt.
- 4
Wenn die Coins eintreffen, erhalten Sie
deposit.pendingund danndeposit.confirmed, sobald das Netzwerk sie bestätigt hat. - 5
Bei
deposit.confirmedschreiben Sie den Betrag dem Kunden gut, der insticky_wallet.referencesteht.
Wallet eines Kunden abrufen
POST/sticky-wallets
Erstellt beim ersten Aufruf die Wallet des Kunden und gibt bei jedem späteren Aufruf dieselbe zurück: 201, wenn sie gerade erstellt wurde, danach 200. Sie können den Endpunkt bedenkenlos jedes Mal aufrufen, wenn die Einzahlungsseite geöffnet wird.
Body-Parameter
referenceErforderlichstring- Ihre ID für diesen Kunden: 1 bis 120 Buchstaben, Ziffern oder
. _ : @ + -, beginnend mit einem Buchstaben oder einer Ziffer. Eine Wallet pro Referenz, dauerhaft. labelOptionalstring- Ein Name, den Sie im Portal sehen. Erneutes Senden ersetzt ihn.
metadataOptionalobject- Ein eigenes Objekt, bis zu 4 KB. Erneutes Senden ersetzt es.
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: [...] }, …]
}Das Objekt der festen Wallet
idstring- Die ID der Wallet, beginnend mit
sw_. referencestring- Ihre ID für den Kunden.
addressesarray- Ein Eintrag pro Netzwerk:
network(tron,evm,sol,btcoderltc), dieaddressund diecoins, die sie akzeptiert. Dieevm-Adresse ist auf Ethereum, BNB Smart Chain, Polygon, Base und Arbitrum dieselbe. pending_networksarray- Netzwerke, deren Adresse noch vorbereitet wird, was selten vorkommt. Rufen Sie den Endpunkt in ein paar Minuten erneut auf, dann erscheinen sie in
addresses. created_atstring- Wann die Wallet erstellt wurde.
{
"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"
}Sagen Sie Kunden, was sie senden sollen
Wallets finden
GET/sticky-wallets
GET/sticky-wallets/{id}
Suchen Sie eine Wallet über Ihre Referenz, rufen Sie eine über ihre ID ab oder blättern Sie durch alle, neueste zuerst: limit von 1 bis 100, starting_after mit der ID der letzten Wallet, die Sie haben, und has_more zeigt an, ob es weitere gibt.
# 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
}Einzahlungen auflisten
GET/deposits
Alle Einzahlungen auf die Wallets Ihrer Kunden, neueste zuerst. Filtern Sie nach sticky_wallet (einer Wallet-ID) und status (pending, confirmed oder dropped) und blättern Sie mit limit und starting_after (einer Einzahlungs-ID). So holen Sie nach, was Ihrem Server entgangen ist, wenn Webhooks nicht angekommen sind.
curl "https://cryptomerchant.online/api/v1/deposits?sticky_wallet=sw_8Kd2pQx7Vb1mNc3T&status=confirmed&limit=20" \
-H "Authorization: Bearer $CM_SECRET_KEY"Das Einzahlungsobjekt
idstring- Die ID der Einzahlung. Verwenden Sie sie, um jede Einzahlung nur einmal gutzuschreiben.
statusstringpending: im Netzwerk erkannt, wartet auf Bestätigungen.confirmed: endgültig und Ihrem Guthaben gutgeschrieben.dropped: wurde nie bestätigt.sticky_walletobject- Die Wallet, an die sie gesendet wurde:
idund Ihrereference. coinobject- Der Coin und sein Netzwerk.
amountstring- Was der Kunde gesendet hat, im Coin.
feestring- Die Gebühr, im Coin.
net_amountstring- Was Ihrem Guthaben gutgeschrieben wurde (Betrag minus Gebühr), sobald die Einzahlung bestätigt ist.
amount_usdstring- Ihr Wert in US-Dollar beim Eingang.
tx_hashstring- Der Transaktions-Hash;
explorer_urlöffnet ihn in einem Block-Explorer.
{
"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
Einzahlungsereignisse enthalten das Einzahlungsobjekt in data. Prüfen Sie die Signatur wie unter Webhooks beschrieben, bevor Sie einem Ereignis vertrauen.
deposit.pending- Eine Einzahlung auf die feste Wallet eines Ihrer Kunden wurde on-chain erkannt und wartet auf Bestätigungen.
deposit.confirmed- Eine Einzahlung auf eine feste Wallet wurde bestätigt und Ihrem Guthaben abzüglich der Gebühr gutgeschrieben: Schreiben Sie sie jetzt diesem Kunden gut.
deposit.dropped- Eine erkannte Einzahlung auf eine feste Wallet wurde nie bestätigt (fehlgeschlagen oder aus der Chain entfernt).
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]);
}
}Fehler
400invalid_request: Ein Feld fehlt oder ist falsch; die Meldung nennt das Feld.401unauthorized: Der geheime Schlüssel fehlt oder ist ungültig.403sticky_wallets_unavailable: Feste Wallets sind für dieses Unternehmen nicht freigeschaltet, oder seine Einrichtung ist noch nicht abgeschlossen.404not_found: Es gibt keine feste Wallet mit dieser ID.
Bewährte Praktiken
- Schreiben Sie einem Kunden nur bei
deposit.confirmedetwas gut, und nur einmal pro Einzahlungs-id: Ein Webhook kann mehr als einmal ankommen. - Entscheiden Sie, wer die Gebühr trägt: Schreiben Sie
net_amountgut, um sie weiterzugeben, oderamount, um sie selbst zu übernehmen. - Ihre Referenz ist der Schlüssel: Ein erneuter Aufruf von
POST /sticky-walletsist immer sicher, Sie müssen die Adressen also nicht speichern. - Bewahren Sie den geheimen Schlüssel auf Ihrem Server auf. Falls er offengelegt wurde, widerrufen Sie ihn unter Entwickler und erstellen Sie einen neuen.
- Wenn Ihr Endpunkt nicht erreichbar war, listen Sie die
confirmed-Einzahlungen auf und schreiben Sie die gut, die Sie noch nicht verarbeitet haben. - Sie bauen ein Kundenguthaben auf? Lesen Sie, wie Sie Krypto-Aufladungen für Kundenkonten einrichten.