Lewati ke konten
Crypto Merchant

Developer

Dompet tetap

Beri setiap pelanggan Anda alamat deposit sendiri yang tidak pernah berubah, satu per jaringan. Setiap deposit masuk ke saldo Crypto Merchant Anda, dan server Anda diberi tahu pelanggan mana yang mengirimnya, sehingga Anda dapat mengisi saldo akun yang tepat.

Cara mendapatkan dompet tetap

Pilih dompet pelanggan saat mendaftar, atau minta tim bantuan mengaktifkan dompet tetap untuk akun yang sudah Anda miliki. Sebelum diaktifkan, endpoint ini menjawab 403 sticky_wallets_unavailable. Endpoint ini memakai URL dasar, kunci rahasia, dan format error yang sama dengan bagian API lainnya.

Sebelum memulai

  1. 1

    Selesaikan penyiapan dan pilih koin Anda. Setiap pelanggan mendapat alamat di jaringan koin yang Anda terima (portal, Pengaturan).

  2. 2

    Buat kunci rahasia. Di portal, buka Developer dan buat kunci API. Kunci hanya ditampilkan sekali: simpan di server Anda, misalnya sebagai CM_SECRET_KEY, jangan pernah di halaman web atau aplikasi.

  3. 3

    Tambahkan endpoint webhook. Masih di Developer, tambahkan URL Anda dengan event deposit.pending, deposit.confirmed, dan deposit.dropped (atau semua event). Simpan secret penandatanganannya, whsec_…, untuk memeriksa setiap permintaan.

Cara kerjanya

  1. 1

    Pelanggan membuka halaman deposit di situs Anda.

  2. 2

    Server Anda memanggil POST /sticky-wallets dengan ID Anda sendiri untuk pelanggan tersebut. Panggilan pertama membuat alamatnya; setiap panggilan berikutnya mengembalikan alamat yang sama.

  3. 3

    Anda menampilkan alamat, beserta kode QR, untuk koin yang dipilih pelanggan.

  4. 4

    Saat koin masuk, Anda menerima deposit.pending, lalu deposit.confirmed setelah jaringan mengonfirmasinya.

  5. 5

    Saat menerima deposit.confirmed, tambahkan saldo pelanggan yang disebutkan di sticky_wallet.reference.

Mengambil dompet pelanggan

POST/sticky-wallets

Membuat dompet pelanggan pada panggilan pertama dan mengembalikan dompet yang sama pada setiap panggilan berikutnya: 201 jika baru dibuat, 200 setelahnya. Aman dipanggil setiap kali halaman deposit dibuka.

Parameter body

referenceWajibstring
ID Anda untuk pelanggan ini: 1 hingga 120 huruf, angka, atau . _ : @ + -, diawali huruf atau angka. Satu dompet per referensi, untuk selamanya.
labelOpsionalstring
Nama yang akan Anda lihat di portal. Mengirimnya lagi akan menggantinya.
metadataOpsionalobject
Objek milik Anda sendiri, hingga 4 KB. Mengirimnya lagi akan menggantinya.
curl
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" }
  }'
Node.js
// 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: [...] }, …]
}

Objek dompet tetap

idstring
ID dompet, diawali dengan sw_.
referencestring
ID Anda untuk pelanggan.
addressesarray
Satu entri per jaringan: network (tron, evm, sol, btc, atau ltc), address, dan coins yang diterimanya. Alamat evm sama di Ethereum, BNB Smart Chain, Polygon, Base, dan Arbitrum.
pending_networksarray
Jaringan yang alamatnya masih disiapkan, yang jarang terjadi. Panggil lagi dalam beberapa menit dan jaringan tersebut akan muncul di addresses.
created_atstring
Waktu dompet dibuat.
sticky_wallet
{
  "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"
}

Beri tahu pelanggan apa yang harus dikirim

Tampilkan setiap alamat bersama koin yang tercantum untuknya. Koin di jaringan lain, atau token yang tidak tercantum, tidak ditambahkan secara otomatis: hubungi tim bantuan jika pelanggan mengirimnya.

