Documentación de la API
Integra Numbay por API REST: consulta tu saldo, renta números, lee mensajes, inicia recargas y recibe eventos en tiempo real con webhooks firmados.
Las llaves de API y los webhooks se gestionan en Ajustes.
API pública
Base: https://numbay.io/api/v1 · Autenticación: Authorization: Bearer nb_live_... (o header x-api-key). Las llaves se crean en Settings → API con scope de solo lectura (read) o lectura y escritura (read+write).
Dinero siempre en centavos enteros (amountCents). Errores en JSON: { "error": "CODE", "message"? }. Rate limit por llave: 120/min lectura, 20/min escritura → 429 con header Retry-After.
GET /wallet (read)
Saldo y últimos movimientos. Query: ledger_limit (1–100, default 20).
{ "data": { "balanceCents": 5000, "currency": "USD", "ledger": [ { "id": "...", "amountCents": 1000, "type": "TOPUP", "refId": "...", "note": "...", "balanceAfter": 5000, "createdAt": "..." } ] } }GET /numbers (read)
Números del usuario. Query: status (ACTIVE|SUSPENDED|RELEASED).
GET /numbers/available (read)
Inventario rentable. Query: country (ej. US), limit (1–20, default 10).
POST /numbers (write)
Renta un número. Compra inventario real: usa Idempotency-Key en los reintentos.
POST /api/v1/numbers
Idempotency-Key: <uuid-propio>
{ "country": "US", "e164": "+14155551008" }201 { "data": { "id", "e164" } } · Errores: 400 INVALID_INPUT, 402 INSUFFICIENT_BALANCE, 403 KYC_REQUIRED, 409 NO_INVENTORY.
GET /messages (read)
Mensajes, más recientes primero. Query: numberId, direction (INBOUND|OUTBOUND), since (ISO 8601), limit (1–100), cursor (id devuelto en nextCursor).
{ "data": [ { "id": "...", "numberId": "...", "conversationId": "...", "direction": "INBOUND", "from": "+1...", "to": "+1...", "body": "...", "segments": 1, "status": "RECEIVED", "costCents": 0, "createdAt": "..." } ], "nextCursor": "..." }POST /topups (write)
Inicia una recarga. Acepta Idempotency-Key.
{ "gateway": "QVAPAY" | "TRONDEALER", "amountCents": 100..100000 }201 { "data": { "id", "gateway", "url"?, "address"?, "amountCents" } } — QvaPay devuelve url de pago; TronDealer devuelve address (USDT/USDC en BSC). La acreditación llega por webhook interno/reconciliación: consulta el estado o suscríbete al evento payment.completed.
GET /topups/{id} (read)
{ "data": { "id", "status": "PENDING|PAID|EXPIRED|FAILED", "gateway", "amountCents", "asset", "url"?, "address"?, "createdAt", "paidAt" } }
Webhooks salientes
Configura endpoints en Settings → Webhooks (URL https pública). Eventos:
message.received— SMS entrante en uno de tus números.data= mismo formato que GET /messages.payment.completed— recarga acreditada.data={ id, gateway, amountCents, asset, paidAt }.
Cuerpo de cada entrega:
{ "id": "<deliveryId>", "event": "message.received", "createdAt": "...", "data": { } }Firma
Headers: x-numbay-event, x-numbay-timestamp (epoch segundos), x-numbay-signature. La firma es HMAC-SHA256 en hex de ${timestamp}.${rawBody} con el secreto del endpoint. Verificación (Node):
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(req, rawBody, secret) {
const ts = req.headers["x-numbay-timestamp"];
const expected = createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
const got = req.headers["x-numbay-signature"] ?? "";
return got.length === expected.length &&
timingSafeEqual(Buffer.from(got), Buffer.from(expected)) &&
Math.abs(Date.now() / 1000 - Number(ts)) < 300; // tolerancia 5 min
}Entrega y reintentos
Responde 2xx en menos de 5 s (procesa async si necesitas más). Semántica at-least-once: deduplica por id. Reintentos con backoff: 1m, 5m, 15m, 1h, 4h, 12h, 24h (8 intentos en total) y luego FAILED definitivo. Desde el panel puedes ver las últimas entregas, reenviarlas manualmente y rotar el secreto.
¿Integras con un agente de IA? Toda esta referencia está disponible en texto plano en /llms-full.txt