# API da blockwallets compatível com a Cryptomus

> A API da blockwallets compatível com a Cryptomus: cobranças e carteiras estáticas, assinatura, webhooks e verificação, modo de teste, redes, erros e migração da Cryptomus trocando o domínio.
>
> HTML: https://blockwallets.io/docs/cryptomus?lang=pt · English: https://blockwallets.io/docs/cryptomus.md?lang=en

## API compatível com a Cryptomus

A blockwallets permite que você aceite USDT e USDC, além de BTC, LTC, DOGE, BCH e moedas nativas (creditadas em dólares americanos a uma cotação travada): o cliente paga, nós confirmamos na blockchain e avisamos você. A API, as assinaturas e os webhooks são os mesmos da **Cryptomus**: se você já integrou a Cryptomus, troque o domínio e pronto. Primeiro como funciona, depois a API.

### Duas formas de receber

As duas aceitam **qualquer valor**: pedidos de preço fixo e recargas em que o cliente digita o valor. Depois de pago, você envia o pedido ou credita o saldo do cliente. A única diferença é **se cada pagamento recebe um endereço novo**.

Recomendado · a maioria das integrações**Cobranças**
O cliente escolhe um produto ou digita um valor na sua página, você cria uma cobrança e ele envia o valor exibido na página de pagamento. Cada cobrança tem um endereço novo e uma contagem regressiva; quando o pagamento chega, avisamos você com o valor realmente recebido.

`POST /v1/payment` → webhook `type: payment`

Opcional**Carteiras estáticas**
Sem valor definido antes: cada cliente recebe um endereço permanente por rede, para salvar na própria carteira e enviar a qualquer momento. Cada transferência dispara o seu próprio webhook.

`POST /v1/wallet` → webhook `type: wallet`

