Documentación de la API

La API de integración es la que consume tu sistema para vender con nosotros: consultar tu catálogo y tus precios, comprar recargas, seguir cada pedido, revisar tu saldo y tus movimientos, y recibir avisos. Las rutas marcadas «En desarrollo» tienen el contrato definitivo y se activan por fases; puedes integrar contra él desde ya.

URL base

Todas las rutas cuelgan del mismo dominio que este sitio, bajo /v1. Solo se atiende HTTPS. El contrato completo está en /openapi.json (OpenAPI 3.1) por si quieres generar un cliente.

https://b2b.recargadoble.com/v1

Autenticación

Toda ruta exige Authorization: Bearer <token>. El token sale de las credenciales de integración de tu cuenta (un identificador de cliente y un secreto), que se emiten para tu cuenta junto con las instrucciones para obtenerlo. Es de corta duración: renuévalo cuando una ruta responda UNAUTHORIZED.

Las credenciales son de tu servidor: nunca las pongas en una app ni en una página web. Si sospechas que se filtraron, pide que se revoquen y se emitan otras.

Formato de las respuestas

Toda respuesta es JSON con la misma envoltura. Si ok es true, el resultado está en data; si es false, en error hay un code y, a veces, details.

Ramifica por code, nunca por el texto ni por el estado HTTP: los códigos son estables y no cambian de significado.

Los importes van en la unidad mínima de su moneda, con la moneda al lado: { "amount": 1050, "currency": "USD" } son 10,50 USD. Las fechas, en ISO 8601 UTC. Las listas largas van por páginas: pide la siguiente con el nextCursor de la anterior.

{ "ok": true, "data": { ... } }
{ "ok": false, "error": { "code": "INSUFFICIENT_BALANCE", "details": { "available": 1200 } } }

Cómo se vende una recarga

1. Catálogo: GET /v1/catalog/countries lista los países habilitados para tu cuenta; .../countries/{country}/carriers, sus operadores; .../carriers/{carrier}/products, los productos con tu precio. Si solo tienes el número, POST /v1/destination/detect te dice país y operador.

2. Compra: POST /v1/orders con el sku de cada producto y el número. Manda expectedPrice con el precio que le mostraste a tu cliente: si cambió, el pedido se rechaza con PRICE_CHANGED en lugar de cobrarte otra cifra. El total se descuenta de tu saldo al crear el pedido.

3. Entrega: el pedido nace PENDING y cada recarga avanza sola. Sigue el estado con los avisos o con GET /v1/orders/{reference}. Una recarga que no se entrega (FAILED o VOIDED) devuelve su precio a tu saldo automáticamente.

Un producto se identifica por su sku, nunca por la cantidad: un operador puede vender dos productos con la misma denominación.

Reintentos sin duplicar compras

POST /v1/orders exige la cabecera Idempotency-Key, un valor único por compra (un UUID sirve). Si la conexión se corta y no sabes si el pedido se creó, repite la misma petición con la misma clave: durante 24 horas devuelve el mismo pedido sin cobrar dos veces. La misma clave con otro cuerpo responde IDEMPOTENCY_CONFLICT.

Pruebas y real

Tu cuenta funciona en dos modos, pruebas y real, con la misma URL base, las mismas rutas y las mismas respuestas. El modo lo decide solo la credencial con la que pides el token: si su identificador empieza por rdc_test_ estás en pruebas; si no, en real. No hay cabecera ni parámetro que lo cambie, así que una credencial de pruebas nunca puede crear un pedido real por error.

En pruebas todo se comporta como en real (catálogo, precios, validaciones, errores, estados y avisos), pero nada se cobra ni llega al operador: el resultado de cada recarga lo simulamos según el número. Cada pedido y cada aviso dice en qué modo está con el campo livemode.

Las credenciales de cada modo se emiten para tu cuenta; pide las de pruebas para integrar y las reales cuando vayas a vender.

Pruebas (rdc_test_…)Real
livemodefalsetrue
Se descuenta de tu saldoNo (no necesitas saldo)Sí, al crear el pedido
Llega al operadorNo: el resultado se simulaSí
Libro, facturas y límites diariosNo cuentaSí
Pedidos, avisos y ventas que vesSolo los de pruebaSolo los reales
Saldo y libro que vesLos reales, sin cambiosLos reales
Catálogo, precios y erroresLos mismosLos mismos
URL de avisos y firmaLa misma (no la cambia)La misma