Mencari dompet

GET/sticky-wallets

GET/sticky-wallets/{id}

Cari dompet berdasarkan referensi Anda, ambil satu berdasarkan ID-nya, atau telusuri semuanya halaman demi halaman, dari yang terbaru: limit dari 1 hingga 100, starting_after berisi ID dompet terakhir yang Anda miliki, dan has_more menunjukkan apakah masih ada lagi.

curl
# 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"
Respons
{
  "object": "list",
  "data": [ { "id": "sw_8Kd2pQx7Vb1mNc3T", "object": "sticky_wallet", … } ],
  "has_more": false
}

Daftar deposit

GET/deposits

Semua deposit ke dompet pelanggan Anda, dari yang terbaru. Filter berdasarkan sticky_wallet (ID dompet) dan status (pending, confirmed, atau dropped), lalu telusuri halaman dengan limit dan starting_after (ID deposit). Gunakan untuk mengejar ketertinggalan saat server Anda melewatkan webhook.

curl
curl "https://cryptomerchant.online/api/v1/deposits?sticky_wallet=sw_8Kd2pQx7Vb1mNc3T&status=confirmed&limit=20" \
  -H "Authorization: Bearer $CM_SECRET_KEY"

Objek deposit

idstring
ID deposit. Gunakan untuk memastikan setiap deposit hanya ditambahkan sekali.
statusstring
pending: terdeteksi di jaringan, menunggu konfirmasi. confirmed: final, dan sudah masuk ke saldo Anda. dropped: tidak pernah dikonfirmasi.
sticky_walletobject
Dompet tujuan pengirimannya: id dan reference Anda.
coinobject
Koin dan jaringannya.
amountstring
Jumlah yang dikirim pelanggan, dalam koin tersebut.
feestring
Biaya, dalam koin tersebut.
net_amountstring
Jumlah yang masuk ke saldo Anda (jumlah dikurangi biaya), setelah dikonfirmasi.
amount_usdstring
Nilainya dalam dolar AS saat deposit masuk.
tx_hashstring
Hash transaksi; explorer_url membukanya di block explorer.
deposit
{
  "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

Event deposit membawa objek deposit di data. Periksa tanda tangannya, seperti dijelaskan di Webhook, sebelum memercayainya.

deposit.pending
Deposit ke dompet tetap salah satu pelanggan Anda terdeteksi on-chain dan sedang menunggu konfirmasi.
deposit.confirmed
Deposit dompet tetap dikonfirmasi dan masuk ke saldo Anda setelah dipotong biaya: tambahkan saldo pelanggan tersebut sekarang.
deposit.dropped
Deposit dompet tetap yang terdeteksi tidak pernah dikonfirmasi (gagal atau dihapus dari chain).
server.js · tambahkan saldo pelanggan
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]);
  }
}

Error

400
invalid_request: ada field yang hilang atau salah; pesannya menyebutkan field mana.
401
unauthorized: kunci rahasia tidak ada atau tidak valid.
403
sticky_wallets_unavailable: dompet tetap belum diaktifkan untuk bisnis ini, atau penyiapannya belum selesai.
404
not_found: tidak ada dompet tetap dengan ID tersebut.

Praktik yang baik

  • Tambahkan saldo pelanggan hanya saat menerima deposit.confirmed, dan hanya sekali per id deposit: webhook dapat tiba lebih dari sekali.
  • Tentukan siapa yang menanggung biaya: tambahkan net_amount untuk membebankannya ke pelanggan, atau amount untuk menanggungnya sendiri.
  • Referensi Anda adalah kuncinya: memanggil POST /sticky-wallets lagi selalu aman, jadi Anda tidak perlu menyimpan alamatnya.
  • Simpan kunci rahasia di server Anda. Jika bocor, cabut kunci tersebut di Developer dan buat yang baru.
  • Jika endpoint Anda sempat mati, ambil daftar deposit confirmed lalu tambahkan saldo untuk deposit yang belum Anda tangani.
  • Membuat saldo untuk pelanggan? Baca cara menambahkan isi saldo kripto ke akun pelanggan.