Referencia de la API REST
Endpoints, autenticación JWT, ejemplos con curl y patrones de error de la API de HeroCtl.
La API de HeroCtl es el canal único entre tú, el CLI y la interfaz web. Todo lo que el panel muestra pasa por aquí. Todo lo que heroctl hace en la línea de comandos también.
La API es REST. JSON en la entrada, JSON en la salida. Sin GraphQL. Sin gRPC público.
Endpoint base
https://manage.<seu-dominio>/v1/
En producción estándar: https://manage.heroctl.com/v1/.
Todas las rutas viven bajo /v1/. Cuando llegue v2, v1 sigue respondiendo por al menos 12 meses.
Autenticación
La API usa JWT. Obtienes un token vía login y lo envías en cada petición:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Sin header, sin respuesta. El servidor responde 401.
Login
curl -X POST https://manage.heroctl.com/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123"}'
Respuesta:
{
"token": "eyJhbGciOi...",
"expires_at": "2026-04-27T15:00:00Z",
"refresh_token": "rt_8f3a..."
}
El token estándar dura 24 horas.
También puedes autenticarte con un ACL token (generado por la interfaz o por el CLI):
curl -X POST https://manage.heroctl.com/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"acl_token":"ht_a1b2c3d4..."}'
Refresh
Antes de que expire el token, cámbialo por uno nuevo:
curl -X POST https://manage.heroctl.com/v1/auth/refresh \
-H "Authorization: Bearer $TOKEN"
Endpoints principales
Jobs
Un job es la definición declarativa de lo que debe correr. El cluster se encarga del resto.
| Método | Ruta | Qué hace |
|---|---|---|
| GET | /v1/jobs | Lista todos los jobs |
| GET | /v1/jobs/:name | Detalle de un job |
| POST | /v1/jobs | Envía o actualiza un job |
| DELETE | /v1/jobs/:name | Elimina el job y sus instancias |
Listar jobs:
curl -s https://manage.heroctl.com/v1/jobs \
-H "Authorization: Bearer $TOKEN" | jq '.[] | .name'
Enviar un job:
curl -X POST https://manage.heroctl.com/v1/jobs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @meu-job.json
Allocations
Cada réplica de un job se vuelve una allocation. Es la unidad de ejecución real.
| Método | Ruta | Qué hace |
|---|---|---|
| GET | /v1/allocations | Lista allocations |
| GET | /v1/allocations/:id | Detalle |
| POST | /v1/allocations/:id/stop | Detiene una allocation |
curl -s "https://manage.heroctl.com/v1/allocations?job=heroctl-site" \
-H "Authorization: Bearer $TOKEN" | jq '.[] | {id, node, status}'
Nodes
Los servidores que corren workloads.
| Método | Ruta | Qué hace |
|---|---|---|
| GET | /v1/nodes | Lista nodos |
| GET | /v1/nodes/:id | Detalle (cpu, ram, disk, status) |
| POST | /v1/nodes/:id/drain | Drena un nodo (mueve workloads fuera) |
Drenar un nodo antes de mantenimiento:
curl -X POST https://manage.heroctl.com/v1/nodes/server-2/drain \
-H "Authorization: Bearer $TOKEN" \
-d '{"deadline_seconds": 300}'
Atención: drain remueve todas las allocations del nodo. Garantiza capacidad en los demás antes.
Cluster
| Método | Ruta | Qué hace |
|---|---|---|
| GET | /v1/cluster/status | Salud general, nodo coordinador, número de miembros |
| GET | /v1/cluster/peers | Lista de pares del plano de control |
| POST | /v1/raft/transfer-leadership | Transfiere coordinación (admin) |
curl -s https://manage.heroctl.com/v1/cluster/status \
-H "Authorization: Bearer $TOKEN" | jq
Secretos
Valores sensibles. Almacenados cifrados en reposo.
| Método | Ruta | Qué hace |
|---|---|---|
| GET | /v1/secrets | Lista nombres (nunca valores) |
| POST | /v1/secrets | Crea o actualiza |
| GET | /v1/secrets/:name | Lee un valor (requiere ACL específica) |
| DELETE | /v1/secrets/:name | Borra |
Crear un secreto:
curl -X POST https://manage.heroctl.com/v1/secrets \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"db_password","value":"s3nh@-forte"}'
Métricas
| Método | Ruta | Qué hace |
|---|---|---|
| GET | /v1/metrics | Snapshot actual (CPU, mem, allocs, ingress) |
| GET | /v1/metrics/query | Query histórica con ventana de tiempo |
curl -s "https://manage.heroctl.com/v1/metrics/query?metric=cpu&job=heroctl-site&from=-1h" \
-H "Authorization: Bearer $TOKEN" | jq
Logs
Los logs viven por allocation.
| Método | Ruta | Qué hace |
|---|---|---|
| GET | /v1/logs/:alloc | Últimas N líneas |
| GET | /v1/logs?stream=true | Streaming vía SSE |
Streaming en vivo:
curl -N "https://manage.heroctl.com/v1/logs?job=heroctl-site&stream=true" \
-H "Authorization: Bearer $TOKEN"
La salida viene en formato text/event-stream:
event: log
data: {"alloc":"a1b2","line":"server started"}
Health
Endpoints sin autenticación. Para uso de monitoreo externo.
| Método | Ruta | Qué hace |
|---|---|---|
| GET | /v1/health/ready | Listo para recibir tráfico |
| GET | /v1/health/live | Proceso vivo |
curl -s https://manage.heroctl.com/v1/health/ready
# {"status":"ok"}
Ingress
Dominios servidos por el cluster.
| Método | Ruta | Qué hace |
|---|---|---|
| GET | /v1/ingress | Todos los dominios activos |
| GET | /v1/ingress/:host | Detalle de un dominio (cert, rutas, job objetivo) |
curl -s https://manage.heroctl.com/v1/ingress/heroctl.com \
-H "Authorization: Bearer $TOKEN" | jq
Long polling
Varios endpoints soportan espera bloqueante. En vez de hacer poll cada segundo, pasas un índice y el tiempo máximo de espera. La respuesta vuelve cuando algo cambia — o cuando el tiempo se acaba.
curl -s "https://manage.heroctl.com/v1/jobs?wait=5m&index=42" \
-H "Authorization: Bearer $TOKEN"
index=N— índice de la última versión que viste.wait=5m— tiempo máximo de espera (máximo 10m).
Si nada cambia en 5 minutos, la respuesta vuelve con el mismo índice. Se reusa el índice en la próxima llamada.
Esto reduce tráfico y latencia drásticamente en paneles en vivo.
Rate limiting
Cada token tiene un límite de 1000 peticiones por minuto. Por encima de eso el servidor responde:
HTTP/1.1 429 Too Many Requests
Retry-After: 12
El header Retry-After indica en segundos cuándo puedes intentar de nuevo.
Los tokens admin tienen límite separado y más generoso. Para automatización pesada, pide un token de servicio dedicado.
Códigos de error
| Código | Significado |
|---|---|
| 200 | OK |
| 201 | Creado |
| 400 | Petición inválida (JSON malformado, campo faltante) |
| 401 | Token ausente, expirado o inválido |
| 403 | Token válido, pero sin permiso para la ruta |
| 404 | Recurso no existe |
| 409 | Conflicto (ej.: crear job con nombre existente) |
| 429 | Rate limit alcanzado |
| 500 | Error interno |
| 503 | Cluster temporalmente sin coordinación |
Los errores vienen con cuerpo estandarizado:
{
"error": "job_not_found",
"message": "job 'foo' não existe",
"request_id": "req_a1b2c3"
}
Siempre incluye el request_id cuando abras un ticket de soporte.
Webhooks (Plan Business)
Registras una URL y el cluster envía POSTs en eventos relevantes.
curl -X POST https://manage.heroctl.com/v1/webhooks \
-H "Authorization: Bearer $TOKEN" \
-d '{
"url": "https://api.minha-empresa.com/heroctl-events",
"events": ["job.deployed", "alloc.failed", "node.down"],
"secret": "whk_a1b2c3"
}'
Eventos disponibles:
job.submitted— nuevo job enviadojob.deployed— todas las réplicas saludablesjob.failed— deploy falló e hizo rollbackalloc.failed— una instancia cayónode.down— un servidor salió del clustercert.renewed— certificado TLS renovadosecret.changed— valor de secreto actualizado
Cada POST trae un header X-HeroCtl-Signature con HMAC-SHA256 del cuerpo, usando el secret que registraste. Valida antes de procesar.
Próximos pasos
- Ver autenticación y ACL para crear tokens con scope restringido.
- Ver troubleshooting si una llamada está retornando errores inesperados.
- Ver backup y restauración para proteger el estado que la API expone.