Cómo probar tu integración

1. Pide el token con tu credencial de pruebas, exactamente igual que con una real.

2. Compra con POST /v1/orders usando un sku de tu catálogo y un número válido para su país. Las cuatro últimas cifras del número deciden qué pasa: 0001 falla al momento con CARRIER_REJECTED; 0002 se queda en entrega unos minutos (hasta unos 15) y después se entrega; 0003 se queda en entrega y después falla; cualquier otro se entrega al momento.

3. Sigue el pedido como lo harías en real: con GET /v1/orders/{reference} o con los avisos en tu URL. Los avisos de prueba llevan livemode: false, y una recarga fallida produce el mismo order.item.failed que en real, con el precio que se te devolvería.

4. Prueba los casos que te importan: reintentos con la misma Idempotency-Key, PRICE_CHANGED, un producto que no está en tu catálogo, la verificación de la firma de los avisos y el reenvío de uno que falló.

Con este pedido de ejemplo la recarga falla, porque el número termina en 0001:

POST https://b2b.recargadoble.com/v1/orders
Authorization: Bearer <token de rdc_test_...>
Idempotency-Key: 6f1c2a1e-9b0d-4c55-a2b7-3e8f0d1c4a90

{
  "items": [
    { "sku": "JM-DIGICEL-TOPUP-500-K7Q2M9XA", "phoneNumber": "+18765550001" }
  ]
}

Pasar a real

1. Cambia la credencial de pruebas por la real en tu servidor. Es lo único que cambia: ni la URL, ni las rutas, ni el formato de los pedidos o de los avisos.

2. Asegúrate de tener saldo (o crédito) suficiente: en real cada pedido se descuenta al crearse, y sin saldo se rechaza con INSUFFICIENT_BALANCE.

3. Deja de usar números terminados en 0001, 0002 o 0003 como prueba: en real cada número recibe la recarga de verdad.

4. Comprueba livemode en cada pedido y en cada aviso, y no mezcles en tu sistema lo que llega con false: son pedidos que no se entregaron ni se cobraron.

Puedes conservar la credencial de pruebas para seguir probando cambios: los dos modos conviven, y cada credencial solo ve lo suyo.

Avisos (webhooks)

Configura con PUT /v1/webhooks una URL HTTPS y los eventos que quieres recibir: order.item.completed, order.item.failed, order.completed, balance.low, invoice.issued, invoice.overdue, invoice.paid e invoice.voided. Cada aviso es un POST JSON con id, type, occurredAt, livemode (false en un aviso de pruebas), merchant y data.

Cada aviso va firmado en X-RD-Signature: t=<epoch>,v1=<firma>, donde la firma es HMAC-SHA256 en hexadecimal de <t>.<cuerpo> con tu secreto. Compruébala y rechaza avisos con más de 5 minutos. Responde 2xx en menos de 10 segundos; si no, se reintenta con espera creciente. El id es el mismo en cada reintento: úsalo para no procesar dos veces el mismo aviso.

Los avisos no sustituyen a la consulta: si tu sistema estuvo caído, GET /v1/orders con from recupera lo que pasó.

Identificador de petición

Toda respuesta trae la cabecera x-request-id. Guárdala junto a tus operaciones y mándanosla si algo no sale como esperabas: con ella encontramos esa petición exacta.

Límites

Cada ruta tiene un límite de peticiones por segundo; al superarlo la respuesta es 429. Espera y reintenta con un intervalo creciente; no reintentes en bucle. Tu cuenta puede tener además un límite diario de importe o de pedidos (GET /v1/merchant), que responde DAILY_LIMIT_EXCEEDED.

Códigos de error comunes

UNAUTHORIZED: falta el token o caducó. FORBIDDEN: el token es válido pero no da acceso a eso. NOT_FOUND: no existe o no es tuyo. VALIDATION_FAILED: revisa details.fields. MERCHANT_BLOCKED: tu cuenta puede consultar pero no comprar; habla con tu contacto. RATE_LIMITED: espera y reintenta. INTERNAL_ERROR: fallo nuestro; reintenta más tarde y mándanos el x-request-id.

Referencia

