API para desarrolladores
Integra tu CRM, tu bot o tu sistema con WIFICOR ISP: clientes, deuda, servicio y tickets, con llaves, permisos y registro de actividad.
Primeros pasos
API para integrar tu sistema, CRM o bot con WIFICOR ISP: consulta clientes, deuda y servicio, y ejecuta acciones autorizadas.
- El dueño del ISP crea una llave en Ajustes generales > API e integraciones y marca los permisos que le da.
- Te entrega la llave (se muestra una sola vez) y el dominio de su sistema.
- Prueba la conexión: esta llamada te dice qué puede hacer tu llave.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/ping"Después elige un módulo en el menú: cada uno trae sus endpoints con parámetros, respuestas y ejemplos.
Autenticación y permisos
Autenticación
Cada ISP crea sus llaves en *Ajustes generales > API e integraciones* y se las entrega a cada integración. Envíala en cada petición:
Authorization: Bearer <llave>
La llave se muestra una sola vez. Puede rotarse (la anterior sigue válida unas horas) y revocarse en cualquier momento. Esta API se usa por ISP: la dirección base es el dominio de cada ISP.
Permisos (scopes)
Cada llave lleva scopes. Lo que puede hacer es la intersección entre sus scopes y los permisos del perfil del usuario a cuyo nombre actúa.
| Scope | Permite | Estado |
|---|---|---|
customers:read | Clientes: consultar | Disponible |
billing:read | Facturas y deuda | Disponible |
payments:read | Medios de pago | Disponible |
payments:write | Pagos: promesas y comprobantes | Disponible |
service:read | Estado del servicio | Disponible |
service:activate | Reactivar servicio | Disponible |
service:suspend | Cortar servicio | Disponible |
tickets:read | Tickets: consultar | Disponible |
tickets:write | Tickets: crear | Disponible |
tickets:close | Tickets: cerrar | Disponible |
network:read | Consumo de red | Disponible |
onu:read | ONU y OLT: consultar | Disponible |
onu:write | ONU: reiniciar | Disponible |
Límites y errores
Límites
Por defecto 120 peticiones por minuto por llave (el ISP puede fijar otro). Al pasarlo: 429 con Retry-After.
Idempotencia
Las escrituras (crear y cerrar ticket, promesa de pago, cortar y reactivar servicio, reiniciar ONU) aceptan Idempotency-Key: repetir la misma llave devuelve la respuesta original sin volver a ejecutar.
Errores
Siempre { "error": "CODIGO", "message": "..." }. Programa contra error, no contra message.
| Código | HTTP | Cuándo |
|---|---|---|
UNAUTHORIZED | 401 | Falta la llave, no es válida, fue revocada o ya venció. |
FORBIDDEN | 403 | El perfil del usuario de la llave no permite la operación, o el servicio está suspendido por licencia. |
INSUFFICIENT_SCOPE | 403 | La llave no tiene el scope que exige este endpoint. |
NOT_FOUND | 404 | El recurso no existe (o la ruta no existe). |
INVALID_REQUEST | 400 | Faltan datos o tienen un formato inválido. |
CONFLICT | 409 | La operación no se puede hacer en el estado actual. |
RATE_LIMITED | 429 | Pasaste el límite de uso de la llave. Espera lo que indica Retry-After (segundos). |
UNAVAILABLE | 500 | No se pudo completar. 503 si el conector no está disponible en este sistema. Se puede reintentar más tarde. |
Convenciones
Multi-país
La moneda, la zona horaria y el país los fija cada empresa; GET /ping los devuelve. Los importes llevan su moneda (ISO 4217).
Compatibilidad
/api/v1 y /connector/v1 son la misma API. Los cambios dentro de v1 solo agregan campos y funciones; nada se quita ni cambia de significado sin una nueva versión.
Sistema
Estado de la API y de la llave que consulta.
La especificación de ESTE sistema, generada en el momento, con su dirección ya puesta. No necesita llave.
curl \
"https://TU-DOMINIO/api/v1/openapi"Comprueba la conexión y devuelve la región de la empresa (país, moneda, zona horaria) y solo las funciones que esta llave puede usar. Úsalo para probar la llave.
| Campo | Tipo | Descripción |
|---|---|---|
ok | boolean | |
system | object | |
system.name | string | |
system.version | string | Versión del sistema. |
apiVersion | string | |
country | string · puede ser null | País de la empresa (ISO 3166-1 alfa-2). |
currency | string | Moneda de la empresa (ISO 4217). |
timezone | string | Zona horaria de la empresa. |
language | string | |
capabilities | lista de string | Funciones que ESTA llave puede usar (según sus scopes y el perfil del usuario). |
scopes | lista de string | Scopes de la llave. |
{
"ok": true,
"system": {
"name": "Wificor ISP",
"version": "8.0.1"
},
"apiVersion": "v1",
"country": "PE",
"currency": "PEN",
"timezone": "America/Lima",
"language": "es",
"capabilities": [
"customer.lookup",
"customer.detail",
"invoices"
],
"scopes": [
"customers:read",
"billing:read"
]
}- 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/ping"Clientes
Buscar al cliente por su celular y ver su ficha.
Devuelve los clientes que tienen ese celular. Con más de uno el número es ambiguo: no adivines. numberBlocked indica si el número está en la lista de números a los que este sistema no atiende.
Permiso (scope) requerido: customers:read.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
phone | query | string | Sí | Celular con código de país, sin +, de 7 a 15 dígitos. |
| Campo | Tipo | Descripción |
|---|---|---|
matches | lista de object | Clientes con ese celular. Si hay más de uno, el número es ambiguo: no adivines. |
matches[].id | string | Id del cliente (numérico, como texto). |
matches[].name | string | |
matches[].phones | lista de string | Celulares, solo dígitos y con código de país. |
matches[].document | string | Documento ENMASCARADO: nunca se entrega completo. |
matches[].status | active | suspended | pending | retired | Estado del servicio: activo, cortado, en instalación o dado de baja. |
matches[].plan | string · puede ser null | Plan contratado. |
matches[].balance | object | |
matches[].balance.amount | number | Deuda pendiente total. |
matches[].balance.currency | string | Moneda (ISO 4217). |
matches[].balance.overdueInvoices | integer | Cantidad de facturas vencidas. |
matches[].nextDueDate | string · puede ser null | Próximo vencimiento pendiente (AAAA-MM-DD). |
matches[].zone | string · puede ser null | |
numberBlocked | boolean | El número está en la lista de números a los que este sistema no atiende (Cobros IA). |
{
"matches": [
{
"id": "1234",
"name": "Ana Pérez",
"phones": [
"51987654321"
],
"document": "4****678",
"status": "active",
"plan": "Fibra 100",
"balance": {
"amount": 80,
"currency": "PEN",
"overdueInvoices": 1
},
"nextDueDate": "2026-10-15",
"zone": "Zona Norte"
}
],
"numberBlocked": false
}- 400 INVALID_REQUEST:
phoneno tiene entre 7 y 15 dígitos. - 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/customers/lookup?phone=51987654321"El resumen del cliente más sus servicios, ONU, último pago y tickets abiertos. El documento siempre va enmascarado.
Permiso (scope) requerido: customers:read.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
| Campo | Tipo | Descripción |
|---|---|---|
id | string | Id del cliente (numérico, como texto). |
name | string | |
phones | lista de string | Celulares, solo dígitos y con código de país. |
document | string | Documento ENMASCARADO: nunca se entrega completo. |
status | active | suspended | pending | retired | Estado del servicio: activo, cortado, en instalación o dado de baja. |
plan | string · puede ser null | Plan contratado. |
balance | object | |
balance.amount | number | Deuda pendiente total. |
balance.currency | string | Moneda (ISO 4217). |
balance.overdueInvoices | integer | Cantidad de facturas vencidas. |
nextDueDate | string · puede ser null | Próximo vencimiento pendiente (AAAA-MM-DD). |
zone | string · puede ser null | |
address | string · puede ser null | |
services | lista de object | |
services[].plan | string | |
services[].speed | cualquiera | Velocidad contratada (número). |
services[].speedUnit | string · puede ser null | |
services[].monthlyPrice | number | |
services[].technology | string · puede ser null | |
services[].status | string | |
onu | object · puede ser null | Estado de la ONU o de la conexión; null si el sistema no lo conoce. |
onu.state | online | offline | unknown | |
onu.lastSeen | string · puede ser null | Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
lastPayment | object · puede ser null | |
lastPayment.date | string | |
lastPayment.amount | number | |
openTickets | integer | Tickets abiertos. |
acquiredAt | string · puede ser null | Fecha del primer contrato (AAAA-MM-DD). |
{
"id": "1234",
"name": "Ana Pérez",
"phones": [
"51987654321"
],
"document": "4****678",
"status": "active",
"plan": "Fibra 100",
"balance": {
"amount": 80,
"currency": "PEN",
"overdueInvoices": 1
},
"nextDueDate": "2026-10-15",
"zone": "Zona Norte",
"address": "Av. Principal 123",
"services": [
{
"plan": "Fibra 100",
"speed": 100,
"speedUnit": "Mbps",
"monthlyPrice": 30,
"technology": "Fibra",
"status": "active"
}
],
"onu": {
"state": "online",
"lastSeen": "2026-10-06 10:40:00"
},
"lastPayment": {
"date": "2026-09-15",
"amount": 30
},
"openTickets": 0,
"acquiredAt": "2024-03-02"
}- 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente no existe.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/customers/1234"Los clientes de la empresa, de a pocos y por orden de id, cada uno con el mismo resumen de la búsqueda por celular. Pagina con nextCursor → after. Con q busca por nombre, documento, correo o celular (con o sin código de país).
Permiso (scope) requerido: customers:read.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
q | query | string | No | Texto a buscar: nombre, documento, correo o celular. |
status | query | active | suspended | pending | retired | No | Solo clientes en ese estado del servicio. |
limit | query | integer · por defecto 25 | No | Cuántos devolver (1 a 100). |
after | query | string | No | El nextCursor de la página anterior. |
| Campo | Tipo | Descripción |
|---|---|---|
customers | lista de object | |
customers[].id | string | Id del cliente (numérico, como texto). |
customers[].name | string | |
customers[].phones | lista de string | Celulares, solo dígitos y con código de país. |
customers[].document | string | Documento ENMASCARADO: nunca se entrega completo. |
customers[].status | active | suspended | pending | retired | Estado del servicio: activo, cortado, en instalación o dado de baja. |
customers[].plan | string · puede ser null | Plan contratado. |
customers[].balance | object | |
customers[].balance.amount | number | Deuda pendiente total. |
customers[].balance.currency | string | Moneda (ISO 4217). |
customers[].balance.overdueInvoices | integer | Cantidad de facturas vencidas. |
customers[].nextDueDate | string · puede ser null | Próximo vencimiento pendiente (AAAA-MM-DD). |
customers[].zone | string · puede ser null | |
nextCursor | string · puede ser null | Pásalo como after para pedir la página siguiente. null = no hay más. |
{
"customers": [
{
"id": "1234",
"name": "Ana Pérez",
"phones": [
"51987654321"
],
"document": "4****678",
"status": "active",
"plan": "Fibra 100",
"balance": {
"amount": 80,
"currency": "PEN",
"overdueInvoices": 1
},
"nextDueDate": "2026-10-15",
"zone": "Zona Norte"
}
],
"nextCursor": "1234"
}- 400 INVALID_REQUEST:
statusoafterno son válidos. - 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/customers"Facturación
Deuda y facturas del cliente.
Facturas del cliente, la de vencimiento más reciente primero.
Permiso (scope) requerido: billing:read.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
status | query | pending | paid | all · por defecto pending | No | Qué facturas devolver. |
limit | query | integer · por defecto 20 | No | Cuántas devolver (1 a 100). |
| Campo | Tipo | Descripción |
|---|---|---|
invoices | lista de object | |
invoices[].id | string | |
invoices[].number | string | Serie y correlativo. |
invoices[].issuedAt | string | |
invoices[].dueDate | string | |
invoices[].amount | number | Total. |
invoices[].paid | number | Pagado. |
invoices[].remaining | number | Pendiente. |
invoices[].currency | string | |
invoices[].status | pending | partial | paid | void | |
invoices[].description | string · puede ser null |
{
"invoices": [
{
"id": "9001",
"number": "F001-0000123",
"issuedAt": "2026-10-01",
"dueDate": "2026-10-15",
"amount": 80,
"paid": 0,
"remaining": 80,
"currency": "PEN",
"status": "pending",
"description": "Mensualidad octubre"
}
]
}- 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente no existe.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/customers/1234/invoices"La factura completa de un cliente: totales, impuesto, periodo que cubre, líneas y los pagos aplicados. La factura debe ser de ese cliente.
Permiso (scope) requerido: billing:read.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
invoiceId | path | string | Sí | Id de la factura (el que devuelve la lista de facturas). |
| Campo | Tipo | Descripción |
|---|---|---|
id | string | |
number | string | Serie y correlativo. |
issuedAt | string | |
dueDate | string | |
amount | number | Total. |
paid | number | Pagado. |
remaining | number | Pendiente. |
currency | string | |
status | pending | partial | paid | void | |
description | string · puede ser null | |
period | object · puede ser null | Periodo que cubre (facturas de servicio). |
period.from | string | |
period.to | string | |
subtotal | number | |
discount | number | |
tax | object | |
tax.amount | number | |
tax.percent | number | |
tax.included | boolean | El precio ya incluye el impuesto. |
installments | object · puede ser null | Solo si la factura se financió en cuotas. |
installments.total | integer | |
installments.interestPercent | number · puede ser null | |
installments.interestAmount | number · puede ser null | |
lines | lista de object | |
lines[].type | service | product | free | Servicio, producto o línea libre. |
lines[].description | string | |
lines[].quantity | integer | |
lines[].price | number | |
lines[].taxPercent | number | |
lines[].total | number | |
payments | lista de object | Pagos aplicados a esta factura, del más antiguo al más nuevo. |
payments[].id | string | |
payments[].invoiceId | string · puede ser null | Factura a la que se aplicó. |
payments[].invoiceNumber | string · puede ser null | |
payments[].date | string | Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
payments[].amount | number | Monto pagado. |
payments[].currency | string | |
payments[].method | string · puede ser null | Forma de pago, con el nombre que le da la empresa. |
payments[].reference | string · puede ser null | Número de operación. |
payments[].status | valid | void | void = pago anulado (no se borra). |
{
"id": "9001",
"number": "F001-0000123",
"issuedAt": "2026-10-01",
"dueDate": "2026-10-15",
"amount": 80,
"paid": 0,
"remaining": 80,
"currency": "PEN",
"status": "pending",
"description": "Mensualidad octubre",
"period": {
"from": "2026-10-01",
"to": "2026-10-31"
},
"subtotal": 80,
"discount": 0,
"tax": {
"amount": 0,
"percent": 0,
"included": false
},
"installments": null,
"lines": [
{
"type": "service",
"description": "Servicio de internet, mes de octubre",
"quantity": 1,
"price": 80,
"taxPercent": 0,
"total": 80
}
],
"payments": [
{
"id": "5501",
"invoiceId": "9001",
"invoiceNumber": "F001-0000123",
"date": "2026-10-05 14:30:00",
"amount": 30,
"currency": "PEN",
"method": "YAPE",
"reference": "00845122",
"status": "valid"
}
]
}- 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente o la factura no existen (o la factura no es de ese cliente).
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/customers/1234/invoices/{invoiceId}"Pagos
Medios de pago, promesas de pago y comprobantes.
Las cuentas de cobro activas del país de la empresa (cada banco o billetera con su nombre).
Permiso (scope) requerido: payments:read.
| Campo | Tipo | Descripción |
|---|---|---|
accounts | lista de object | Cuentas de cobro activas del país de la empresa. |
accounts[].bank | string | Banco o billetera, con el nombre que le da la empresa. |
accounts[].holder | string | Titular. |
accounts[].number | string | Número de cuenta. |
accounts[].cci | string · puede ser null | Código interbancario (CCI, CLABE, CBU... según el país). |
accounts[].phone | string · puede ser null | Celular de la billetera, si aplica. |
accounts[].currency | string | |
accounts[].note | string · puede ser null | |
instructions | string | Texto sugerido para el cliente. |
{
"accounts": [
{
"bank": "Yape",
"holder": "Mi Empresa SAC",
"number": "987654321",
"cci": null,
"phone": "51987654321",
"currency": "PEN",
"note": null
}
],
"instructions": "Cuando pagues, envíanos la captura del comprobante por este chat."
}- 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/payment-methods"Registra el compromiso con exactamente la lógica del panel: fechas, candado de penalidad, estado de compromiso y liberación del corte. Repetir la misma Idempotency-Key (máximo 100 caracteres) devuelve la respuesta original SIN volver a ejecutar la operación; se recuerda 24 horas.
Permiso (scope) requerido: payments:write.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
Idempotency-Key | header | string | No | Evita duplicar la operación si reintentas. Máximo 100 caracteres. |
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
promisedDate | string (date) | Sí | Fecha prometida (AAAA-MM-DD). Obligatoria. |
note | string | No | Nota opcional. |
invoiceId | string | No | Factura a la que se refiere (debe ser de este cliente). Opcional. |
{
"promisedDate": "2026-10-20",
"note": "Cobra el viernes"
}| Campo | Tipo | Descripción |
|---|---|---|
id | string · puede ser null | Id del compromiso vigente. |
promisedDate | string | |
serviceStatus | active | suspended | pending | retired | Estado del servicio tras registrar la promesa (puede reactivarse). |
{
"id": "55",
"promisedDate": "2026-10-20",
"serviceStatus": "active"
}- 400 INVALID_REQUEST:
promisedDateno tiene el formato AAAA-MM-DD. - 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente no existe o la factura no es de este cliente.
- 409 CONFLICT: el cliente no tiene contrato, o el sistema rechazó la promesa (el mensaje dice por qué).
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl -X POST \
-H "Authorization: Bearer TU_LLAVE" \
-H "Idempotency-Key: UN-ID-UNICO" \
-H "Content-Type: application/json" \
-d '{"promisedDate":"2026-10-20","note":"Cobra el viernes"}' \
"https://TU-DOMINIO/api/v1/customers/1234/payment-promises"Entrega la imagen o PDF a Cobros IA, que lo lee y lo concilia. Responde 202 de inmediato; el resultado (y el aviso al cliente) llegan después por los canales del sistema. Requiere que Cobros IA esté activado.
Permiso (scope) requerido: payments:write.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
fileUrl | string | Sí | Dirección https de la imagen o PDF del comprobante. Obligatoria. |
mimeType | string | No | Tipo del archivo. Por defecto image/jpeg. |
text | string | No | Texto que acompañó al comprobante. |
{
"fileUrl": "https://ejemplo.com/comprobante.jpg",
"mimeType": "image/jpeg"
}| Campo | Tipo | Descripción |
|---|---|---|
id | string | Identificador de la captura. |
status | received |
{
"id": "cap-1a2b3c4d5e6f",
"status": "received"
}- 400 INVALID_REQUEST:
fileUrlno es una dirección https. - 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente no existe.
- 409 CONFLICT: Cobros IA no está activado, o el cliente no tiene celular registrado.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl -X POST \
-H "Authorization: Bearer TU_LLAVE" \
-H "Content-Type: application/json" \
-d '{"fileUrl":"https://ejemplo.com/comprobante.jpg","mimeType":"image/jpeg"}' \
"https://TU-DOMINIO/api/v1/customers/1234/payment-proofs"Los pagos del cliente entre dos fechas (por defecto los últimos 30 días, hasta 93), el más reciente primero. Un pago anulado no se borra: sale con status: void.
Permiso (scope) requerido: payments:read.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
from | query | string (date) | No | Desde (AAAA-MM-DD). Por defecto, 30 días antes de to. |
to | query | string (date) | No | Hasta (AAAA-MM-DD, inclusive). Por defecto, hoy. El rango máximo es de 93 días. |
status | query | valid | void | all · por defecto valid | No | Pagos válidos, anulados o todos. |
limit | query | integer · por defecto 25 | No | Cuántos devolver (1 a 100). |
after | query | string | No | El nextCursor de la página anterior. |
| Campo | Tipo | Descripción |
|---|---|---|
payments | lista de object | |
payments[].id | string | |
payments[].invoiceId | string · puede ser null | Factura a la que se aplicó. |
payments[].invoiceNumber | string · puede ser null | |
payments[].date | string | Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
payments[].amount | number | Monto pagado. |
payments[].currency | string | |
payments[].method | string · puede ser null | Forma de pago, con el nombre que le da la empresa. |
payments[].reference | string · puede ser null | Número de operación. |
payments[].status | valid | void | void = pago anulado (no se borra). |
nextCursor | string · puede ser null | Pásalo como after para la página siguiente. null = no hay más. |
{
"payments": [
{
"id": "5501",
"invoiceId": "9001",
"invoiceNumber": "F001-0000123",
"date": "2026-10-05 14:30:00",
"amount": 30,
"currency": "PEN",
"method": "YAPE",
"reference": "00845122",
"status": "valid"
}
],
"nextCursor": null
}- 400 INVALID_REQUEST: las fechas no tienen el formato AAAA-MM-DD, el rango pasa de 93 días, o
status/afterno son válidos. - 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente no existe.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/customers/1234/payments"Los pagos de TODOS los clientes entre dos fechas (por defecto los últimos 30 días, hasta 93), el más reciente primero. Sirve para conciliar. Cada pago trae su cliente.
Permiso (scope) requerido: payments:read.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
from | query | string (date) | No | Desde (AAAA-MM-DD). Por defecto, 30 días antes de to. |
to | query | string (date) | No | Hasta (AAAA-MM-DD, inclusive). Por defecto, hoy. El rango máximo es de 93 días. |
status | query | valid | void | all · por defecto valid | No | Pagos válidos, anulados o todos. |
limit | query | integer · por defecto 25 | No | Cuántos devolver (1 a 100). |
after | query | string | No | El nextCursor de la página anterior. |
| Campo | Tipo | Descripción |
|---|---|---|
payments | lista de object | |
payments[].id | string | |
payments[].invoiceId | string · puede ser null | Factura a la que se aplicó. |
payments[].invoiceNumber | string · puede ser null | |
payments[].date | string | Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
payments[].amount | number | Monto pagado. |
payments[].currency | string | |
payments[].method | string · puede ser null | Forma de pago, con el nombre que le da la empresa. |
payments[].reference | string · puede ser null | Número de operación. |
payments[].status | valid | void | void = pago anulado (no se borra). |
payments[].customer | object | |
payments[].customer.id | string | |
payments[].customer.name | string | |
nextCursor | string · puede ser null | Pásalo como after para la página siguiente. null = no hay más. |
{
"payments": [
{
"id": "5501",
"invoiceId": "9001",
"invoiceNumber": "F001-0000123",
"date": "2026-10-05 14:30:00",
"amount": 30,
"currency": "PEN",
"method": "YAPE",
"reference": "00845122",
"status": "valid",
"customer": {
"id": "1234",
"name": "Ana Pérez"
}
}
],
"nextCursor": "5501"
}- 400 INVALID_REQUEST: las fechas no tienen el formato AAAA-MM-DD, el rango pasa de 93 días, o
status/afterno son válidos. - 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/payments"Servicio
Estado del servicio y su corte o reactivación.
Contrato, conexión (en línea o no), ONU y potencia óptica. Lo deja el monitor de la OLT y el colector de tráfico: no consulta el equipo en vivo.
Permiso (scope) requerido: service:read.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
| Campo | Tipo | Descripción |
|---|---|---|
status | active | suspended | pending | retired | |
suspendedSince | string · puede ser null | |
plan | string · puede ser null | |
speed | cualquiera | Velocidad contratada (número). |
speedUnit | string · puede ser null | |
technology | string · puede ser null | |
router | string · puede ser null | |
connection | object | |
connection.state | online | offline | unknown | |
connection.lastSeen | string · puede ser null | Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
onu | object · puede ser null | null si el cliente no tiene ONU vinculada. |
onu.serial | string · puede ser null | |
onu.olt | string · puede ser null | |
onu.pon | cualquiera | Puerto PON. |
onu.state | online | offline | unknown | |
onu.cause | string · puede ser null | Causa de la caída, si el monitor la conoce. |
onu.rxDbm | number · puede ser null | Potencia óptica recibida (dBm). |
onu.rxLevel | good | weak | critical · puede ser null | good ≥ -25 dBm; weak hasta -27.5; critical por debajo. |
onu.updatedAt | string · puede ser null | Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
actions | object | |
actions.canSuspend | boolean | |
actions.canActivate | boolean |
{
"status": "active",
"suspendedSince": null,
"plan": "Fibra 100",
"speed": 100,
"speedUnit": "Mbps",
"technology": "Fibra",
"router": "RB-Norte",
"connection": {
"state": "online",
"lastSeen": "2026-10-06 10:40:00"
},
"onu": {
"serial": "TPLG12345678",
"olt": "OLT-1",
"pon": "1/1/3",
"state": "online",
"cause": null,
"rxDbm": -21.4,
"rxLevel": "good",
"updatedAt": "2026-10-06 10:40:00"
},
"actions": {
"canSuspend": true,
"canActivate": false
}
}- 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente no existe.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/customers/1234/service"Corta el servicio con los mismos pasos que el botón Cortar del panel (estado del contrato, instalación y corte en el router). Es una acción sobre la red del cliente. Si ya estaba cortado no hace nada (changed: false). Repetir la misma Idempotency-Key (máximo 100 caracteres) devuelve la respuesta original SIN volver a ejecutar la operación; se recuerda 24 horas.
Permiso (scope) requerido: service:suspend.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
Idempotency-Key | header | string | No | Evita duplicar la operación si reintentas. Máximo 100 caracteres. |
| Campo | Tipo | Descripción |
|---|---|---|
status | active | suspended | |
changed | boolean | false si el servicio ya estaba en ese estado (repetir no hace nada). |
network | object | |
network.applied | boolean | El corte o la reconexión se aplicó en el router. |
network.note | string · puede ser null |
{
"status": "suspended",
"changed": true,
"network": {
"applied": true,
"note": null
}
}- 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente no existe.
- 409 CONFLICT: el cliente no tiene contrato, o el servicio está en instalación o dado de baja.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl -X POST \
-H "Authorization: Bearer TU_LLAVE" \
-H "Idempotency-Key: UN-ID-UNICO" \
"https://TU-DOMINIO/api/v1/customers/1234/service/suspend"Reactiva un servicio cortado con los mismos pasos que el botón Activar del panel. Una baja o una instalación no se reactivan por aquí. Si ya estaba activo no hace nada. Repetir la misma Idempotency-Key (máximo 100 caracteres) devuelve la respuesta original SIN volver a ejecutar la operación; se recuerda 24 horas.
Permiso (scope) requerido: service:activate.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
Idempotency-Key | header | string | No | Evita duplicar la operación si reintentas. Máximo 100 caracteres. |
| Campo | Tipo | Descripción |
|---|---|---|
status | active | suspended | |
changed | boolean | false si el servicio ya estaba en ese estado (repetir no hace nada). |
network | object | |
network.applied | boolean | El corte o la reconexión se aplicó en el router. |
network.note | string · puede ser null |
{
"status": "active",
"changed": true,
"network": {
"applied": true,
"note": null
}
}- 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente no existe.
- 409 CONFLICT: el cliente no tiene contrato, o solo se reactiva un servicio cortado.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl -X POST \
-H "Authorization: Bearer TU_LLAVE" \
-H "Idempotency-Key: UN-ID-UNICO" \
"https://TU-DOMINIO/api/v1/customers/1234/service/activate"Tickets
Tickets de soporte del cliente.
Hasta 50 tickets, el más reciente primero.
Permiso (scope) requerido: tickets:read.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
status | query | open | closed | all · por defecto open | No | Qué tickets devolver. |
| Campo | Tipo | Descripción |
|---|---|---|
tickets | lista de object | Hasta 50, el más reciente primero. |
tickets[].id | string | |
tickets[].number | string | |
tickets[].type | string | Motivo del ticket (catálogo de incidencias de la empresa). |
tickets[].status | open | closed | |
tickets[].createdAt | string | Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
tickets[].summary | string · puede ser null |
{
"tickets": [
{
"id": "3021",
"number": "T-3021",
"type": "AVERIA INTERNET",
"status": "open",
"createdAt": "2026-10-06 09:12:00",
"summary": "Sin internet desde la mañana"
}
]
}- 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente no existe.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/customers/1234/tickets"Crea el ticket con la misma lógica del panel (incluye el aviso al equipo). Repetir la misma Idempotency-Key (máximo 100 caracteres) devuelve la respuesta original SIN volver a ejecutar la operación; se recuerda 24 horas.
Permiso (scope) requerido: tickets:write.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
Idempotency-Key | header | string | No | Evita duplicar la operación si reintentas. Máximo 100 caracteres. |
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
type | outage | support | billing | other | No | Tipo. Un valor desconocido se toma como other. |
description | string | Sí | Obligatoria, máximo 500 caracteres. |
{
"type": "outage",
"description": "Sin internet desde la mañana"
}| Campo | Tipo | Descripción |
|---|---|---|
id | string | |
number | string | |
status | open |
{
"id": "3021",
"number": "T-3021",
"status": "open"
}- 400 INVALID_REQUEST: falta
descriptiono pasa de 500 caracteres. - 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente no existe.
- 409 CONFLICT: no hay motivos de ticket configurados, o el cliente ya tiene un ticket a esa hora.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl -X POST \
-H "Authorization: Bearer TU_LLAVE" \
-H "Idempotency-Key: UN-ID-UNICO" \
-H "Content-Type: application/json" \
-d '{"type":"outage","description":"Sin internet desde la mañana"}' \
"https://TU-DOMINIO/api/v1/customers/1234/tickets"El ticket completo de un cliente: tipo, etapa, prioridad, fechas, técnico asignado y la solución que registró al cerrarlo. El ticket debe ser de ese cliente.
Permiso (scope) requerido: tickets:read.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
ticketId | path | string | Sí | Id del ticket (el que devuelve la lista de tickets). |
| Campo | Tipo | Descripción |
|---|---|---|
id | string | |
number | string | |
type | string | Motivo del ticket. |
status | open | closed | |
stage | pending | in_progress | resolved | cancelled | Etapa: pendiente, en proceso, resuelto o cancelado. |
priority | low | medium | high | urgent | |
description | string · puede ser null | |
scheduledAt | string | Fecha programada de atención. Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
openedAt | string · puede ser null | Cuando el técnico empezó. Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
closedAt | string · puede ser null | Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
createdAt | string | Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
technician | string · puede ser null | Técnico asignado. |
resolution | object · puede ser null | La solución que registró el técnico al cerrar. |
resolution.comment | string · puede ser null | |
resolution.closedAt | string | Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
{
"id": "3021",
"number": "T-3021",
"type": "AVERIA INTERNET",
"status": "closed",
"stage": "resolved",
"priority": "high",
"description": "Sin internet desde la mañana",
"scheduledAt": "2026-10-06 09:12:00",
"openedAt": "2026-10-06 10:00:00",
"closedAt": "2026-10-06 11:30:00",
"createdAt": "2026-10-06 09:12:00",
"technician": "Luis Rojas",
"resolution": {
"comment": "Se cambió el conector",
"closedAt": "2026-10-06 11:30:00"
}
}- 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente o el ticket no existen (o el ticket no es de ese cliente).
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/customers/1234/tickets/{ticketId}"Cierra el ticket como resuelto, con la misma lógica del panel (solución, fecha y quién lo cerró). Si estaba pendiente, se atiende y se cierra en la misma operación. Un ticket ya resuelto no se vuelve a cerrar (changed: false); uno cancelado no se puede cerrar. Solo lo puede hacer una llave de un usuario administrador. Repetir la misma Idempotency-Key (máximo 100 caracteres) devuelve la respuesta original SIN volver a ejecutar la operación; se recuerda 24 horas.
Permiso (scope) requerido: tickets:close.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
Idempotency-Key | header | string | No | Evita duplicar la operación si reintentas. Máximo 100 caracteres. |
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
resolution | string | Sí | La solución que se registra al cerrar. Obligatoria, máximo 500 caracteres. |
notifyCustomer | boolean | No | Avisar al cliente que su ticket se resolvió (por los canales del sistema). Por defecto no. |
{
"resolution": "Se cambió el conector",
"notifyCustomer": false
}| Campo | Tipo | Descripción |
|---|---|---|
id | string | |
number | string | |
status | open | closed | |
stage | pending | in_progress | resolved | cancelled | |
changed | boolean | false si el ticket ya estaba resuelto (repetir no hace nada). |
closedAt | string · puede ser null | Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
{
"id": "3021",
"number": "T-3021",
"status": "closed",
"stage": "resolved",
"changed": true,
"closedAt": "2026-10-06 11:30:00"
}- 400 INVALID_REQUEST: falta
resolutiono pasa de 500 caracteres. - 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente o el ticket no existen (o el ticket no es de ese cliente).
- 409 CONFLICT: el ticket está cancelado.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl -X POST \
-H "Authorization: Bearer TU_LLAVE" \
-H "Idempotency-Key: UN-ID-UNICO" \
-H "Content-Type: application/json" \
-d '{"resolution":"Se cambió el conector","notifyCustomer":false}' \
"https://TU-DOMINIO/api/v1/customers/1234/tickets/{ticketId}/close"Red
Consumo, routers y conexión del cliente.
Descarga y subida por hora (24h) o por día (7d, 30d), con totales y el pico.
Permiso (scope) requerido: network:read.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
range | query | 24h | 7d | 30d · por defecto 24h | No | Periodo. |
| Campo | Tipo | Descripción |
|---|---|---|
range | 24h | 7d | 30d | |
unit | hour | day | hour para 24h; day para 7d y 30d. |
monitored | boolean | false si el router del cliente no envía datos de consumo. |
lastTrafficAt | string · puede ser null | Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
totals | object | |
totals.downloadBytes | integer | |
totals.uploadBytes | integer | |
peak | object · puede ser null | Pico de descarga. |
peak.at | string | |
peak.downloadBytes | integer | |
points | lista de object | |
points[].at | string | Hora (AAAA-MM-DD HH:00) o día (AAAA-MM-DD), en la zona de la empresa. |
points[].downloadBytes | integer | |
points[].uploadBytes | integer |
{
"range": "24h",
"unit": "hour",
"monitored": true,
"lastTrafficAt": "2026-10-06 10:55:00",
"totals": {
"downloadBytes": 120000000,
"uploadBytes": 8000000
},
"peak": {
"at": "2026-10-06 09:00",
"downloadBytes": 120000000
},
"points": [
{
"at": "2026-10-06 09:00",
"downloadBytes": 120000000,
"uploadBytes": 8000000
}
]
}- 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente no existe.
- 409 CONFLICT: el cliente no tiene contrato.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/customers/1234/traffic"Por cada servicio activo del cliente: su router, el usuario y perfil PPPoE (la clave nunca se entrega), la IP asignada y la cola.
Permiso (scope) requerido: network:read.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
| Campo | Tipo | Descripción |
|---|---|---|
services | lista de object | Servicios activos del cliente. |
services[].plan | string | |
services[].speed | cualquiera | Velocidad contratada (número). |
services[].speedUnit | string · puede ser null | |
services[].technology | string · puede ser null | |
services[].connectionType | internet | personalizado | personalizado = servicio a medida, sin conexión de internet gestionada. |
services[].router | object · puede ser null | |
services[].router.id | string | |
services[].router.name | string | |
services[].pppoe | object · puede ser null | Usuario y perfil PPPoE. La clave nunca se entrega. |
services[].pppoe.user | string | |
services[].pppoe.profile | string · puede ser null | |
services[].ipAddress | string · puede ser null | IP asignada. |
services[].speedLimit | string · puede ser null | |
services[].queue | string · puede ser null | Cola simple del router. |
{
"services": [
{
"plan": "Fibra 100",
"speed": 100,
"speedUnit": "MBPS",
"technology": "FIBRA",
"connectionType": "internet",
"router": {
"id": "1",
"name": "RB-Norte"
},
"pppoe": {
"user": "72194956",
"profile": "100Mbps/100Mbps"
},
"ipAddress": "10.10.0.15",
"speedLimit": null,
"queue": null
}
]
}- 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente no existe.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/customers/1234/network"Los routers con su modelo, si el sistema los gestiona, cuántos clientes tienen y el estado de su monitoreo de tráfico. Nunca se entregan su dirección de gestión, usuarios ni claves.
Permiso (scope) requerido: network:read.
| Campo | Tipo | Descripción |
|---|---|---|
routers | lista de object | |
routers[].id | string | |
routers[].name | string | |
routers[].model | string · puede ser null | |
routers[].routerosVersion | string · puede ser null | |
routers[].managed | boolean | El sistema está conectado a este router para gestionarlo. |
routers[].apiEnabled | boolean | false = el sistema lo trata como desconectado (pruebas o emergencias). |
routers[].customers | integer | Clientes con un servicio activo en este router. |
routers[].trafficMonitoring | object | |
routers[].trafficMonitoring.enabled | boolean | |
routers[].trafficMonitoring.status | string | |
routers[].trafficMonitoring.lastSeen | string · puede ser null | Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
{
"routers": [
{
"id": "1",
"name": "RB-Norte",
"model": "RB4011",
"routerosVersion": "7.14",
"managed": true,
"apiEnabled": true,
"customers": 120,
"trafficMonitoring": {
"enabled": true,
"status": "activo",
"lastSeen": "2026-10-06 10:55:00"
}
}
]
}- 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/routers"ONU y OLT
ONU del cliente y OLT de la empresa (el último estado que dejó el monitor).
La ONU vinculada al cliente y su último estado conocido, con la potencia óptica. Lo deja el monitor de la OLT: no consulta el equipo en vivo. onu es null si el cliente no tiene ONU vinculada.
Permiso (scope) requerido: onu:read.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
| Campo | Tipo | Descripción |
|---|---|---|
onu | object · puede ser null | null si el cliente no tiene ONU vinculada. |
onu.serial | string | |
onu.olt | string · puede ser null | |
onu.pon | cualquiera | Puerto PON. |
onu.state | online | offline | unknown | |
onu.cause | string · puede ser null | Causa de la caída, si el monitor la conoce. |
onu.rxDbm | number · puede ser null | Potencia óptica recibida (dBm). |
onu.rxLevel | good | weak | critical · puede ser null | good ≥ -25 dBm; weak hasta -27.5; critical por debajo. |
onu.updatedAt | string · puede ser null | Último estado del monitor. Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
onu.linkedAt | string · puede ser null | Cuándo se vinculó. Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
{
"onu": {
"serial": "TPLG12345678",
"olt": "OLT-1",
"pon": "1/1/3",
"state": "online",
"cause": null,
"rxDbm": -21.4,
"rxLevel": "good",
"updatedAt": "2026-10-06 10:40:00",
"linkedAt": "2026-03-02 09:00:00"
}
}- 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente no existe.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/customers/1234/onu"Las OLT con cuántas ONU tienen vinculadas a clientes y cuántas están en línea o caídas (según el último estado del monitor). Nunca se entregan sus conexiones (dirección, usuario, clave).
Permiso (scope) requerido: onu:read.
| Campo | Tipo | Descripción |
|---|---|---|
olts | lista de object | |
olts[].id | string | |
olts[].name | string | |
olts[].vendor | string · puede ser null | |
olts[].model | string · puede ser null | |
olts[].zone | string · puede ser null | |
olts[].onus | object | |
olts[].onus.linked | integer | ONU vinculadas a clientes. |
olts[].onus.online | integer | |
olts[].onus.offline | integer | |
olts[].onus.unknown | integer | Sin estado todavía. |
olts[].lastUpdate | string · puede ser null | Última lectura del monitor. Fecha y hora en la zona horaria de la empresa (AAAA-MM-DD HH:MM:SS). |
{
"olts": [
{
"id": "1",
"name": "OLT-1",
"vendor": "HUAWEI",
"model": "MA5800",
"zone": "Zona Norte",
"onus": {
"linked": 120,
"online": 110,
"offline": 8,
"unknown": 2
},
"lastUpdate": "2026-10-06 10:40:00"
}
]
}- 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
curl \
-H "Authorization: Bearer TU_LLAVE" \
"https://TU-DOMINIO/api/v1/olts"Envía el reinicio a la OLT en el acto, con la misma lógica del Portal Cliente. Solo la ONU activa de ese cliente. El cliente pierde la conexión unos minutos. Por seguridad, un reinicio correcto reciente (menos de 5 minutos) de la misma ONU impide otro. Repetir la misma Idempotency-Key (máximo 100 caracteres) devuelve la respuesta original SIN volver a ejecutar la operación; se recuerda 24 horas.
Permiso (scope) requerido: onu:write.
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string | Sí | Id del cliente (el que devuelve la búsqueda por celular). |
Idempotency-Key | header | string | No | Evita duplicar la operación si reintentas. Máximo 100 caracteres. |
| Campo | Tipo | Descripción |
|---|---|---|
requested | boolean | El reinicio se envió a la OLT. |
serial | string | |
olt | string · puede ser null | |
pon | cualquiera | Puerto PON. |
note | string |
{
"requested": true,
"serial": "TPLG12345678",
"olt": "OLT-1",
"pon": "1/1/3",
"note": "Reinicio enviado: el cliente pierde la conexión unos minutos."
}- 401 UNAUTHORIZED: falta la llave o no es válida.
- 403 FORBIDDEN o INSUFFICIENT_SCOPE.
- 404 NOT_FOUND: el cliente no existe.
- 409 CONFLICT: el cliente no tiene ONU vinculada, su equipo no admite reinicio remoto, su servicio está dado de baja, o ya se reinició hace menos de 5 minutos.
- 429 RATE_LIMITED.
- 500 UNAVAILABLE.
- 503 UNAVAILABLE: la OLT o el equipo no respondió.
curl -X POST \
-H "Authorization: Bearer TU_LLAVE" \
-H "Idempotency-Key: UN-ID-UNICO" \
"https://TU-DOMINIO/api/v1/customers/1234/onu/reboot"