API REST nativa

Abrir en ChatGPTAbrir en Claude

La API nativa es la interfaz REST propia de blockwallets: facturas con precio en centavos de dólar, un ref idempotente por pedido, cuentas de depósito estáticas que cubren todas las redes y webhooks firmados con HMAC-SHA256. Crea las mismas facturas en la misma página de pago alojada que la API compatible con Cryptomus, con las mismas comisiones y el mismo saldo.

Genera tus claves tú mismo en el panel, en “Desarrolladores › Integración y claves”: una clave Live y una Test con sus claves de firma de webhooks. Cada una se muestra una sola vez; la lista solo muestra su prefijo. Si tu cuenta tiene la verificación en dos pasos activada, generar o rotar una clave Live pide un código. ¿Aún no tienes cuenta de comercio? Solicita acceso. ¿Ya usas Cryptomus? Consulta la API compatible con Cryptomus (cómo elegir).

Claves y peticiones

URL base https://blockwallets.io. Las peticiones y respuestas son JSON. Cada petición lleva:

Los errores devuelven un estado HTTP y {"error": {"code": "…", "message": "…"}}: 400 invalid_request (un campo ausente o mal formado), 401 unauthorized (clave ausente, desconocida o desactivada), 404 not_found, 409 conflict (la petición choca con el estado actual de la factura), 422 currency_unsupported.

Endpoints

EndpointQué hace
GET /v1/networksRedes que puedes aceptar ahora mismo en el modo de esta clave: mínimo, confirmaciones, tiempo de llegada habitual y comisión estimada; las monedas con precio incluyen la tasa actual
POST /v1/invoicesCrea una factura (201), o devuelve la existente para el mismo ref (200)
GET /v1/invoices?ref=…Consulta una factura por tu ref
GET /v1/invoices/:idConsulta una factura por id
POST /v1/invoices/:id/networkElige tú mismo la red de una factura (página de pago de marca blanca): devuelve la address y el pay_amount que debes mostrar
POST /v1/invoices/:id/closeCierra una factura pendiente que no ha recibido ninguna transferencia
POST /v1/deposit-accountsAbre (201) u obtiene (200) la cuenta de depósito de un cliente: una dirección permanente en cada red
GET /v1/deposit-accounts?customer_ref=…Consulta una cuenta de depósito por customer_ref
GET /v1/deposit-accounts/:idConsulta una cuenta de depósito por id
GET /v1/depositsLista los depósitos de una cuenta (account_id o customer_ref, limit 1–200, por defecto 50)
GET /v1/deposits/:idConsulta un depósito
GET /v1/eventsEnvíos de webhook de una factura o un depósito (invoice_id o deposit_id)
POST /v1/events/:id/redeliverVuelve a enviar un webhook (202)

Añade ?probe=1 a la consulta de una factura o de una cuenta de depósito para comprobar la cadena en el momento (como máximo una vez cada 10 segundos); si no, obtienes el último estado de nuestro escáner, que revisa cada minuto.

Crear una factura POST /v1/invoices

Llama a POST /v1/invoices cuando el cliente haga el pedido y redirígelo a la pay_url de la respuesta.

curl
curl -X POST https://blockwallets.io/v1/invoices \
  -H "Authorization: Bearer $BW_KEY" -H "Content-Type: application/json" \
  -d '{"ref":"order_1042","amount":4200,"title":"Order #1042",
       "return_url":"https://shop.example/cart","success_url":"https://shop.example/thanks?order=1042",
       "meta":{"user_id":42}}'