Cada ruta con sus parámetros, lo que recibe, lo que devuelve dentro de data y sus códigos de error propios.

GET/v1/merchantRequiere token

Los datos de tu cuenta: nombre, estado, moneda, modo de facturación (prepago o pospago) y límites diarios.

Respuesta (data)

{
  "code": "ACME",
  "tradeName": "Acme Recargas",
  "legalName": "Acme Recargas LLC",
  "countryCode": "JM",
  "currency": "USD",
  "status": "ACTIVE",
  "billingMode": "PREPAID",
  "billingEmail": "facturas@acme.example",
  "limits": {
    "dailyAmount": {
      "amount": 1050,
      "currency": "USD"
    },
    "dailyOrders": 500
  },
  "createdAt": "2026-01-01T00:00:00.000Z"
}

Códigos de error

VALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X GET "https://b2b.recargadoble.com/v1/merchant" \
  -H "authorization: Bearer $ACCESS_TOKEN"
GET/v1/merchant/balanceRequiere token

Tu saldo, el crédito concedido y available, lo máximo que admite el siguiente pedido.

Respuesta (data)

{
  "currency": "USD",
  "balance": 250000,
  "creditLimit": 0,
  "available": 250000,
  "lowBalanceThreshold": 20000,
  "updatedAt": "2026-01-01T00:00:00.000Z"
}

Códigos de error

VALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X GET "https://b2b.recargadoble.com/v1/merchant/balance" \
  -H "authorization: Bearer $ACCESS_TOKEN"
GET/v1/catalog/countriesRequiere token

Los países en los que puedes vender, con cuántos operadores y qué tipos de producto tiene cada uno.

Parámetros

localeconsulta
Idioma de nombres y descripciones; es si no se indica

Respuesta (data)

{
  "items": [
    {
      "code": "JM",
      "name": "Jamaica",
      "callingCode": "+1876",
      "carrierCount": 2,
      "productTypes": [
        "TOPUP"
      ]
    }
  ]
}

Códigos de error

VALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X GET "https://b2b.recargadoble.com/v1/catalog/countries" \
  -H "authorization: Bearer $ACCESS_TOKEN"
GET/v1/catalog/countries/{country}/carriersRequiere token

Los operadores habilitados de un país (country en ISO 3166-1, p. ej. JM).

Parámetros

countryruta · obligatorio
ISO 3166-1 alfa-2
localeconsulta
Idioma de nombres y descripciones; es si no se indica

Respuesta (data)

{
  "items": [
    {
      "name": "Digicel",
      "countryCode": "JM",
      "logoUrl": "string",
      "productTypes": [
        "TOPUP"
      ]
    }
  ]
}

Códigos de error

NOT_FOUNDVALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X GET "https://b2b.recargadoble.com/v1/catalog/countries/JM/carriers" \
  -H "authorization: Bearer $ACCESS_TOKEN"
GET/v1/catalog/carriers/{carrier}/productsRequiere token

Los productos de un operador con lo que recibe el número (delivers) y lo que te cuesta (price). Filtra con type.

Parámetros

carrierruta · obligatorio
localeconsulta
Idioma de nombres y descripciones; es si no se indica
typeconsulta
Solo productos de este tipo

Respuesta (data)

{
  "items": [
    {
      "sku": "JM-DIGICEL-TOPUP-500-K7Q2M9XA",
      "carrierId": "jm-digicel",
      "countryCode": "JM",
      "type": "TOPUP",
      "name": "Recarga 500 JMD",
      "description": "string",
      "delivers": {
        "amount": 1050,
        "currency": "USD"
      },
      "price": {
        "amount": 1050,
        "currency": "USD"
      },
      "promotion": {
        "name": "Doble saldo",
        "endsAt": "2026-01-01T00:00:00.000Z"
      }
    }
  ]
}

Códigos de error

NOT_FOUNDVALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X GET "https://b2b.recargadoble.com/v1/catalog/carriers/jm-digicel/products" \
  -H "authorization: Bearer $ACCESS_TOKEN"
GET/v1/catalog/products/{sku}Requiere token

Un producto por su sku, con tu precio de hoy. Útil para confirmar el precio justo antes de comprar.

Parámetros

skuruta · obligatorio
localeconsulta
Idioma de nombres y descripciones; es si no se indica