Em caso de dúvida, use cobranças. Sem código, os [links de pagamento](https://blockwallets.io/docs/cryptomus?lang=pt#links) do painel são cobranças criadas para você. Ainda não é lojista? Solicite acesso na [página inicial](https://blockwallets.io/?lang=pt#join); depois de aprovado, entre no [painel do lojista](https://blockwallets.io/dashboard) e comece por “Testar um pagamento” na página inicial do painel, pagando um valor pequeno (o dinheiro vai para o seu próprio saldo).

### Como uma cobrança evolui

Um pagamento envolve quatro partes: o cliente, o seu site, a blockwallets e a blockchain. O diagrama corre de cima para baixo no tempo; a coluna da direita é o status da cobrança em cada etapa.

Resumindo, cinco etapas:

- Você cria uma cobrança (um link de pagamento faz isso por você, ou o seu servidor chama `/v1/payment`), recebe a `url` da página de pagamento e redireciona o cliente para lá.

- Na página de pagamento, o cliente escolhe uma moeda e uma rede, recebe um endereço e um valor exclusivos e paga a partir de uma carteira ou de uma corretora.

- Vemos a transferência na blockchain, esperamos confirmações suficientes e então a conferimos com um segundo provedor de nós (para que um nó não consiga forjá-la).

- A cobrança vira `paid` e na mesma hora enviamos um webhook assinado por POST para o seu `url_callback`; alguns segundos depois, a página de pagamento devolve o cliente ao seu `url_success`.

- O dinheiro é creditado no seu saldo; saque para a sua própria carteira pelo painel do lojista.

#### Status da cobrança

| status | Significado | O que você faz |
| --- | --- | --- |
| `check` | Aguardando pagamento | — |
| `confirm_check` | Transferência detectada, aguardando confirmações | — |
| `wrong_amount_waiting` | Recebido, mas insuficiente; o cliente pode complementar no mesmo endereço (quando `is_payment_multiple` é true; notificado uma vez) | — (você recebe `paid` quando for complementado) |
| `paid` | Paga | Envie / credite conforme `payment_amount_usd` |
| `paid_over` | Paga, com pagamento a mais | O mesmo (`payment_amount_usd` é o valor recebido) |
| `wrong_amount` | Expirada com menos que o valor total (com `is_payment_multiple` false: a primeira transferência insuficiente) | Negócios de recarga podem creditar o `payment_amount_usd` recebido; lojas pedem ao cliente que pague o restante |
| `cancel` | Expirada sem nada recebido | — (o dinheiro que chegar depois ainda é creditado e notificado) |

Quando `is_final` é `true`, o status não muda mais (exceto por pagamentos tardios).

### Links de pagamento (sem código)

Painel do lojista → “Recebimentos › Links de pagamento” → informe uma descrição e um valor (fixe uma rede ou deixe o cliente escolher) → criar. Cada link tem uma URL e um QR code.

- Toda vez que alguém abre o link, uma nova cobrança é criada, então um mesmo link pode ser reutilizado (p. ex. “Plano de membros $99”).

- Cada pagamento aparece em “Recebimentos › Transações”; saque-o para a sua carteira em “Fundos › Saldo e saques”.

- Se você criou credenciais e uma URL de webhook em “Desenvolvedores › Integração e chaves”, os pagamentos feitos por links também são notificados no formato abaixo.

- Para parar de receber, clique em “Desativar” e o link deixa de funcionar imediatamente.

### Integração por API

#### 1. Credenciais e assinatura

Painel do lojista → “Desenvolvedores › Integração e chaves” → gere um **merchant** (UUID) e uma **API key**. Há um conjunto para Live e outro para Test: Live movimenta dinheiro real, Test roda em testnets. Cadastre também os **domínios do seu site**: `url_callback`, `url_return` e `url_success` precisam estar neles. A API key é exibida uma única vez: guarde-a bem e somente no seu servidor.

URL base `https://blockwallets.io`. Todo endpoint é `POST` + JSON, com estes cabeçalhos:

- `merchant`: o UUID do seu merchant (é ele que define Live ou Test)

- `sign`: `md5(base64(request body) + API key)`, onde o corpo é exatamente a string JSON que você envia

Em caso de sucesso retorna `{"state": 0, "result": {…}}`; em caso de falha, `{"state": 1, "message": "…"}` (veja [Erros](https://blockwallets.io/docs/cryptomus?lang=pt#errors)).

Os principais endpoints abaixo têm um painel “Testar”: informe o seu merchant e a API key de Test, e a página assina a requisição no seu navegador, chama o endpoint e mostra a requisição e a resposta completas (as credenciais ficam só na memória da página). Se uma assinatura não bater, compare-a passo a passo com o [verificador de assinatura](https://blockwallets.io/docs/sign?lang=pt).

```nodejs
import crypto from "node:crypto";

async function call(path, data) {
  const body = JSON.stringify(data);
  const sign = crypto.createHash("md5").update(Buffer.from(body).toString("base64") + process.env.BW_API_KEY).digest("hex");
  const res = await fetch("https://blockwallets.io" + path, {
    method: "POST",
    headers: { merchant: process.env.BW_MERCHANT, sign, "Content-Type": "application/json" },
    body,
  });
  return res.json();
}
```

```php
function bw_call(string $path, array $data): array {
    $body = json_encode($data, JSON_UNESCAPED_UNICODE);
    $sign = md5(base64_encode($body) . getenv('BW_API_KEY'));
    $ch = curl_init('https://blockwallets.io' . $path);
    curl_setopt_array($ch, [
        CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => ['merchant: ' . getenv('BW_MERCHANT'), 'sign: ' . $sign, 'Content-Type: application/json'],
    ]);
    return json_decode(curl_exec($ch), true);
}
```

```python
import base64, hashlib, json, os, requests

def bw_call(path: str, data: dict) -> dict:
    body = json.dumps(data, separators=(",", ":"), ensure_ascii=False)
    sign = hashlib.md5((base64.b64encode(body.encode()).decode() + os.environ["BW_API_KEY"]).encode()).hexdigest()
    headers = {"merchant": os.environ["BW_MERCHANT"], "sign": sign, "Content-Type": "application/json"}
    return requests.post("https://blockwallets.io" + path, data=body.encode(), headers=headers).json()
```

#### 2. Criar uma cobrança POST /v1/payment

Quando o cliente faz um pedido, ou digita um valor na sua página de recarga, chame `https://blockwallets.io/v1/payment` e redirecione-o para o `result.url` retornado.

```json
{
  "amount": "42.00",
  "currency": "USD",
  "order_id": "order_1042",
  "url_callback": "https://shop.example/webhooks/crypto",
  "url_return": "https://shop.example/cart",
  "url_success": "https://shop.example/thanks?order=1042"
}
```

| Parâmetro | Obrigatório | Descrição |
| --- | --- | --- |
| `amount` | Sim | Valor como string, com até duas casas decimais: `"42.00"`. O seu preço ou um número digitado pelo cliente; não abaixo do mínimo da rede escolhida (veja [redes](https://blockwallets.io/docs/cryptomus?lang=pt#networks)) |
| `currency` | Sim | `USD`, `USDT` ou `USDC`, todas 1:1 |
| `order_id` | Sim | O número do seu pedido: letras, dígitos, `-`, `_`, ≤ 100 caracteres. Chamar de novo com o mesmo order_id retorna a cobrança existente (sem pedidos duplicados) |
| `url_callback` | Não | URL do webhook. Se omitida, nenhum webhook é enviado |
| `url_return` | Não | Para onde vai o “Voltar” antes de pagar |
| `url_success` | Não | Para onde o cliente vai depois de pagar |
| `network` | Não | Pré-selecionar uma rede: `tron` / `bsc` / `eth` / `base` / `polygon` / `arbitrum` / `optimism` / `avalanche` / `xlayer` / `btc` / `ltc` / `doge` / `bch` / `sol` / `ton`; se omitida, o cliente escolhe na página de pagamento |
| `to_currency` | Não | Moeda nessa rede: `USDT` / `USDC`; em `btc` / `ltc` / `doge` / `bch` é `BTC` / `LTC` / `DOGE` / `BCH` (opcional) |
| `lifetime` | Não | Duração da cobrança em segundos, de 300 a 43200, padrão 3600; qualquer valor abaixo de 600 conta como 600 |
| `accuracy_payment_percent` | Não | Quanto de pagamento a menos ainda conta como pago, de 0 a 5, padrão 0. `100` = aceitar o que chegar: `paid` assim que confirmar (`paid_over` se for mais), crédito por `payment_amount_usd` no webhook — bom para recargas. Se omitido, vale a “Regra de valor” em “Configurações › Regras de recebimento e taxas” no painel: “creditar o que chegar” significa 100 |
| `subtract` | Não | Parcela da taxa da plataforma paga pelo cliente, de 0 a 100, somada a `payer_amount` (a taxa da plataforma é 1%, menor com mais volume; a 1%, com 100, uma cobrança de $100 custa ao cliente $101.00; veja os [preços](https://blockwallets.io/pricing?lang=pt)). Se omitido, vale a configuração “Taxas e pagamentos a menos” em “Configurações › Regras de recebimento e taxas” no painel (padrão 0) |
| `is_payment_multiple` | Não | Se um pagamento a menos pode ser complementado, padrão true: status `wrong_amount_waiting`; pagar o restante no mesmo endereço a torna `paid` (se restarem menos de 30 minutos no primeiro pagamento a menos, o prazo é movido para 30 minutos depois). false: a primeira transferência insuficiente a torna `wrong_amount`. Se omitido, vale a configuração do painel |
| `additional_data` | Não | Qualquer string (≤ 255), devolvida como está nas consultas e nos webhooks |

```json
{
  "state": 0,
  "result": {
    "uuid": "6f1c2a7e-…",
    "order_id": "order_1042",
    "amount": "42.00",
    "currency": "USD",
    "network": null,
    "address": null,
    "payer_amount": null,
    "payment_amount": null,
    "url": "https://blockwallets.io/pay/inv_01J8…",
    "expired_at": 1760965200,
    "status": "check",
    "is_final": false
  }
}
```

`network`, `address` e `payer_amount` são preenchidos assim que o cliente escolhe uma rede.

#### 3. Consultar cobranças

- `POST /v1/payment/info` `{"order_id": "…"}` ou `{"uuid": "…"}`: busca uma cobrança e confere a blockchain no caminho (no máximo uma vez a cada 10 segundos).

- `POST /v1/payment/list`: lista, 15 por página, com `date_from` / `date_to` opcionais; a próxima página vem pelo `paginate.nextCursor` retornado (`?cursor=…`).

- `POST /v1/payment/services`: redes disponíveis e o valor mínimo de cada uma.

- `POST /v1/payment/resend` `{"order_id": "…"}`: reenvia o webhook de uma cobrança paga / paga a menos.

Os webhooks são o canal principal; as consultas são o plano B (por exemplo, se o seu servidor estava fora do ar e perdeu um webhook).

#### 4. Carteiras estáticas POST /v1/wallet

Abre um endereço permanente para um cliente em uma rede. O mesmo `order_id` (normalmente o ID do seu usuário) + rede sempre dá o mesmo endereço; todas as redes EVM (BNB Chain, Ethereum, Base, Polygon, Arbitrum, Optimism, Avalanche, X Layer) compartilham um endereço, enquanto TRON, BTC, LTC, DOGE, BCH, Solana e TON têm cada uma o seu. Tudo que o cliente enviar é creditado, com um webhook por transferência; as transferências em BTC / LTC / DOGE / BCH / TRX / BNB / ETH / POL / AVAX / OKB / SOL / TON são convertidas em dólares americanos pela cotação do momento em que cada uma foi vista (`payment_amount_usd`).

```json
{
  "order_id": "user_42",
  "currency": "USDT",
  "network": "tron",
  "url_callback": "https://shop.example/webhooks/crypto"
}
```

```json
{
  "state": 0,
  "result": {
    "wallet_uuid": "0b9d…",
    "uuid": "5e2f…",
    "order_id": "user_42",
    "currency": "USDT",
    "network": "tron",
    "address": "TXy4…8kQ2",
    "url": "https://blockwallets.io/deposit/dac_01J8…"
  }
}
```

`result.url` é uma página de depósito hospedada (endereço + QR code + depósitos recentes) que você pode entregar ao cliente. Transferências abaixo do mínimo da rede (geralmente $1, BTC $5) não são creditadas automaticamente; fale com a gente para creditá-las. O bloqueio de endereços (`/v1/wallet/block-address`) ainda não é suportado.

### Webhooks

Quando o status de uma cobrança muda (`paid`, `paid_over`, `wrong_amount_waiting`, `wrong_amount`, `cancel`) e a cada transferência para uma carteira estática, enviamos um POST com JSON para `url_callback`. Uma resposta 2xx conta como entregue; caso contrário, tentamos de novo após 1 minuto, 5 minutos, 30 minutos, 2 horas, 12 horas, 24 horas e 24 horas. Você também pode reenviar pelo painel ou com `/v1/payment/resend`.

```json
{
  "type": "payment",
  "uuid": "6f1c2a7e-…",
  "order_id": "order_1042",
  "amount": "42.00",
  "payment_amount": "42",
  "payment_amount_usd": "42.00",
  "merchant_amount": "41.58",
  "commission": "0.42",
  "is_final": true,
  "status": "paid",
  "from": "TQ8m…",
  "wallet_address_uuid": null,
  "network": "tron",
  "currency": "USD",
  "payer_currency": "USDT",
  "payer_amount": "42",
  "payer_amount_exchange_rate": "1",
  "additional_data": null,
  "txid": "9c1e…",
  "sign": "5f0c9b…"
}
```

| type | Quando | Crédito |
| --- | --- | --- |
| `payment` | O status de uma cobrança mudou — veja `status` | Credite `payment_amount_usd` em `paid` / `paid_over`; deduplique por `uuid` |
| `wallet` | Uma transferência chegou a uma carteira estática (`status` é sempre `paid`; `order_id` é aquele com que você abriu a carteira) | Credite `payment_amount_usd`; cada transferência tem o seu próprio `uuid` — deduplique por ele |

#### Verificar a assinatura (obrigatório)

A assinatura é o campo `sign` do corpo do webhook: remova `sign`, recodifique o resto como o `json_encode` do PHP faz (compacto, `/` escapada como `\/`, caracteres não ASCII sem escape) e `md5(base64(encoded) + API key)` deve ser igual a `sign`. Use a API key do mesmo modo. O mesmo webhook pode chegar mais de uma vez — deduplique por `uuid` + `status`.

Se a verificação falhar, cole o corpo bruto do webhook no [verificador de assinatura](https://blockwallets.io/docs/sign?lang=pt): ele mostra o resultado de cada etapa e marca onde a sua difere (tudo roda no seu navegador; a API key nunca é enviada). Todo webhook de “Desenvolvedores › Log de webhooks” no painel abre no verificador com um clique.

```nodejs
import crypto from "node:crypto";

function verify(rawBody, apiKey) {
  const { sign, ...data } = JSON.parse(rawBody);
  const json = JSON.stringify(data).replaceAll("/", "\\/");
  const expected = crypto.createHash("md5").update(Buffer.from(json).toString("base64") + apiKey).digest("hex");
  return typeof sign === "string" && sign.length === expected.length && crypto.timingSafeEqual(Buffer.from(sign), Buffer.from(expected));
}
```

```php
$data = json_decode(file_get_contents('php://input'), true);
$sign = $data['sign'] ?? '';
unset($data['sign']);
$expected = md5(base64_encode(json_encode($data, JSON_UNESCAPED_UNICODE)) . $apiKey);
if (!hash_equals($expected, $sign)) {
    http_response_code(401); exit;
}
```

```python
import base64, hashlib, hmac, json

def verify(raw_body: bytes, api_key: str) -> bool:
    data = json.loads(raw_body)
    sign = data.pop("sign", "")
    encoded = json.dumps(data, separators=(",", ":"), ensure_ascii=False).replace("/", "\\/")
    expected = hashlib.md5((base64.b64encode(encoded.encode()).decode() + api_key).encode()).hexdigest()
    return hmac.compare_digest(expected, sign)
```

### Modo de teste

As cobranças criadas com o merchant e a API key de Test rodam em testnets, sem dinheiro real. A página de pagamento mostra um botão “Simular pagamento” (total / metade / a mais), para você ver as mudanças de status e os webhooks sem precisar de moedas de testnet.

- `POST /v1/test-webhook/payment`, `/v1/test-webhook/wallet`: enviam um webhook de exemplo assinado para `url_callback` (informe `url_callback`, obrigatório e em um dos seus domínios cadastrados, além de `currency`, `network` e, opcionalmente, `status`, `order_id`) para depurar o seu código de verificação.

- Painel “Desenvolvedores › Integração e chaves” → “Enviar uma notificação de teste”: envia um exemplo para a sua URL de webhook.

- Painel “Desenvolvedores › Log de webhooks”: cada tentativa de entrega com horário, URL de destino, status HTTP, duração, corpo da requisição e a resposta do seu servidor (primeiros 4 KB); filtre por pedido ou status e reenvie com um clique. Guardado por 30 dias.

### Migrando da Cryptomus

- Painel “Desenvolvedores › Integração e chaves” → gere um merchant e uma API key.

- Troque `https://api.cryptomus.com` no seu código por `https://blockwallets.io` e use o novo merchant e a nova API key.

- Cadastre os seus domínios em “Domínios do site” (`url_callback` / `url_return` / `url_success` só aceitam esses).

Suportados: `/v1/payment`, `/v1/payment/info`, `/v1/payment/list`, `/v1/payment/services`, `/v1/payment/resend`, `/v1/wallet`, `/v1/test-webhook/payment`, `/v1/test-webhook/wallet`. Diferenças: as cobranças são precificadas apenas em USD / USDT / USDC (todas 1:1, sem spread de câmbio); `commission` é a nossa taxa da plataforma (o valor recebido × a taxa do lojista quando a cobrança foi criada — 1% padrão, chegando a 0.5% conforme o volume; nada é cobrado duas vezes sobre a parte que o cliente cobre) e `merchant_amount` = recebido − `commission`; quando o cliente paga em BTC / LTC / DOGE / BCH / TRX / BNB / ETH / POL / AVAX / OKB / SOL / TON, cotamos a mediana de várias corretoras, travada por 30 minutos — `payer_amount` é o número de moedas a enviar, `payer_amount_exchange_rate` é o valor em USD de uma moeda, e o pagamento é convertido em `payment_amount_usd` pela cotação travada (as moedas ficam conosco, nada é trocado); redes `tron` / `bsc` / `eth` / `base` / `polygon` / `arbitrum` / `optimism` / `avalanche` / `xlayer` / `btc` / `ltc` / `doge` / `bch` / `sol` / `ton`; duração mínima da cobrança de 10 minutos; sem `is_refresh` e sem bloqueio de carteiras estáticas; por padrão os webhooks vêm de IPs variáveis; se você usa lista de IPs permitidos, ative “Webhooks com IP fixo” no painel, em “Desenvolvedores › Integração e chaves”, e os webhooks virão apenas de `18.163.145.41` — uma lista de permitidos é uma camada extra, continue verificando `sign`.

Vindo da **NOWPayments** ou da **Coinbase Commerce**? Temos APIs compatíveis com as duas — troque a URL base e as chaves; veja o [guia de migração](https://blockwallets.io/docs/migrate?lang=pt).

### Redes e valores

| Moeda | Rede | Parâmetro network | Mínimo | Chegada |
| --- | --- | --- | --- | --- |
| USDT | TRON | `tron` | $1 | ~1 min |
| USDT | BNB Chain | `bsc` | $1 | ~1 min |
| USDC | BNB Chain | `bsc` | $1 | ~1 min |
| USDT | Ethereum | `eth` | $5 | ~1 min |
| USDC | Ethereum | `eth` | $5 | ~1 min |
| USDC | Base | `base` | $1 | ~1 min |
| USDT | Polygon | `polygon` | $1 | ~1 min |
| USDC | Polygon | `polygon` | $1 | ~1 min |
| USDT | Arbitrum | `arbitrum` | $1 | ~1 min |
| USDC | Arbitrum | `arbitrum` | $1 | ~1 min |
| USDT | Optimism | `optimism` | $1 | ~1 min |
| USDC | Optimism | `optimism` | $1 | ~1 min |
| USDT | Avalanche | `avalanche` | $1 | ~1 min |
| USDC | Avalanche | `avalanche` | $1 | ~1 min |
| USDT | X Layer | `xlayer` | $1 | ~1 min |
| USDC | X Layer | `xlayer` | $1 | ~1 min |
| USD1 | BNB Chain | `bsc` | $1 | ~1 min |
| FDUSD | BNB Chain | `bsc` | $1 | ~1 min |
| DAI | Ethereum | `eth` | $5 | ~1 min |
| DAI | Arbitrum | `arbitrum` | $1 | ~1 min |
| DAI | Base | `base` | $1 | ~1 min |
| BTC | Bitcoin | `btc` | $5 | ~10 min |
| LTC | Litecoin | `ltc` | $1 | ~3 min |
| DOGE | Dogecoin | `doge` | $1 | ~1 min |
| BCH | Bitcoin Cash | `bch` | $1 | ~10 min |
| TRX | TRON | `tron` | $1 | ~1 min |
| BNB | BNB Chain | `bsc` | $1 | ~1 min |
| ETH | Ethereum | `eth` | $5 | ~1 min |
| ETH | Base | `base` | $1 | ~1 min |
| ETH | Arbitrum | `arbitrum` | $1 | ~1 min |
| ETH | Optimism | `optimism` | $1 | ~1 min |
| POL | Polygon | `polygon` | $1 | ~1 min |
| AVAX | Avalanche | `avalanche` | $1 | ~1 min |
| OKB | X Layer | `xlayer` | $1 | ~1 min |
| USDT | Solana | `sol` | $1 | ~1 min |
| USDC | Solana | `sol` | $1 | ~1 min |
| SOL | Solana | `sol` | $1 | ~1 min |
| USDT | TON | `ton` | $1 | ~1 min |
| TON | TON | `ton` | $1 | ~1 min |

As taxas do ERC-20 são altas, então o mínimo é $5; as do Bitcoin também não são baixas, mínimo $5; todo o resto é $1. Os clientes precisam enviar pela rede exibida na página de pagamento — dinheiro enviado por outra rede não é creditado automaticamente. BTC / LTC / DOGE / BCH aparecem como “detectado” assim que entram na mempool e só contam depois de confirmações suficientes; transações substituídas (RBF) ou descartadas não contam. As moedas nativas (TRX, BNB, ETH, POL, AVAX, OKB, SOL, TON) são cotadas a uma cotação travada e creditadas em dólares americanos como BTC / LTC / DOGE / BCH; informe a rede e a moeda: cobranças `network: "bsc", to_currency: "BNB"`, carteiras estáticas `network: "bsc", currency: "BNB"`. Uma rede sozinha equivale, por padrão, a USDT nessa rede (USDC na Base). Transferências feitas por contratos (multisig, pagamentos em lote) também são recebidas; em algumas redes o hash da transação não está disponível e `txid` no webhook é `null`.

### Erros

```json
{ "state": 1, "message": "amount must be a number like 10.28" }
```

| HTTP | Causas comuns |
| --- | --- |
| 422 | Parâmetros ausentes ou malformados; valor abaixo do mínimo da rede; URL de callback / redirecionamento fora dos seus domínios cadastrados; moeda / rede não suportada em `/v1/payment` |
| 401 | Merchant errado, `sign` errado (`Invalid Sign.`) ou API key trocada |
| 404 | A cobrança não existe ou não é sua (`Payment not found`); em `/v1/wallet`, combinação de moeda / rede não suportada (`The service was not found`) |
| 503 | A rede está temporariamente indisponível — escolha outra ou não pré-selecione nenhuma |

Quando a assinatura está errada (`Invalid Sign.`), a resposta traz um objeto `debug`: `body_base64` é o base64 do corpo da requisição que recebemos (o seu próprio conteúdo, nunca a API key) e `body_bytes` o seu tamanho. Compare com o base64 que você assinou: se forem diferentes, o corpo que você enviou não é a string que você assinou (o seu framework serializou de novo, um proxy mudou a codificação, uma quebra de linha no final); se forem iguais, a API key está errada. Cole no [verificador de assinatura](https://blockwallets.io/docs/sign?lang=pt) para ver a primeira diferença.

```json
{
  "state": 1,
  "message": "Invalid Sign.",
  "debug": {
    "body_base64": "eyJhbW91bnQiOiI0Mi4wMCIsImN1cnJlbmN5IjoiVVNEIiwi…",
    "body_bytes": 158,
    "sign_formula": "md5(body_base64 + API key)"
  }
}
```

### Perguntas frequentes

#### Os clientes recarregam o valor que quiserem — qual modo?

Cobranças. Deixe o cliente digitar um valor na sua página de recarga, crie uma cobrança para ele e credite `payment_amount_usd` quando chegar. Use carteiras estáticas só se os clientes precisarem salvar um endereço e enviar para ele repetidamente.

#### E se um cliente pagar a menos?

Antes de expirar, o cliente pode enviar a diferença pela página de pagamento (ela mostra quanto ainda falta; status `wrong_amount_waiting`, e se restarem menos de 30 minutos no primeiro pagamento a menos, o prazo é movido para 30 minutos depois). Se ainda faltar na expiração, a cobrança vira `wrong_amount` e `payment_amount_usd` no webhook é o valor recebido; negócios de recarga podem simplesmente creditar esse valor.

#### E se um cliente pagar com atraso, ou duas vezes?

O dinheiro que chega depois da expiração ainda é creditado e notificado; o dinheiro que chega depois de a cobrança já estar totalmente paga também é registrado e fica visível no painel.

#### E se um cliente enviar pela rede errada?

Por exemplo, a cobrança é em TRON e ele envia pela BNB Chain: não é creditado automaticamente — entre em contato e resolvemos manualmente.

#### Quanto custa?

1% de cada pagamento recebido, reduzido automaticamente pelo volume do mês anterior (0.9% a partir de $50,000, 0.8% a partir de $100,000, 0.7% a partir de $250,000, 0.6% a partir de $500,000 e 0.5% a partir de $1,000,000), sem mensalidade nem taxa de adesão. O cliente paga a taxa de rede ao enviar; para repassar essa taxa ao cliente, defina `subtract` ao criar uma cobrança ou como padrão no painel. Os saques não têm taxa extra. Veja os [preços](https://blockwallets.io/pricing?lang=pt).

#### Quando o dinheiro chega até mim?

É creditado no seu saldo assim que o pagamento confirma. Solicite um saque para a sua própria carteira em “Fundos › Saldo e saques”; depois que aprovamos, fazemos o pagamento e a transação na blockchain aparece no seu histórico de saques.

Você também pode ativar o saque automático: quando o seu saldo disponível atingir um valor que você definir, ou uma vez por dia às 00:00 UTC, todo o saldo disponível é sacado. Os saques automáticos são revisados do mesmo jeito, e toda alteração de configuração envia um aviso para o seu e-mail.
