डेवलपर
स्थायी वॉलेट
अपने हर ग्राहक को अपने डिपॉज़िट पते दें जो कभी नहीं बदलते, हर नेटवर्क के लिए एक। हर डिपॉज़िट आपके Crypto Merchant बैलेंस में जुड़ता है, और आपके सर्वर को बताया जाता है कि उसे किस ग्राहक ने भेजा, ताकि आप सही अकाउंट टॉप अप कर सकें।
स्थायी वॉलेट कैसे पाएं
403 sticky_wallets_unavailable लौटाते हैं। ये बाकी API वाला ही बेस URL, वही सीक्रेट की और वही एरर फ़ॉर्मैट इस्तेमाल करते हैं।शुरू करने से पहले
- 1
सेटअप पूरा करें और अपने कॉइन चुनें। हर ग्राहक को उन कॉइन के नेटवर्क पर एक पता मिलता है जिन्हें आप स्वीकार करते हैं (पोर्टल, सेटिंग्स)।
- 2
सीक्रेट की बनाएँ। पोर्टल में डेवलपर खोलें और एक API की बनाएँ। यह सिर्फ़ एक बार दिखाई जाती है: इसे अपने सर्वर पर रखें, जैसे
CM_SECRET_KEYके रूप में, कभी किसी वेब पेज या ऐप में नहीं। - 3
वेबहुक एंडपॉइंट जोड़ें। डेवलपर में ही अपना URL
deposit.pending,deposit.confirmedऔरdeposit.droppedइवेंट (या सभी इवेंट) के साथ जोड़ें। हर रिक्वेस्ट जाँचने के लिए उसका साइनिंग सीक्रेट,whsec_…, संभालकर रखें।
यह कैसे काम करता है
- 1
कोई ग्राहक आपकी साइट पर डिपॉज़िट पेज खोलता है।
- 2
आपका सर्वर उस ग्राहक के लिए आपकी अपनी ID के साथ
POST /sticky-walletsकॉल करता है। पहली कॉल पते बनाती है; बाद की हर कॉल वही पते लौटाती है। - 3
ग्राहक जो कॉइन चुनता है, उसके लिए आप पता QR कोड के साथ दिखाते हैं।
- 4
कॉइन आने पर आपको
deposit.pendingमिलता है, फिर नेटवर्क के कन्फ़र्म करते हीdeposit.confirmed। - 5
deposit.confirmedमिलने पर आपsticky_wallet.referenceमें बताए गए ग्राहक के अकाउंट में राशि जोड़ते हैं।
किसी ग्राहक का वॉलेट पाएँ
POST/sticky-wallets
पहली कॉल पर ग्राहक का वॉलेट बनाता है और बाद की हर कॉल पर वही वॉलेट लौटाता है: अभी बना हो तो 201, उसके बाद 200। जब भी डिपॉज़िट पेज खुले, इसे कॉल करना सुरक्षित है।
बॉडी पैरामीटर
referenceज़रूरीstring- इस ग्राहक के लिए आपकी ID: 1 से 120 अक्षर, अंक या
. _ : @ + -, जो किसी अक्षर या अंक से शुरू हो। हर रेफ़रेंस का हमेशा के लिए एक वॉलेट। labelवैकल्पिकstring- एक नाम जो आपको पोर्टल में दिखेगा। दोबारा भेजने पर यह बदल जाता है।
metadataवैकल्पिकobject- आपका अपना ऑब्जेक्ट, 4 KB तक। दोबारा भेजने पर यह बदल जाता है।
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: [...] }, …]
}स्थायी वॉलेट ऑब्जेक्ट
idstring- वॉलेट की ID, जो
sw_से शुरू होती है। referencestring- ग्राहक के लिए आपकी ID।
addressesarray- हर नेटवर्क के लिए एक एंट्री:
network(tron,evm,sol,btcयाltc),addressऔर वेcoinsजिन्हें यह स्वीकार करता है।evmपता Ethereum, BNB Smart Chain, Polygon, Base और Arbitrum पर एक ही है। pending_networksarray- वे नेटवर्क जिनका पता अभी तैयार हो रहा है, जो कम ही होता है। कुछ मिनट बाद फिर से कॉल करें, ये
addressesमें आ जाएँगे। created_atstring- वॉलेट कब बनाया गया।
{
"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"
}ग्राहकों को बताएँ कि क्या भेजना है
वॉलेट खोजें
GET/sticky-wallets
GET/sticky-wallets/{id}
अपने रेफ़रेंस से कोई वॉलेट खोजें, ID से कोई वॉलेट पाएँ, या सभी वॉलेट पेज दर पेज देखें, सबसे नए पहले: limit 1 से 100 तक, starting_after में आपके पास मौजूद आख़िरी वॉलेट की ID, और has_more बताता है कि और हैं या नहीं।
# 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
}डिपॉज़िट की सूची
GET/deposits
आपके ग्राहकों के वॉलेट में आए सभी डिपॉज़िट, सबसे नए पहले। sticky_wallet (वॉलेट ID) और status (pending, confirmed या dropped) से फ़िल्टर करें, और limit व starting_after (डिपॉज़िट ID) से पेज बदलें। जब आपके सर्वर तक कुछ वेबहुक न पहुँचे हों, तब छूटे हुए डिपॉज़िट पकड़ने के लिए इसका इस्तेमाल करें।
curl "https://cryptomerchant.online/api/v1/deposits?sticky_wallet=sw_8Kd2pQx7Vb1mNc3T&status=confirmed&limit=20" \
-H "Authorization: Bearer $CM_SECRET_KEY"डिपॉज़िट ऑब्जेक्ट
idstring- डिपॉज़िट की ID। इससे हर डिपॉज़िट की राशि सिर्फ़ एक बार जोड़ें।
statusstringpending: नेटवर्क पर दिखा, कन्फ़र्मेशन का इंतज़ार।confirmed: पक्का, और आपके बैलेंस में जुड़ गया।dropped: यह कभी कन्फ़र्म नहीं हुआ।sticky_walletobject- जिस वॉलेट में यह भेजा गया:
idऔर आपकाreference। coinobject- कॉइन और उसका नेटवर्क।
amountstring- ग्राहक ने जो भेजा, कॉइन में।
feestring- शुल्क, कॉइन में।
net_amountstring- कन्फ़र्म होने के बाद आपके बैलेंस में जो जुड़ा (राशि में से शुल्क घटाकर)।
amount_usdstring- आने के समय अमेरिकी डॉलर में इसकी वैल्यू।
tx_hashstring- ट्रांज़ैक्शन हैश;
explorer_urlइसे किसी ब्लॉक एक्सप्लोरर पर खोलता है।
{
"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"
}वेबहुक
डिपॉज़िट इवेंट में data के अंदर डिपॉज़िट ऑब्जेक्ट होता है। किसी इवेंट पर भरोसा करने से पहले सिग्नेचर जाँचें, जैसा वेबहुक में बताया गया है।
deposit.pending- आपके किसी ग्राहक के स्थायी वॉलेट में ऑन-चेन एक डिपॉज़िट दिखा है और वह कन्फ़र्मेशन का इंतज़ार कर रहा है।
deposit.confirmed- एक स्थायी वॉलेट डिपॉज़िट कन्फ़र्म हुआ और शुल्क कटकर आपके बैलेंस में जुड़ गया: अब उस ग्राहक के अकाउंट में राशि जोड़ें।
deposit.dropped- दिखा हुआ एक स्थायी वॉलेट डिपॉज़िट कभी कन्फ़र्म नहीं हुआ (नाकाम रहा या चेन से हट गया)।
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]);
}
}एरर
400invalid_request: कोई फ़ील्ड मौजूद नहीं है या ग़लत है; मैसेज बताता है कि कौन-सा।401unauthorized: सीक्रेट की मौजूद नहीं है या मान्य नहीं है।403sticky_wallets_unavailable: इस बिज़नेस के लिए स्थायी वॉलेट चालू नहीं हैं, या इसका सेटअप पूरा नहीं हुआ है।404not_found: उस ID का कोई स्थायी वॉलेट नहीं है।
अच्छे तरीक़े
- किसी ग्राहक के अकाउंट में राशि सिर्फ़
deposit.confirmedपर जोड़ें, और हर डिपॉज़िटidके लिए सिर्फ़ एक बार: कोई वेबहुक एक से ज़्यादा बार आ सकता है। - तय करें कि शुल्क कौन देगा: शुल्क ग्राहक पर डालने के लिए
net_amountजोड़ें, या खुद उठाने के लिएamount। - आपका रेफ़रेंस ही असली चाबी है:
POST /sticky-walletsको दोबारा कॉल करना हमेशा सुरक्षित है, इसलिए आपको पते सेव करने की ज़रूरत नहीं। - सीक्रेट की अपने सर्वर पर रखें। अगर यह लीक हो जाए, तो डेवलपर में इसे रद्द करें और नई की बनाएँ।
- अगर आपका एंडपॉइंट बंद था, तो
confirmedडिपॉज़िट की सूची लें और जिन्हें आपने अभी तक नहीं संभाला है, उनकी राशि जोड़ें। - ग्राहकों के लिए बैलेंस बना रहे हैं? पढ़ें ग्राहक खातों में क्रिप्टो टॉप-अप कैसे जोड़ें।