Respuesta (data)

{
  "sku": "JM-DIGICEL-TOPUP-500-K7Q2M9XA",
  "carrierId": "jm-digicel",
  "countryCode": "JM",
  "type": "TOPUP",
  "name": "Recarga 500 JMD",
  "description": "string",
  "delivers": {
    "amount": 1050,
    "currency": "USD"
  },
  "price": {
    "amount": 1050,
    "currency": "USD"
  },
  "promotion": {
    "name": "Doble saldo",
    "endsAt": "2026-01-01T00:00:00.000Z"
  }
}

Códigos de error

NOT_FOUNDVALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X GET "https://b2b.recargadoble.com/v1/catalog/products/JM-DIGICEL-TOPUP-500-K7Q2M9XA" \
  -H "authorization: Bearer $ACCESS_TOKEN"
POST/v1/destination/detectRequiere token

El país y el operador de un número. Con portabilidad el operador puede ser otro: confírmalo con tu cliente.

Cuerpo de la petición

{
  "phoneNumber": "+18765550123"
}

Respuesta (data)

{
  "phoneNumber": "+18765550123",
  "countryCode": "JM",
  "carrier": {
    "name": "Digicel",
    "countryCode": "JM",
    "logoUrl": "string",
    "productTypes": [
      "TOPUP"
    ]
  }
}

Códigos de error

DESTINATION_INVALIDVALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X POST "https://b2b.recargadoble.com/v1/destination/detect" \
  -H "authorization: Bearer $ACCESS_TOKEN" \
  -H "content-type: application/json" \
  -d '{"phoneNumber":"+18765550123"}'
GET/v1/ordersRequiere token

Tus pedidos, del más reciente al más antiguo. Filtra por fechas, estado, número o tu externalReference.

Parámetros

cursorconsulta
El `nextCursor` de la pagina anterior
limitconsulta
Entre 1 y 100; 50 si no se indica
fromconsulta
Desde (incluido)
toconsulta
Hasta (excluido)
statusconsulta
PARTIAL: unas recargas se entregaron y otras no; lo no entregado se devuelve al saldo
phoneNumberconsulta
Pedidos con alguna recarga a este numero
externalReferenceconsulta

Respuesta (data)

{
  "items": [
    {
      "reference": "B2B-7KQ2M9XH4P",
      "externalReference": "string",
      "livemode": true,
      "status": "PENDING",
      "total": {
        "amount": 1050,
        "currency": "USD"
      },
      "refunded": {
        "amount": 1050,
        "currency": "USD"
      },
      "createdAt": "2026-01-01T00:00:00.000Z",
      "completedAt": "2026-01-01T00:00:00.000Z",
      "itemCount": 1
    }
  ],
  "nextCursor": "string"
}

Códigos de error

VALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X GET "https://b2b.recargadoble.com/v1/orders" \
  -H "authorization: Bearer $ACCESS_TOKEN"
POST/v1/ordersRequiere token

Compra una o varias recargas (hasta 50). Exige Idempotency-Key. El total se descuenta de tu saldo al crear el pedido y lo que no se entregue se devuelve.

Parámetros

Idempotency-Keycabecera · obligatorio
Unica por compra en tu cuenta. Repetir la peticion con la misma clave devuelve el mismo pedido sin cobrar otro; con otro cuerpo, IDEMPOTENCY_CONFLICT. Una compra rechazada no consume la clave

Cuerpo de la petición

{
  "items": [
    {
      "sku": "JM-DIGICEL-TOPUP-500-K7Q2M9XA",
      "phoneNumber": "+18765550123",
      "expectedPrice": {
        "amount": 1050,
        "currency": "USD"
      }
    }
  ],
  "externalReference": "venta-000123"
}

Respuesta (data)

