Desenvolvedores
Carteiras fixas
Dê a cada um dos seus clientes endereços de depósito próprios que nunca mudam, um por rede. Cada depósito é somado ao seu saldo no Crypto Merchant, e o seu servidor fica sabendo qual cliente o enviou, para que você recarregue a conta certa.
Como obter carteiras fixas
403 sticky_wallets_unavailable. Eles usam a mesma URL base, as mesmas chaves secretas e o mesmo formato de erro do restante da API.Antes de começar
- 1
Conclua a configuração e escolha suas moedas. Cada cliente recebe um endereço nas redes das moedas que você aceita (portal, Configurações).
- 2
Crie uma chave secreta. No portal, abra Desenvolvedores e crie uma chave de API. Ela é exibida só uma vez: guarde-a no seu servidor, por exemplo como
CM_SECRET_KEY, nunca em uma página web ou em um app. - 3
Adicione um endpoint de webhook. Também em Desenvolvedores, adicione a sua URL com os eventos
deposit.pending,deposit.confirmededeposit.dropped(ou todos os eventos). Guarde o segredo de assinatura dele,whsec_…, para verificar cada solicitação.
Como funciona
- 1
Um cliente abre a página de depósito do seu site.
- 2
O seu servidor chama
POST /sticky-walletscom o seu próprio ID para esse cliente. A primeira chamada cria os endereços; todas as chamadas seguintes retornam os mesmos. - 3
Você mostra o endereço, com um QR code, da moeda que o cliente escolher.
- 4
Quando as moedas chegam, você recebe
deposit.pendinge depoisdeposit.confirmed, assim que a rede as confirma. - 5
Em
deposit.confirmed, você credita o cliente indicado emsticky_wallet.reference.
Obter a carteira de um cliente
POST/sticky-wallets
Cria a carteira do cliente na primeira chamada e retorna a mesma em todas as chamadas seguintes: 201 quando ela acabou de ser criada, 200 depois disso. Você pode chamar sem problema toda vez que a página de depósito for aberta.
Parâmetros do corpo
referenceObrigatóriostring- O seu ID para este cliente: de 1 a 120 letras, números ou
. _ : @ + -, começando com uma letra ou um número. Uma carteira por referência, para sempre. labelOpcionalstring- Um nome que você verá no portal. Enviá-lo de novo o substitui.
metadataOpcionalobject- Um objeto seu, de até 4 KB. Enviá-lo de novo o substitui.
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: [...] }, …]
}O objeto de carteira fixa
idstring- O ID da carteira, começando com
sw_. referencestring- O seu ID para o cliente.
addressesarray- Uma entrada por rede:
network(tron,evm,sol,btcoultc), oaddresse ascoinsque ele aceita. O endereçoevmé o mesmo em Ethereum, BNB Smart Chain, Polygon, Base e Arbitrum. pending_networksarray- Redes cujo endereço ainda está sendo preparado, o que é raro. Chame de novo em alguns minutos e elas aparecerão em
addresses. created_atstring- Quando a carteira foi criada.
{
"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"
}Diga aos clientes o que enviar
Encontrar carteiras
GET/sticky-wallets
GET/sticky-wallets/{id}
Busque uma carteira pela sua referência, obtenha uma pelo ID ou percorra todas, das mais recentes para as mais antigas: limit de 1 a 100, starting_after com o ID da última carteira que você tem, e has_more informa se há mais.
# 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
}Listar depósitos
GET/deposits
Todos os depósitos nas carteiras dos seus clientes, dos mais recentes para os mais antigos. Filtre por sticky_wallet (um ID de carteira) e status (pending, confirmed ou dropped) e pagine com limit e starting_after (um ID de depósito). Use para recuperar o que perdeu quando o seu servidor não recebeu webhooks.
curl "https://cryptomerchant.online/api/v1/deposits?sticky_wallet=sw_8Kd2pQx7Vb1mNc3T&status=confirmed&limit=20" \
-H "Authorization: Bearer $CM_SECRET_KEY"O objeto de depósito
idstring- O ID do depósito. Use-o para creditar cada depósito uma única vez.
statusstringpending: detectado na rede, aguardando confirmações.confirmed: definitivo e somado ao seu saldo.dropped: nunca foi confirmado.sticky_walletobject- A carteira para a qual foi enviado:
ide a suareference. coinobject- A moeda e a rede dela.
amountstring- O que o cliente enviou, na moeda.
feestring- A taxa, na moeda.
net_amountstring- O que foi somado ao seu saldo (valor menos a taxa), depois de confirmado.
amount_usdstring- O valor em dólares americanos no momento em que chegou.
tx_hashstring- O hash da transação;
explorer_urla abre em um explorador de blocos.
{
"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
Os eventos de depósito trazem o objeto de depósito em data. Verifique a assinatura, como mostrado em Webhooks, antes de confiar em um deles.
deposit.pending- Um depósito na carteira fixa de um dos seus clientes foi detectado on-chain e está aguardando confirmações.
deposit.confirmed- Um depósito em carteira fixa foi confirmado e somado ao seu saldo, já descontada a taxa: credite esse cliente agora.
deposit.dropped- Um depósito detectado em carteira fixa nunca foi confirmado (falhou ou foi removido da blockchain).
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]);
}
}Erros
400invalid_request: um campo está ausente ou incorreto; a mensagem informa qual.401unauthorized: a chave secreta está ausente ou não é válida.403sticky_wallets_unavailable: as carteiras fixas não estão ativadas para esta empresa, ou a configuração dela não foi concluída.404not_found: não existe nenhuma carteira fixa com esse ID.
Boas práticas
- Credite um cliente só em
deposit.confirmed, e só uma vez poridde depósito: um webhook pode chegar mais de uma vez. - Decida quem paga a taxa: credite
net_amountpara repassá-la ao cliente, ouamountpara assumi-la você mesmo. - A sua referência é a chave: chamar
POST /sticky-walletsde novo é sempre seguro, então você não precisa guardar os endereços. - Mantenha a chave secreta no seu servidor. Se ela vazar, revogue-a em Desenvolvedores e crie uma nova.
- Se o seu endpoint ficou fora do ar, liste os depósitos
confirmede credite os que você ainda não processou. - Vai criar um saldo para seus clientes? Veja como adicionar recargas em cripto às contas de clientes.