ডেভেলপার
স্থায়ী ওয়ালেট
আপনার প্রতিটি গ্রাহককে নিজের ডিপোজিট ঠিকানা দিন, যা কখনো বদলায় না, প্রতি নেটওয়ার্কে একটি করে। প্রতিটি ডিপোজিট আপনার Crypto Merchant ব্যালেন্সে যোগ হয়, আর কোন গ্রাহক সেটি পাঠিয়েছেন তা আপনার সার্ভারকে জানানো হয়, যাতে আপনি সঠিক অ্যাকাউন্ট টপ আপ করতে পারেন।
স্থায়ী ওয়ালেট কীভাবে পাবেন
403 sticky_wallets_unavailable ফেরত দেয়। এগুলো বাকি API-এর মতোই একই বেস URL, একই সিক্রেট কি এবং একই এরর ফরম্যাট ব্যবহার করে।শুরু করার আগে
- 1
সেটআপ শেষ করুন এবং আপনার কয়েন বেছে নিন। আপনি যেসব কয়েন গ্রহণ করেন, প্রতিটি গ্রাহক সেগুলোর নেটওয়ার্কে একটি করে ঠিকানা পান (পোর্টাল, সেটিংস)।
- 2
একটি সিক্রেট কি তৈরি করুন। পোর্টালে ডেভেলপার খুলে একটি API কি তৈরি করুন। এটি শুধু একবার দেখানো হয়: এটি আপনার সার্ভারে রাখুন, যেমন
CM_SECRET_KEYহিসেবে, কখনো কোনো ওয়েব পেজ বা অ্যাপে নয়। - 3
একটি ওয়েবহুক এন্ডপয়েন্ট যোগ করুন। ডেভেলপার অংশেই
deposit.pending,deposit.confirmedওdeposit.droppedইভেন্টসহ (অথবা সব ইভেন্টসহ) আপনার URL যোগ করুন। প্রতিটি রিকোয়েস্ট যাচাই করতে এর সাইনিং সিক্রেট,whsec_…, রেখে দিন।
যেভাবে কাজ করে
- 1
একজন গ্রাহক আপনার সাইটে ডিপোজিট পেজ খোলেন।
- 2
আপনার সার্ভার সেই গ্রাহকের জন্য আপনার নিজের আইডি দিয়ে
POST /sticky-walletsকল করে। প্রথম কলে ঠিকানাগুলো তৈরি হয়; পরের প্রতিটি কল একই ঠিকানা ফেরত দেয়। - 3
গ্রাহক যে কয়েন বেছে নেন, তার ঠিকানা আপনি QR কোডসহ দেখান।
- 4
কয়েন পৌঁছালে আপনি
deposit.pendingপান, তারপর নেটওয়ার্ক কনফার্ম করলেdeposit.confirmed। - 5
deposit.confirmedপেলেsticky_wallet.reference-এ উল্লেখ করা গ্রাহকের অ্যাকাউন্টে অর্থ যোগ করুন।
একজন গ্রাহকের ওয়ালেট নিন
POST/sticky-wallets
প্রথম কলে গ্রাহকের ওয়ালেট তৈরি করে এবং পরের প্রতিটি কলে সেই একই ওয়ালেট ফেরত দেয়: সদ্য তৈরি হলে 201, তারপর 200। ডিপোজিট পেজ যতবার খোলা হোক, প্রতিবার কল করা নিরাপদ।
বডি প্যারামিটার
referenceআবশ্যকstring- এই গ্রাহকের জন্য আপনার আইডি: 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- ওয়ালেটের আইডি,
sw_দিয়ে শুরু। referencestring- গ্রাহকের জন্য আপনার আইডি।
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}
আপনার রেফারেন্স দিয়ে কোনো ওয়ালেট খুঁজুন, আইডি দিয়ে একটি ওয়ালেট আনুন, অথবা নতুনগুলো আগে রেখে পেজ ধরে সবগুলো দেখুন: limit 1 থেকে 100, starting_after-এ আপনার কাছে থাকা শেষ ওয়ালেটের আইডি, আর 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 (একটি ওয়ালেট আইডি) ও status (pending, confirmed বা dropped) দিয়ে ফিল্টার করুন, আর limit ও starting_after (একটি ডিপোজিট আইডি) দিয়ে পেজ বদলান। আপনার সার্ভার কোনো ওয়েবহুক না পেলে বাদ পড়া ডিপোজিট ধরতে এটি ব্যবহার করুন।
curl "https://cryptomerchant.online/api/v1/deposits?sticky_wallet=sw_8Kd2pQx7Vb1mNc3T&status=confirmed&limit=20" \
-H "Authorization: Bearer $CM_SECRET_KEY"ডিপোজিট অবজেক্ট
idstring- ডিপোজিটের আইডি। প্রতিটি ডিপোজিট শুধু একবার যোগ করতে এটি ব্যবহার করুন।
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: এই আইডির কোনো স্থায়ী ওয়ালেট নেই।
ভালো অভ্যাস
- গ্রাহকের অ্যাকাউন্টে অর্থ শুধু
deposit.confirmedপেলে যোগ করুন, এবং প্রতিটি ডিপোজিটid-এর জন্য শুধু একবার: একটি ওয়েবহুক একাধিকবার আসতে পারে। - ফি কে দেবেন তা ঠিক করুন: ফি গ্রাহকের ওপর দিতে
net_amountযোগ করুন, অথবা নিজে বহন করতেamount। - আপনার রেফারেন্সই মূল চাবি:
POST /sticky-walletsআবার কল করা সবসময় নিরাপদ, তাই ঠিকানাগুলো সংরক্ষণ করার দরকার নেই। - সিক্রেট কি আপনার সার্ভারে রাখুন। এটি ফাঁস হলে ডেভেলপার অংশে সেটি বাতিল করে নতুন একটি তৈরি করুন।
- আপনার এন্ডপয়েন্ট বন্ধ থাকলে,
confirmedডিপোজিটগুলোর তালিকা নিন এবং যেগুলো এখনো সামলাননি সেগুলোর অর্থ যোগ করুন। - গ্রাহকদের জন্য ব্যালেন্স তৈরি করছেন? পড়ুন গ্রাহক অ্যাকাউন্টে ক্রিপ্টো টপ-আপ কীভাবে যোগ করবেন।