{
  "reference": "B2B-7KQ2M9XH4P",
  "externalReference": "string",
  "livemode": true,
  "status": "PENDING",
  "total": {
    "amount": 1050,
    "currency": "USD"
  },
  "refunded": {
    "amount": 1050,
    "currency": "USD"
  },
  "items": [
    {
      "index": 0,
      "sku": "JM-DIGICEL-TOPUP-500-K7Q2M9XA",
      "name": "Recarga 500 JMD",
      "type": "TOPUP",
      "phoneNumber": "+18765550123",
      "countryCode": "JM",
      "carrierName": "Digicel",
      "delivers": {
        "amount": 1050,
        "currency": "USD"
      },
      "price": {
        "amount": 1050,
        "currency": "USD"
      },
      "status": "PENDING",
      "failureCode": "INVALID_NUMBER",
      "carrierReference": "string",
      "completedAt": "2026-01-01T00:00:00.000Z"
    }
  ],
  "createdAt": "2026-01-01T00:00:00.000Z",
  "completedAt": "2026-01-01T00:00:00.000Z"
}

Códigos de error

MERCHANT_BLOCKEDIDEMPOTENCY_KEY_REQUIREDIDEMPOTENCY_CONFLICTPRODUCT_UNAVAILABLEPRICE_CHANGEDCURRENCY_MISMATCHDESTINATION_INVALIDINSUFFICIENT_BALANCEDAILY_LIMIT_EXCEEDEDVALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X POST "https://b2b.recargadoble.com/v1/orders" \
  -H "authorization: Bearer $ACCESS_TOKEN" \
  -H "idempotency-key: $(uuidgen)" \
  -H "content-type: application/json" \
  -d '{"items":[{"sku":"JM-DIGICEL-TOPUP-500-K7Q2M9XA","phoneNumber":"+18765550123","expectedPrice":{"amount":1050,"currency":"USD"}}],"externalReference":"venta-000123"}'
GET/v1/orders/{reference}Requiere token

Un pedido con el estado de cada recarga y, si falló, el motivo en failureCode.

Parámetros

referenceruta · obligatorio

Respuesta (data)

{
  "reference": "B2B-7KQ2M9XH4P",
  "externalReference": "string",
  "livemode": true,
  "status": "PENDING",
  "total": {
    "amount": 1050,
    "currency": "USD"
  },
  "refunded": {
    "amount": 1050,
    "currency": "USD"
  },
  "items": [
    {
      "index": 0,
      "sku": "JM-DIGICEL-TOPUP-500-K7Q2M9XA",
      "name": "Recarga 500 JMD",
      "type": "TOPUP",
      "phoneNumber": "+18765550123",
      "countryCode": "JM",
      "carrierName": "Digicel",
      "delivers": {
        "amount": 1050,
        "currency": "USD"
      },
      "price": {
        "amount": 1050,
        "currency": "USD"
      },
      "status": "PENDING",
      "failureCode": "INVALID_NUMBER",
      "carrierReference": "string",
      "completedAt": "2026-01-01T00:00:00.000Z"
    }
  ],
  "createdAt": "2026-01-01T00:00:00.000Z",
  "completedAt": "2026-01-01T00:00:00.000Z"
}

Códigos de error

NOT_FOUNDVALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X GET "https://b2b.recargadoble.com/v1/orders/B2B-7KQ2M9XH4P" \
  -H "authorization: Bearer $ACCESS_TOKEN"
GET/v1/orders/{reference}/eventsRequiere token

La historia del pedido, paso a paso: los mismos eventos que reciben los avisos.

Parámetros

referenceruta · obligatorio

Respuesta (data)

{
  "items": [
    {
      "type": "order.created",
      "itemIndex": 0,
      "status": "string",
      "at": "2026-01-01T00:00:00.000Z"
    }
  ]
}

Códigos de error

NOT_FOUNDVALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X GET "https://b2b.recargadoble.com/v1/orders/B2B-7KQ2M9XH4P/events" \
  -H "authorization: Bearer $ACCESS_TOKEN"
GET/v1/ledgerRequiere token

Los movimientos de tu saldo: depósitos, cobros de pedidos, devoluciones, pagos de facturas y ajustes, con el saldo tras cada uno.

Parámetros

cursorconsulta
El `nextCursor` de la pagina anterior
limitconsulta
Entre 1 y 100; 50 si no se indica
fromconsulta
Desde (incluido)
toconsulta
Hasta (excluido)
kindconsulta
ORDER_DEBIT: cobro de una recarga. ORDER_REVERSAL: devolucion de una que no se entrego

Respuesta (data)