CampoObligatorioDescripción
refSíTu número de pedido: 1–64 caracteres entre letras, dígitos y _ . : -. Único por modo; si envías el mismo ref con los mismos campos se devuelve la misma factura, y con campos distintos devuelve 409
amountSíImporte en centavos de dólar como entero: 4200 = $42.00. No inferior al mínimo de la red una vez elegida
titleSíLo que ve el cliente en la página de pago, hasta 64 caracteres
return_urlSíA dónde lleva “Volver” en la página de pago; debe estar en uno de los dominios de tu sitio web
success_urlNoA dónde va el cliente después de pagar; por defecto, return_url
networkNoPreselecciona un id de red de la tabla de redes; omítelo para que el cliente elija en la página de pago
customer_refNoEl id de tu cliente, hasta 64 caracteres, devuelto tal cual
lifetimeNoDuración en segundos, 600 – 43200, por defecto 3600
amount_ruleNo"any" = acredita lo que llegue (recargas): paid en cuanto se confirma. Omítelo para usar la “Regla de importe” de “Ajustes › Reglas de cobro y tarifas” en el panel
accuracy_percentNoCuánto pago de menos se sigue considerando pagado, 0 – 5 (por ciento), por defecto 0
subtract_percentNoParte de la comisión de la plataforma que paga el cliente, 0 – 100 (por ciento), añadida al pay_amount; omítelo para usar el valor por defecto del panel
payment_multipleNoSi un pago insuficiente se puede completar en la misma dirección; por defecto, el valor del panel (activado salvo que lo cambies); false: la primera transferencia insuficiente termina como wrong_amount
metaNoCualquier objeto JSON de hasta 2 KB, devuelto tal cual en las consultas y los webhooks
currencyNoSolo USD (el valor por defecto); cualquier otro devuelve 422

Cada URL debe estar en uno de los dominios de tu sitio web (panel → “Desarrolladores › Integración y claves”). La respuesta es el objeto factura de abajo; network, address y pay_amount se rellenan cuando se elige una red.

El objeto factura

Los ids empiezan por inv_. amount está en centavos de dólar; pay_amount y paid_amount son importes de la moneda, como cadenas decimales, en la red elegida.

json
{
  "id": "inv_01J8…",
  "ref": "order_1042",
  "mode": "live",
  "status": "pending",
  "amount": 4200,
  "currency": "USD",
  "title": "Order #1042",
  "meta": { "user_id": 42 },
  "network": null,
  "address": null,
  "pay_amount": null,
  "paid_amount": null,
  "payments": [],
  "pay_url": "https://blockwallets.io/pay/inv_01J8…",
  "return_url": "https://shop.example/cart",
  "success_url": "https://shop.example/thanks?order=1042",
  "created_at": "2026-11-03T08:00:00.000Z",
  "expires_at": "2026-11-03T09:00:00.000Z",
  "paid_at": null,
  "closed_at": null
}
statusSignificadoQué haces tú
pendingPendiente de pago—
confirmingSe detectó una transferencia y se está confirmando, o llegó incompleta y aún se puede completar—
paidPagadaEnvía / acredita el pedido
paid_overPagada, con pago de másIgual; el extra está en tu saldo
wrong_amountTerminó con menos del importe total (al caducar, o en la primera transferencia insuficiente cuando payment_multiple es false)Los negocios de recargas pueden acreditar lo que llegó (paid_amount; las monedas con tasa también traen paid_cents); las tiendas piden al cliente que pague el resto
closedCaducó sin recibir nada, o la cerraste tú— (el dinero que llegue más tarde se acredita y se notifica igualmente)

Otros campos: pay_url (la página de pago alojada), payments (cada transferencia con txid, amount, confirmations y confirmed), expires_at, paid_at, closed_at; BTC, LTC, DOGE, BCH y las monedas nativas también incluyen rate (dólares por moneda, bloqueada durante 30 minutos), rate_locked_until y paid_cents (lo recibido hasta ahora, en centavos de dólar).

Redes

Pasa el id como network. GET /v1/networks devuelve las abiertas ahora mismo en tu modo; una red puede estar en pausa, así que es mejor consultarla que fijarla en el código.

networkMonedaCadenaMínimo
USDT_TRC20USDTTRON$1
USDT_BEP20USDTBNB Chain$1
USDC_BEP20USDCBNB Chain$1
USDT_ERC20USDTEthereum$5
USDC_ERC20USDCEthereum$5
USDC_BASEUSDCBase$1
USDT_POLYGONUSDTPolygon$1
USDC_POLYGONUSDCPolygon$1
USDT_ARBITRUMUSDTArbitrum$1
USDC_ARBITRUMUSDCArbitrum$1
USDT_OPTIMISMUSDTOptimism$1
USDC_OPTIMISMUSDCOptimism$1
USDT_AVALANCHEUSDTAvalanche$1
USDC_AVALANCHEUSDCAvalanche$1
USDT_XLAYERUSDTX Layer$1
USDC_XLAYERUSDCX Layer$1
USD1_BEP20USD1BNB Chain$1
FDUSD_BEP20FDUSDBNB Chain$1
DAI_ERC20DAIEthereum$5
DAI_ARBITRUMDAIArbitrum$1
DAI_BASEDAIBase$1
BTCBTCBitcoin$5
LTCLTCLitecoin$1
DOGEDOGEDogecoin$1
BCHBCHBitcoin Cash$1
TRXTRXTRON$1
BNBBNBBNB Chain$1
ETHETHEthereum$5
ETH_BASEETHBase$1
ETH_ARBITRUMETHArbitrum$1
ETH_OPTIMISMETHOptimism$1
POLPOLPolygon$1
AVAXAVAXAvalanche$1
OKBOKBX Layer$1
USDT_SOLUSDTSolana$1
USDC_SOLUSDCSolana$1
SOLSOLSolana$1
USDT_TONUSDTTON$1
TONTONTON$1

