Cripto na cobrança
Como cobrar em cripto pelo POST /charge, escolher as moedas, ler a cotação e saber quando o pagamento foi feito.
Uma cobrança em cripto é uma cobrança comum de Criar cobrança com
paymentMethod: "CRYPTO". O valor é definido na moeda da cobrança (BRL, USD ou EUR) e o pagador transfere o
equivalente em cripto. O que muda em relação a PIX e boleto está nesta página.
curl -X POST "https://api.gates2b.com/charge" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"grossAmount": "35.00",
"currency": "BRL",
"paymentMethod": "CRYPTO",
"externalReference": "pedido-0004",
"gatewayOptions": { "cryptoTickers": ["ETH_USDT"] }
}'passthroughFees: true não é aceito em cripto e responde 400.
Moedas
gatewayOptions.cryptoTickers lista as moedas aceitas. Cada item é um ticker no formato REDE_ATIVO; moedas
nativas usam só o ativo.
| Ativo | Rede | Ticker |
|---|---|---|
| USDT | Ethereum | ETH_USDT |
| USDT | BNB Smart Chain | BSC_USDT |
| USDT | Polygon | MATIC_USDT |
| USDC | Ethereum | ETH_USDC |
| USDC | Polygon | MATIC_USDC |
| ETH | Ethereum | ETH |
| BNB | BNB Smart Chain | BNB |
| MATIC | Polygon | MATIC |
- A oferta real é a das moedas habilitadas na sua conta.
cryptoTickerssó restringe esse conjunto: pedir um ticker não habilitado não o adiciona. - Omitir o campo equivale a aceitar todas as moedas habilitadas. Lista vazia responde
400. - De 1 a 20 tickers, sem repetição.
Um ticker ou vários
A quantidade de tickers muda o fluxo, não só a lista de moedas.
Um ticker: moeda travada. A cotação e a carteira são reservadas na criação. A resposta já traz endereço, valor
exato e QR Code em checkoutMeta.crypto e checkoutMeta.qr_image, e o pagador não escolhe moeda.
Com um ticker, a reserva de 20 minutos começa na criação
Use um ticker só quando o pagador vai pagar em seguida. Para link enviado por mensagem e aberto mais tarde, use vários tickers ou omita o campo, senão a reserva pode vencer antes de o pagador abrir o link.
Dois ou mais tickers, ou o campo omitido: moeda aberta. Nada é reservado. O pagador escolhe a moeda no
checkout e a reserva começa a contar depois da escolha. A resposta vem sem checkoutMeta.crypto e sem
qr_image.
Resposta da criação
A resposta é a tentativa de pagamento. O id da cobrança vem em chargeId.
{
"id": "0192f4c6-7d1e-7a3b-9c2d-4e5f6a7b8c9f",
"chargeId": "01JC8Z3R5W7Y9A1C3E5G7J9K2Q",
"status": "PROCESSING",
"paymentMethod": "CRYPTO",
"checkoutMeta": {
"url": "https://pay.gates2b.com/01JC8Z3R5W7Y9A1C3E5G7J9K2Q",
"paymentMethod": "CRYPTO",
"redirectUrl": "https://pay.provider.example/p/6f1c2a90",
"crypto": {
"ticker": "ETH_USDT",
"symbol": "USDT",
"network": "Ethereum",
"networkKey": "ethereum",
"address": "0x9f1C4b2E8a7D3c6F5e0B1a2C3d4E5f6A7b8CE4a2",
"paymentUri": "ethereum:0x9f1C4b2E8a7D3c6F5e0B1a2C3d4E5f6A7b8CE4a2?amount=6.875105",
"amount": "6875105",
"amountFormatted": "6.875105",
"expiresAt": "2026-10-22T14:20:00.000Z",
"expirationDurationMin": 20
},
"qr_image": "data:image/png;base64,iVBORw0KGgo..."
},
"checkoutUrl": "https://pay.gates2b.com/01JC8Z3R5W7Y9A1C3E5G7J9K2Q"
}| Campo | O que é |
|---|---|
checkoutUrl | Checkout onde o pagador vê endereço, valor, QR Code e prazo. Mande o pagador para cá. |
checkoutMeta.redirectUrl | Página de pagamento alternativa para esta tentativa. Não é a URL de retorno de gatewayOptions.redirectUrl. |
crypto.amount | Valor na menor unidade do token, inteiro em string. |
crypto.amountFormatted | Valor na unidade do ativo. É o que o pagador transfere. |
crypto.paymentUri | Conteúdo do QR Code, com o valor exato. |
crypto.expiresAt, crypto.expirationDurationMin | Fim e duração da reserva. Podem não vir; sem eles, a tela só perde o contador. |
Os valores em cripto são strings de propósito: um token de 18 casas decimais convertido para número de ponto flutuante perde dígitos. Guarde e compare como string ou com uma biblioteca decimal.
Exibir o valor
Se você mostrar o valor na sua própria tela, arredonde amountFormatted para cima nas casas do ativo. O número
na tela é instrução de pagamento: arredondar para baixo pede menos do que a reserva e a transferência fica
incompleta.
| Ativo | Casas | Exemplo |
|---|---|---|
| USDT, USDC, DAI, DOGE | 2 | 6.88 |
| ETH, LTC, BCH | 6 | 0.004312 |
| BTC | 8 | 0.00012345 |
| SHIB | 0 | 1240918 |
| Demais ativos | 4 | 12.3457 |
Deixe o valor exato acessível para copiar. O QR Code (paymentUri) já carrega o valor exato.
Status e prazo
O status da cobrança segue o mesmo ciclo das outras, com um status a mais, PARTIAL, para pagamento abaixo do
cotado.
PENDINGaguardando a transferência
PAIDEXPIREDainda aceita transferência atrasada
PARTIALaberta, não expira, não é paga
PAIDdispara charge.paid
Cripto tem três particularidades:
- Pagamento a menor. O pagador pode transferir menos que o cotado. A cobrança vai para
PARTIAL: continua aberta, não é paga e não expira pelo prazo. Ela viraPAIDquando o restante chega. Não libere o pedido emPARTIAL. - Prazo ancorado na reserva. Com moeda travada, o
expiresAtda cobrança passa a ser o fim da reserva de 20 minutos, não o valor enviado na criação. - Pagamento depois do prazo. Uma cobrança
EXPIREDque recebe a transferência depois do prazo ainda é creditada: viraPAIDcom o valor cheio, ouPARTIALcom valor menor.
Saber que foi pago
Assine o evento charge.paid numa inscrição de webhook. Ele é enviado quando a cobrança vira PAID, também em
cripto, e traz o externalReference. Veja Webhooks.
Os eventos crypto_payment.* não são enviados para cobranças de /charge. Eles valem só para pagamentos criados
em Criar pagamento em cripto.
Dados da liquidação
Depois do pagamento, a cobrança ganha um bloco crypto com os números da transação: moeda e rede pagas, valores
bruto e líquido em cripto e tarifas.
"crypto": {
"currency": "ETH_USDT",
"blockchain": "ETH",
"grossAmount": "6.512300",
"netAmount": "6.317931",
"fee": "0.194369",
"feePercent": 2.985,
"networkFee": "0.900000"
}O bloco aparece em lastConfirmedAttempt.crypto no detalhe da cobrança (GET /charge/me/{id}), em crypto em
cada item da listagem (GET /charge/list) e em crypto nas consultas de tentativa
(GET /charge/{chargeId}/attempts e GET /charge/attempts/{attemptId}).
Trate todos os campos do bloco como opcionais. O conteúdo varia conforme a rede e o momento da consulta, e campos
como txHash, senderAddress, paidAt e confirmations podem não vir. Use o bloco para conciliação e exibição,
não como condição para dar o pedido por pago: essa decisão é do status PAID.