{
  "items": [
    {
      "kind": "DEPOSIT",
      "amount": {
        "amount": 1050,
        "currency": "USD"
      },
      "balanceAfter": {
        "amount": 1050,
        "currency": "USD"
      },
      "orderReference": "string",
      "invoiceNumber": "string",
      "description": "string",
      "createdAt": "2026-01-01T00:00:00.000Z"
    }
  ],
  "nextCursor": "string"
}

Códigos de error

VALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X GET "https://b2b.recargadoble.com/v1/ledger" \
  -H "authorization: Bearer $ACCESS_TOKEN"
GET/v1/reports/salesRequiere token

Lo vendido en un periodo: pedidos, recargas entregadas y fallidas, importe cobrado y devuelto, por día, país u operador.

Parámetros

fromconsulta
Desde (incluido)
toconsulta
Hasta (excluido)
groupByconsulta
Como se agrupan las filas; day si no se indica

Respuesta (data)

{
  "from": "2026-01-01T00:00:00.000Z",
  "to": "2026-01-01T00:00:00.000Z",
  "groupBy": "day",
  "totals": {
    "orders": 120,
    "itemsDelivered": 118,
    "itemsFailed": 2,
    "spent": {
      "amount": 1050,
      "currency": "USD"
    },
    "refunded": {
      "amount": 1050,
      "currency": "USD"
    }
  },
  "rows": [
    {
      "orders": 120,
      "itemsDelivered": 118,
      "itemsFailed": 2,
      "spent": {
        "amount": 1050,
        "currency": "USD"
      },
      "refunded": {
        "amount": 1050,
        "currency": "USD"
      },
      "key": "2026-10-14",
      "countryCode": "JM"
    }
  ]
}

Códigos de error

VALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X GET "https://b2b.recargadoble.com/v1/reports/sales" \
  -H "authorization: Bearer $ACCESS_TOKEN"
GET/v1/webhooksRequiere token

La URL a la que se envían tus avisos, los eventos suscritos y si está activa.

Respuesta (data)

{
  "url": "https://api.acme.example/rd/webhooks",
  "events": [
    "order.item.completed"
  ],
  "isActive": true,
  "secretHint": "whsec_...9f2a",
  "disabledReason": "string"
}

Códigos de error

VALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X GET "https://b2b.recargadoble.com/v1/webhooks" \
  -H "authorization: Bearer $ACCESS_TOKEN"
PUT/v1/webhooksRequiere token

Configura la URL de avisos y los eventos. Con rotateSecret emite un secreto nuevo, que solo se muestra en esta respuesta; el anterior sigue valiendo 24 horas. La URL y el secreto son los mismos para pruebas y real, asi que una credencial de pruebas no puede cambiarlos (FORBIDDEN): hazlo con una credencial real.

Cuerpo de la petición

{
  "url": "https://api.acme.example/rd/webhooks",
  "events": [
    "order.item.completed"
  ],
  "rotateSecret": true
}

Respuesta (data)

{
  "url": "https://api.acme.example/rd/webhooks",
  "events": [
    "order.item.completed"
  ],
  "isActive": true,
  "secretHint": "whsec_...9f2a",
  "disabledReason": "string",
  "secret": "string"
}

Códigos de error

WEBHOOK_URL_INVALIDVALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X PUT "https://b2b.recargadoble.com/v1/webhooks" \
  -H "authorization: Bearer $ACCESS_TOKEN" \
  -H "content-type: application/json" \
  -d '{"url":"https://api.acme.example/rd/webhooks","events":["order.item.completed"],"rotateSecret":true}'
GET/v1/webhooks/deliveriesRequiere token

Los avisos enviados, con cuántos intentos llevan y la respuesta de tu servidor.

Parámetros

cursorconsulta
El `nextCursor` de la pagina anterior
limitconsulta
Entre 1 y 100; 50 si no se indica
fromconsulta
Desde (incluido)
toconsulta
Hasta (excluido)
statusconsulta

Respuesta (data)

{
  "items": [
    {
      "eventType": "order.item.completed",
      "eventId": "evt_01J9ZK7QXN",
      "status": "PENDING",
      "attempts": 1,
      "lastStatusCode": 200,
      "nextAttemptAt": "2026-01-01T00:00:00.000Z",
      "createdAt": "2026-01-01T00:00:00.000Z",
      "deliveredAt": "2026-01-01T00:00:00.000Z"
    }
  ],
  "nextCursor": "string"
}

Códigos de error

VALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X GET "https://b2b.recargadoble.com/v1/webhooks/deliveries" \
  -H "authorization: Bearer $ACCESS_TOKEN"
POST/v1/webhooks/deliveries/{id}/resendRequiere token

Reenvía un aviso, con el mismo id de evento.

Respuesta (data)

{
  "eventType": "order.item.completed",
  "eventId": "evt_01J9ZK7QXN",
  "status": "PENDING",
  "attempts": 1,
  "lastStatusCode": 200,
  "nextAttemptAt": "2026-01-01T00:00:00.000Z",
  "createdAt": "2026-01-01T00:00:00.000Z",
  "deliveredAt": "2026-01-01T00:00:00.000Z"
}

Códigos de error

NOT_FOUNDVALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X POST "https://b2b.recargadoble.com/v1/webhooks/deliveries/{id}/resend" \
  -H "authorization: Bearer $ACCESS_TOKEN"
GET/v1/invoicesRequiere token

Tus facturas (pospago) o extractos (prepago), con su estado.

Parámetros

cursorconsulta
El `nextCursor` de la pagina anterior
limitconsulta
Entre 1 y 100; 50 si no se indica
statusconsulta
ISSUED: emitida y pendiente. OVERDUE: vencida sin pagar. PAID: pagada. VOID: anulada

Respuesta (data)

{
  "items": [
    {
      "number": "INV-ACME-12",
      "kind": "INVOICE",
      "status": "ISSUED",
      "periodStart": "2026-01-01T00:00:00.000Z",
      "periodEnd": "2026-01-01T00:00:00.000Z",
      "issuedAt": "2026-01-01T00:00:00.000Z",
      "dueAt": "2026-01-01T00:00:00.000Z",
      "total": {
        "amount": 1050,
        "currency": "USD"
      },
      "paidAt": "2026-01-01T00:00:00.000Z"
    }
  ],
  "nextCursor": "string"
}

Códigos de error

VALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X GET "https://b2b.recargadoble.com/v1/invoices" \
  -H "authorization: Bearer $ACCESS_TOKEN"
GET/v1/invoices/{number}Requiere token

Una factura con sus líneas y el resumen del periodo: saldo inicial, abonos y saldo final.

Parámetros

numberruta · obligatorio

Respuesta (data)

{
  "number": "INV-ACME-12",
  "kind": "INVOICE",
  "status": "ISSUED",
  "periodStart": "2026-01-01T00:00:00.000Z",
  "periodEnd": "2026-01-01T00:00:00.000Z",
  "issuedAt": "2026-01-01T00:00:00.000Z",
  "dueAt": "2026-01-01T00:00:00.000Z",
  "total": {
    "amount": 1050,
    "currency": "USD"
  },
  "paidAt": "2026-01-01T00:00:00.000Z",
  "lines": [
    {
      "type": "RECHARGES",
      "description": "Recargas: Digicel (JM)",
      "countryCode": "JM",
      "carrierName": "Digicel",
      "quantity": 118,
      "amount": {
        "amount": 1050,
        "currency": "USD"
      }
    }
  ],
  "summary": {
    "openingBalance": {
      "amount": 1050,
      "currency": "USD"
    },
    "credits": {
      "amount": 1050,
      "currency": "USD"
    },
    "closingBalance": {
      "amount": 1050,
      "currency": "USD"
    }
  }
}

Códigos de error

NOT_FOUNDVALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X GET "https://b2b.recargadoble.com/v1/invoices/INV-ACME-12" \
  -H "authorization: Bearer $ACCESS_TOKEN"
GET/v1/invoices/{number}/pdfRequiere token

El PDF de la factura, en base64. Se genera desde el documento emitido, así que siempre dice lo mismo.

Parámetros

numberruta · obligatorio

Respuesta (data)

{
  "filename": "INV-ACME-12.pdf",
  "contentType": "application/pdf",
  "contentBase64": "string"
}

Códigos de error

NOT_FOUNDVALIDATION_FAILEDRATE_LIMITEDUNAUTHORIZEDFORBIDDENINTERNAL_ERROR

Ejemplo

curl -X GET "https://b2b.recargadoble.com/v1/invoices/INV-ACME-12/pdf" \
  -H "authorization: Bearer $ACCESS_TOKEN"