Referencia de la API de ingesta
Esta es la API HTTP neutral que integra cada cliente. Si construye o mantiene un paquete cliente, impleméntelo contra este contrato. Todas las rutas son JSON sobre HTTPS.
Ruta base y versionado
Los puntos de entrada de ingesta se encuentran bajo /api/v1. Envíe y acepte application/json (la subida de copias de seguridad es la única excepción, en multipart/form-data).
Autenticación
Cada petición se autentica con una clave de API de proyecto (lm_...). Se aceptan dos estilos de encabezado; la forma bearer es la recomendada:
La clave se coteja por su hash SHA-256 y se resuelve hacia un único proyecto. Los fallos de autenticación devuelven 401:
Límites de tasa
- Ingesta (
/ingest,/logs,/dependencies,/heartbeats/*): 300 peticiones por minuto, indexadas por token de proyecto. - Copias de seguridad (
/encryption-key,/backups*): 60 peticiones por minuto.
Superar un límite devuelve 429 Too Many Requests.
Cuando la ingesta está suspendida
Mientras quede un pago pendiente en la suscripción del equipo, /ingest, /logs y /dependencies responden 402 Payment Required y no almacenan nada:
Los pings de heartbeat se siguen registrando durante ese periodo, para que las tareas programadas de un equipo suspendido no parezcan rotas. Trate un 402 como un estado que registrar y mostrar, no como un error que reintentar: se levanta solo cuando el pago pasa.
Un punto de entrada de la bóveda responde 402 en el mismo periodo, con su propio mensaje: POST /backups. La lectura sigue abierta, incluido el material de clave, para que una restauración de lo que ya ha pagado siga funcionando.
Listar, descargar y eliminar una copia siguen abiertos: un archivo ya almacenado puede recuperarse igualmente. El punto de entrada de clave es el que conviene notar: también sirve el material que necesita monitor:restore, de modo que el descifrado del lado del cliente espera al pago, mientras que el blob no.
POST /api/v1/ingest, reportar una excepción
Reporta una única ocurrencia de excepción.
Cuerpo de la petición
Reglas de los campos
| Campo | Requerido | Tipo / límite |
|---|---|---|
exception.class | sí | cadena, máx. 255 |
exception.message | no | cadena, máx. 8192 |
exception.code | no | cualquiera |
exception.file | no | cadena, máx. 1024 |
exception.line | no | entero ≥ 0 |
exception.trace | no | array |
context.environment | no | cadena, máx. 100 |
context.release | no | cadena, máx. 255 (un SHA hex activa la correlación de commit) |
context.occurred_at | no | cadena, máx. 64 (fecha analizable) |
Respuestas
202 Accepted: almacenada:
``json { "message": "accepted", "stored": true, "issue_id": "01kw6tkrd8wjbfv2pktr7ssw43" } ``
202 Accepted: cuota superada, confirmada pero no almacenada:
``json { "message": "accepted", "stored": false } ``
422 Unprocessable Entity: fallo de validación.
issue_id es el identificador público de la incidencia, un ULID. Es el mismo valor que lleva la URL del panel, así que puede registrarlo y pegarlo en la barra de direcciones. No es un número de fila, y la respuesta no incluye ningún contador de ocurrencias: esos números habrían indicado a cada proyecto cuántas excepciones había almacenado toda la plataforma.
POST /api/v1/logs, reportar logs de aplicación (lote)
Almacena un lote de entradas de log. Condicionado a la funcionalidad de plan logs.
Cuerpo de la petición
Reglas de los campos
| Campo | Requerido | Tipo / límite |
|---|---|---|
logs | sí | array, de 1 a 500 entradas |
logs.*.level | no | cadena, máx. 20 |
logs.*.message | sí | cadena, máx. 8192 |
logs.*.context | no | array |
logs.*.channel | no | cadena, máx. 100 |
logs.*.environment | no | cadena, máx. 100 |
logs.*.release | no | cadena, máx. 255 |
logs.*.logged_at | no | cadena, máx. 64 |
Respuestas
202 Accepted:
``json { "message": "accepted", "stored": 137 } ``
stored indica cuántas entradas se han registrado realmente (un lote parcial se almacena cuando la cuota está casi llena).
403 Forbidden: el plan no incluye los logs:
``json { "message": "Application logs are not available on your current plan." } ``
POST /api/v1/dependencies, reportar el composer.lock
Sustituye la instantánea de dependencias del proyecto y desencadena un escaneo de vulnerabilidades en segundo plano.
Cuerpo de la petición
Reglas de los campos
| Campo | Requerido | Tipo / límite |
|---|---|---|
packages | sí | array, de 1 a 5000 entradas |
packages.*.name | sí | cadena, máx. 255 |
packages.*.version | sí | cadena, máx. 100 |
packages.*.is_dev | no | booleano |
Respuesta
202 Accepted:
``json { "message": "accepted", "dependencies": 142 } ``
POST /api/v1/heartbeats/{slug}, hacer ping a una tarea programada
Señala que una tarea programada acaba de ejecutarse. La petición no lleva cuerpo.
{slug} se normaliza a minúsculas, dígitos y guiones. El primer ping sobre un slug desconocido registra el heartbeat sin armar: queda consignado y nunca alerta hasta que se define un periodo esperado en el panel. Vea Heartbeats.
Respuestas
202 Accepted:
``json { "message": "pong", "armed": true } ``
armed indica si hay un periodo esperado definido, para que un cliente distinga un ping consignado de uno vigilado.
422 Unprocessable Entity: el slug se normaliza a una cadena vacía, o el proyecto ya contiene el número máximo de heartbeats.
Puntos de entrada de la bóveda de copias de seguridad
Estos alimentan la bóveda de copias de seguridad cifradas. Todos requieren la funcionalidad de plan backups. Mientras quede un pago pendiente, POST /backups responde 402 Payment Required; recuperar el material de clave, listar, descargar y eliminar siguen abiertos, para que monitor:restore siga funcionando sobre los archivos que ya tiene.
GET /api/v1/encryption-key
Sirve el material de clave del equipo para que el cliente pueda sellar y (con la frase secreta, en local) desenvolver.
403si el plan no incluye las copias de seguridad.404si el equipo no ha configurado claves de cifrado.
GET /api/v1/backups
POST /api/v1/backups
Subida multipart/form-data de un blob ya cifrado.
| Campo | Requerido | Observaciones |
|---|---|---|
type | sí | database o files |
name | no | cadena, máx. 255 |
file | sí | el archivo cifrado |
201 Createddevuelve los metadatos de la copia de seguridad almacenada (misma forma que una entrada de la lista).403si el plan no incluye las copias de seguridad.413 Request Entity Too Largesi la subida superaría la cuota de almacenamiento:
``json { "message": "Backup storage quota exceeded.", "used_bytes": 5012345678, "limit_bytes": 5000000000 } ``
GET /api/v1/backups/{uuid}
Transmite el blob cifrado como descarga (<nombre>.enc).
DELETE /api/v1/backups/{uuid}
Elimina la copia de seguridad. Devuelve 204 No Content.
Recapitulación de errores
| Estado | Significado |
|---|---|
202 Accepted | Ingerido (consulte stored para saber qué se ha conservado). |
201 Created | Copia de seguridad subida. |
204 No Content | Copia de seguridad eliminada. |
401 Unauthorized | Clave de API ausente o inválida. |
402 Payment Required | Ingesta, material de clave y subidas de copias suspendidos mientras quede un pago pendiente. |
403 Forbidden | Funcionalidad ausente del plan del equipo. |
404 Not Found | Claves de cifrado no configuradas (punto de entrada de clave). |
413 Payload Too Large | Cuota de almacenamiento de copias de seguridad superada. |
422 Unprocessable Entity | Fallo de validación. |
429 Too Many Requests | Límite de tasa superado. |
Está leyendo la documentación Quiet Guard v1.0.