Cuentas de depósito (direcciones estáticas) POST /v1/deposit-accounts

POST /v1/deposit-accounts con {"customer_ref": "user_42"} da a ese cliente una dirección permanente en cada red (todas las cadenas EVM comparten una dirección). Todo lo que envíe se acredita en dólares estadounidenses, con un webhook deposit.credited por transferencia.

curl
curl -X POST https://blockwallets.io/v1/deposit-accounts \
  -H "Authorization: Bearer $BW_KEY" -H "Content-Type: application/json" \
  -d '{"customer_ref":"user_42"}'
json
{
  "id": "dac_01J8…",
  "mode": "live",
  "customer_ref": "user_42",
  "deposit_url": "https://blockwallets.io/deposit/dac_01J8…",
  "min_amount": 100,
  "currency": "USD",
  "networks": [
    { "id": "USDT_TRC20", "chain": "tron", "token": "USDT", "address": "TXy4…8kQ2", "min_amount": 100, "confirmations": 1, … },
    { "id": "USDC_BASE", "chain": "base", "token": "USDC", "address": "0x5aE1…", "min_amount": 100, "confirmations": 20, … }
  ]
}

Las transferencias por debajo del mínimo (normalmente $1, BTC $5) se registran como below_min y no se acreditan automáticamente; contáctanos para que las acreditemos.

Webhooks

Enviamos un POST con JSON a la URL de webhook del panel (“Desarrolladores › Integración y claves”; Live y Test tienen cada uno su propia URL y su propio secret). El cuerpo es el evento:

http
POST /your/webhook
X-BW-Event: ev_01J8…
X-BW-Delivery: 1
X-BW-Signature: t=1793693052,v1=5f0c9b…

{"id":"ev_01J8…","type":"invoice.paid","created_at":"2026-11-03T08:04:12.000Z","invoice":{"id":"inv_01J8…","ref":"order_1042","status":"paid","amount":4200,…}}
EventoCuándo
invoice.paidLa factura pasó a paid o paid_over (incluido el dinero que llegó tras caducar)
invoice.wrong_amountLa factura terminó como wrong_amount
invoice.closedLa factura caducó sin recibir nada, o la cerraste tú
deposit.creditedSe acreditó una transferencia a una cuenta de depósito

Verifica contra el cuerpo sin procesar antes de analizarlo, rechaza una t que difiera más de 300 segundos de tu reloj y compara en tiempo constante. invoice / deposit en el cuerpo es el mismo objeto que devuelve una consulta.

Node.js
import crypto from "node:crypto";

// rawBody: the request body exactly as received (a string), header: X-BW-Signature
function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.trim().split("=")));
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return typeof parts.v1 === "string" && parts.v1.length === expected.length
    && crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
}

Una respuesta 2xx cuenta como entregada; si no, reintentamos tras 1 minuto, 5 minutos, 30 minutos, 2 horas, 12 horas, 24 horas y 24 horas (8 intentos en total).

Eventos y reenvío

GET /v1/events?invoice_id=inv_… (o deposit_id=dep_…) lista los webhooks de una factura o un depósito con su state, attempts, last_status y last_error. POST /v1/events/ev_…/redeliver lo pone de nuevo en cola al instante, por ejemplo después de corregir tu endpoint. La página “Desarrolladores › Registro de webhooks” del panel muestra cada intento con su petición y su respuesta.

Modo de prueba

Las facturas creadas con una clave bw_test_ funcionan en testnets y nunca tocan dinero real. La página de pago alojada muestra un botón “Simular pago” (completo / mitad / de más), así que puedes ver los estados y los webhooks sin monedas de testnet.