Geliştiriciler
Sabit cüzdanlar
Her müşterinize hiç değişmeyen kendi yatırma adreslerini verin; her ağ için bir tane. Her yatırma Crypto Merchant bakiyenize eklenir ve sunucunuza hangi müşterinin gönderdiği bildirilir; böylece doğru hesaba bakiye yükleyebilirsiniz.
Sabit cüzdanlar nasıl etkinleştirilir
403 sticky_wallets_unavailable yanıtını verir. API genelindekiyle aynı temel URL'yi, gizli anahtarları ve hata biçimini kullanırlar.Başlamadan önce
- 1
Kurulumu tamamlayın ve coinlerinizi seçin. Her müşteri, kabul ettiğiniz coinlerin ağlarında bir adres alır (portal, Ayarlar).
- 2
Gizli bir anahtar oluşturun. Portalda Geliştiriciler bölümünü açın ve bir API anahtarı oluşturun. Anahtar yalnızca bir kez gösterilir: Örneğin
CM_SECRET_KEYolarak sunucunuzda saklayın, asla bir web sayfasına veya uygulamaya koymayın. - 3
Bir webhook uç noktası ekleyin. Yine Geliştiriciler altında URL adresinizi
deposit.pending,deposit.confirmedvedeposit.droppedolaylarıyla (veya tüm olaylarla) ekleyin. Her isteği doğrulamak için uç noktanın imzalama sırrını (whsec_…) saklayın.
Nasıl çalışır
- 1
Bir müşteri sitenizdeki yatırma sayfasını açar.
- 2
Sunucunuz, o müşteri için kendi kimliğinizle
POST /sticky-walletsçağrısı yapar. İlk çağrı adresleri oluşturur; sonraki her çağrı aynı adresleri döndürür. - 3
Müşterinin seçtiği coin için adresi QR koduyla birlikte gösterirsiniz.
- 4
Coinler ulaştığında önce
deposit.pending, ağ onayladıktan sonra dadeposit.confirmedolayını alırsınız. - 5
deposit.confirmedgeldiğinde tutarı,sticky_wallet.referencealanında belirtilen müşterinin hesabına eklersiniz.
Bir müşterinin cüzdanını alma
POST/sticky-wallets
İlk çağrıda müşterinin cüzdanını oluşturur, sonraki her çağrıda aynı cüzdanı döndürür: yeni oluşturulduğunda 201, sonrasında 200. Yatırma sayfası her açıldığında güvenle çağrılabilir.
Gövde parametreleri
referenceZorunlustring- Bu müşteri için kendi kimliğiniz: harf veya rakamla başlayan, 1 ile 120 arasında harf, rakam ya da
. _ : @ + -karakteri. Her referans için kalıcı olarak tek bir cüzdan. labelİsteğe bağlıstring- Portalda göreceğiniz bir ad. Yeniden gönderirseniz eskisinin yerini alır.
metadataİsteğe bağlıobject- En fazla 4 KB boyutunda kendi nesneniz. Yeniden gönderirseniz eskisinin yerini alır.
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: [...] }, …]
}Sabit cüzdan nesnesi
idstringsw_ile başlayan cüzdan kimliği.referencestring- Müşteri için kendi kimliğiniz.
addressesarray- Her ağ için bir kayıt:
network(tron,evm,sol,btcveyaltc),addressve adresin kabul ettiğicoins.evmadresi Ethereum, BNB Smart Chain, Polygon, Base ve Arbitrum üzerinde aynıdır. pending_networksarray- Adresi hâlâ hazırlanan ağlar; bu nadiren olur. Birkaç dakika sonra yeniden çağırın,
addressesiçinde görünürler. created_atstring- Cüzdanın oluşturulduğu zaman.
{
"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"
}Müşterilere ne göndereceklerini söyleyin
Cüzdanları bulma
GET/sticky-wallets
GET/sticky-wallets/{id}
Bir cüzdanı referansınızla arayın, kimliğiyle getirin veya en yeniden başlayarak tümünü sayfa sayfa gezin: limit 1 ile 100 arasında, starting_after elinizdeki son cüzdanın kimliği; has_more daha fazlası olup olmadığını gösterir.
# 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
}Yatırmaları listeleme
GET/deposits
Müşterilerinizin cüzdanlarına yapılan tüm yatırmalar, en yeniden başlayarak. sticky_wallet (bir cüzdan kimliği) ve status (pending, confirmed veya dropped) ile filtreleyin, limit ve starting_after (bir yatırma kimliği) ile sayfalayın. Sunucunuz webhook kaçırdığında eksikleri tamamlamak için kullanın.
curl "https://cryptomerchant.online/api/v1/deposits?sticky_wallet=sw_8Kd2pQx7Vb1mNc3T&status=confirmed&limit=20" \
-H "Authorization: Bearer $CM_SECRET_KEY"Yatırma nesnesi
idstring- Yatırmanın kimliği. Her yatırmayı yalnızca bir kez eklemek için kullanın.
statusstringpending: ağda görüldü, onay bekliyor.confirmed: kesinleşti ve bakiyenize eklendi.dropped: hiç onaylanmadı.sticky_walletobject- Gönderildiği cüzdan:
idve sizinreferencedeğeriniz. coinobject- Coin ve ağı.
amountstring- Müşterinin gönderdiği tutar, coin cinsinden.
feestring- Ücret, coin cinsinden.
net_amountstring- Onaylandıktan sonra bakiyenize eklenen tutar (tutar eksi ücret).
amount_usdstring- Ulaştığı andaki ABD doları cinsinden değeri.
tx_hashstring- İşlem hash değeri;
explorer_urlişlemi bir blok gezgininde açar.
{
"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"
}Webhook'lar
Yatırma olayları, yatırma nesnesini data içinde taşır. Bir olaya güvenmeden önce imzayı Webhook'lar sayfasında gösterildiği gibi doğrulayın.
deposit.pending- Müşterilerinizden birinin sabit cüzdanına yapılan bir yatırma zincir üstünde görüldü ve onay bekliyor.
deposit.confirmed- Bir sabit cüzdan yatırması onaylandı ve ücret düşülerek bakiyenize eklendi: tutarı şimdi o müşterinin hesabına ekleyin.
deposit.dropped- Görülen bir sabit cüzdan yatırması hiç onaylanmadı (başarısız oldu veya zincirden kaldırıldı).
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]);
}
}Hatalar
400invalid_request: Bir alan eksik veya yanlış; mesaj hangisi olduğunu belirtir.401unauthorized: Gizli anahtar eksik veya geçerli değil.403sticky_wallets_unavailable: Sabit cüzdanlar bu işletme için etkin değil veya işletmenin kurulumu tamamlanmadı.404not_found: Bu kimliğe sahip bir sabit cüzdan yok.
İyi uygulamalar
- Bir müşterinin hesabına yalnızca
deposit.confirmedgeldiğinde ve her yatırmaiddeğeri için yalnızca bir kez ekleme yapın: Bir webhook birden fazla kez gelebilir. - Ücreti kimin ödeyeceğine karar verin: Ücreti müşteriye yansıtmak için
net_amount, kendiniz karşılamak içinamounttutarını ekleyin. - Anahtar, referansınızdır:
POST /sticky-walletsçağrısını yeniden yapmak her zaman güvenlidir, bu yüzden adresleri saklamanız gerekmez. - Gizli anahtarı sunucunuzda saklayın. Sızarsa Geliştiriciler altında iptal edin ve yeni bir tane oluşturun.
- Uç noktanız erişilemez durumda kaldıysa
confirmeddurumundaki yatırmaları listeleyin ve henüz işlemediklerinizi müşterilerin hesabına ekleyin. - Müşterileriniz için bakiye mi oluşturuyorsunuz? Müşteri hesaplarına kripto bakiye yüklemenin nasıl ekleneceğini okuyun.