CaaS
Crear una app
Sección titulada «Crear una app»POST /v1/caas/{id}/apps · scope caas:write · reversible · idempotente
Crea la app y configura su origen, pero no la despliega: queda en idle hasta que llames a POST /v1/caas/{id}/apps/{app_id}/deploy. Separar las dos cosas es lo que permite crear la app, cargarle las variables y recién ahí desplegar — el orden inverso arrancaría la aplicación sin su configuración.
curl https://api.truo.cloud/v1/caas/svc_10432/apps \ -X POST \ -H "Authorization: Bearer $TRUO_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"api"}'truo caas app create svc_10432await truo.caas.apps.create("svc_10432", {"name":"api"});truo_caas({ "action": "app_create", "id": "svc_10432"})operationId: caas.apps.create
Borrar una app
Sección titulada «Borrar una app»DELETE /v1/caas/{id}/apps/{app_id} · scope caas:write · destructiva — no tiene vuelta atras · idempotente
Destructivo. Borra la app, sus variables y sus dominios. Los datos de las bases del servicio no se tocan: viven aparte.
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e \ -X DELETE \ -H "Authorization: Bearer $TRUO_TOKEN"truo caas app delete svc_10432 app_9f2c1b7eawait truo.caas.apps.delete("svc_10432", "app_9f2c1b7e");truo_caas({ "action": "app_delete", "id": "svc_10432", "appId": "app_9f2c1b7e"})operationId: caas.apps.delete
Desplegar una app
Sección titulada «Desplegar una app»POST /v1/caas/{id}/apps/{app_id}/deploy · scope caas:deploy · reversible · asincrona · idempotente
Devuelve 202 en cuanto el despliegue arranca. La operación se resuelve buscando ese despliegue en el historial de la app, que es el único lugar donde el backend reporta en qué quedó. Esperá con GET /v1/operations/{id}; el detalle de un fallo está en GET /v1/caas/{id}/apps/{app_id}/logs.
Vive en su propio scope (caas:deploy) porque desplegar ejecuta el código que haya en el origen configurado — es distinto de editar la configuración de la app.
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e/deploy \ -X POST \ -H "Authorization: Bearer $TRUO_TOKEN"truo caas deploy svc_10432 app_9f2c1b7eawait truo.caas.apps.deploy("svc_10432", "app_9f2c1b7e");truo_caas({ "action": "deploy", "id": "svc_10432", "appId": "app_9f2c1b7e"})operationId: caas.apps.deploy
Obtener una app
Sección titulada «Obtener una app»GET /v1/caas/{id}/apps/{app_id} · scope caas:read
Devuelve solo los campos declarados. El backend responde con el objeto interno completo del motor de despliegue —que incluye las variables de entorno en claro—; nada de eso sale por acá. Para los nombres de las variables, GET /v1/caas/{id}/apps/{app_id}/env.
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e \ -H "Authorization: Bearer $TRUO_TOKEN"truo caas app get svc_10432 app_9f2c1b7eawait truo.caas.apps.get("svc_10432", "app_9f2c1b7e");truo_caas({ "action": "app_get", "id": "svc_10432", "appId": "app_9f2c1b7e"})operationId: caas.apps.get
Listar las apps del servicio
Sección titulada «Listar las apps del servicio»GET /v1/caas/{id}/apps · scope caas:read
source viene en null: el backend no lo trae en el listado.
curl https://api.truo.cloud/v1/caas/svc_10432/apps \ -H "Authorization: Bearer $TRUO_TOKEN"truo caas app list svc_10432await truo.caas.apps.list("svc_10432");truo_caas({ "action": "app_list", "id": "svc_10432"})operationId: caas.apps.list
Logs de una app
Sección titulada «Logs de una app»GET /v1/caas/{id}/apps/{app_id}/logs · scope caas:read
Es una foto, no un stream. Devuelve lo que el backend tenga en el momento de la llamada y no hay forma de pedir “lo que vino después”: el backend acepta un cursor pero nunca emite el siguiente, así que este endpoint no publica ninguno. Para seguir una aplicación en vivo, volvé a llamar.
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e/logs \ -H "Authorization: Bearer $TRUO_TOKEN"truo caas logs svc_10432 app_9f2c1b7eawait truo.caas.apps.logs("svc_10432", "app_9f2c1b7e");truo_caas({ "action": "logs", "id": "svc_10432", "appId": "app_9f2c1b7e"})operationId: caas.apps.logs
Reiniciar una app
Sección titulada «Reiniciar una app»POST /v1/caas/{id}/apps/{app_id}/restart · scope caas:write · reversible · idempotente
Reinicia el proceso sin volver a construir la imagen: toma las variables de entorno actuales pero no trae código nuevo. Para eso es deploy.
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e/restart \ -X POST \ -H "Authorization: Bearer $TRUO_TOKEN"truo caas app restart svc_10432 app_9f2c1b7eawait truo.caas.apps.restart("svc_10432", "app_9f2c1b7e");truo_caas({ "action": "app_restart", "id": "svc_10432", "appId": "app_9f2c1b7e"})operationId: caas.apps.restart
Crear una base de datos
Sección titulada «Crear una base de datos»POST /v1/caas/{id}/databases · scope caas:write · reversible · idempotente
La contraseña la genera la plataforma y no se devuelve acá ni en ningún otro endpoint de /v1: no hay forma de recuperarla por esta API. Conectate desde una app del mismo servicio, donde la cadena de conexión ya está disponible.
Borrar una base no está en esta versión: el backend todavía no lo implementa y publicar un endpoint que siempre falla sería publicar roadmap.
curl https://api.truo.cloud/v1/caas/svc_10432/databases \ -X POST \ -H "Authorization: Bearer $TRUO_TOKEN" \ -H "Content-Type: application/json" \ -d '{"engine":"postgres","name":"principal"}'truo caas database create svc_10432await truo.caas.databases.create("svc_10432", {"engine":"postgres","name":"principal"});truo_caas({ "action": "database_create", "id": "svc_10432"})operationId: caas.databases.create
Bases de datos del servicio
Sección titulada «Bases de datos del servicio»GET /v1/caas/{id}/databases · scope caas:read
Son del servicio, no de una app: varias apps del mismo servicio pueden usar la misma base. Las credenciales no se devuelven por ningún endpoint de esta API.
curl https://api.truo.cloud/v1/caas/svc_10432/databases \ -H "Authorization: Bearer $TRUO_TOKEN"truo caas database list svc_10432await truo.caas.databases.list("svc_10432");truo_caas({ "action": "database_list", "id": "svc_10432"})operationId: caas.databases.list
Historial de despliegues de una app
Sección titulada «Historial de despliegues de una app»GET /v1/caas/{id}/apps/{app_id}/deployments · scope caas:read
Del más reciente al más viejo, según lo devuelve el backend.
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e/deployments \ -H "Authorization: Bearer $TRUO_TOKEN"truo caas deployment list svc_10432 app_9f2c1b7eawait truo.caas.deployments.list("svc_10432", "app_9f2c1b7e");truo_caas({ "action": "deployment_list", "id": "svc_10432", "appId": "app_9f2c1b7e"})operationId: caas.deployments.list
Agregar un dominio a una app
Sección titulada «Agregar un dominio a una app»POST /v1/caas/{id}/apps/{app_id}/domains · scope caas:write · reversible · idempotente
El DNS del host tiene que estar apuntado a la IP del servicio antes de llamar: la emisión del certificado se valida por HTTP.
Dos cosas más que hay que saber:
- No es atómico. El alta registra el dominio y después reconstruye el ruteo de entrada; si lo segundo falla, la llamada devuelve error con el dominio ya creado. Reintentar es seguro y es lo correcto — el alta es idempotente por host.
- El certificado se emite después, de forma asíncrona y sin ningún estado ni id que consultar. Por eso
certificate_typeviene ennullacá. La única verificación real es una petición HTTPS al host.
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e/domains \ -X POST \ -H "Authorization: Bearer $TRUO_TOKEN" \ -H "Content-Type: application/json" \ -d '{"host":"app.ejemplo.com"}'truo caas domain add svc_10432 app_9f2c1b7eawait truo.caas.domains.create("svc_10432", "app_9f2c1b7e", {"host":"app.ejemplo.com"});truo_caas({ "action": "domain_create", "id": "svc_10432", "appId": "app_9f2c1b7e"})operationId: caas.domains.create
Quitar un dominio de una app
Sección titulada «Quitar un dominio de una app»DELETE /v1/caas/{id}/apps/{app_id}/domains/{host} · scope caas:write · destructiva — no tiene vuelta atras · idempotente
Borrar un host que no está en la app no es un error: el ruteo de entrada se reconstruye igual, que es lo que hace que reintentar sea seguro.
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e/domains/app.ejemplo.com \ -X DELETE \ -H "Authorization: Bearer $TRUO_TOKEN"truo caas domain remove svc_10432 app_9f2c1b7e app.ejemplo.comawait truo.caas.domains.delete("svc_10432", "app_9f2c1b7e", "app.ejemplo.com");truo_caas({ "action": "domain_delete", "id": "svc_10432", "appId": "app_9f2c1b7e", "host": "app.ejemplo.com"})operationId: caas.domains.delete
Dominios de una app
Sección titulada «Dominios de una app»GET /v1/caas/{id}/apps/{app_id}/domains · scope caas:read
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e/domains \ -H "Authorization: Bearer $TRUO_TOKEN"truo caas domain list svc_10432 app_9f2c1b7eawait truo.caas.domains.list("svc_10432", "app_9f2c1b7e");truo_caas({ "action": "domain_list", "id": "svc_10432", "appId": "app_9f2c1b7e"})operationId: caas.domains.list
Nombres de las variables de entorno
Sección titulada «Nombres de las variables de entorno»GET /v1/caas/{id}/apps/{app_id}/env · scope caas:read
Devuelve los nombres, nunca los valores. No hay una versión de este endpoint que los devuelva: una vez escrito, un valor solo lo lee la aplicación. El backend enmascara aplicando una regex al nombre de la clave, lo que deja pasar en claro cualquier cosa que no se llame como un secreto (DATABASE_URL, SENTRY_DSN); eso no es una política de clasificación y no se publica.
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e/env \ -H "Authorization: Bearer $TRUO_TOKEN"truo caas env list svc_10432 app_9f2c1b7eawait truo.caas.env.list("svc_10432", "app_9f2c1b7e");truo_caas({ "action": "env_list", "id": "svc_10432", "appId": "app_9f2c1b7e"})operationId: caas.env.list
Reemplazar las variables de entorno
Sección titulada «Reemplazar las variables de entorno»PUT /v1/caas/{id}/apps/{app_id}/env · scope caas:write · destructiva — no tiene vuelta atras · idempotente
Reemplaza el conjunto entero: lo que no venga en vars se borra. No es una limitación, es la semántica del backend, que escribe el bloque completo de una.
Como GET /env no devuelve valores, el set tiene que salir de tu lado — de tu gestor de secretos o de tu repositorio de configuración. Eso es lo natural para infraestructura declarativa, y de paso elimina el modo de fallo del panel, donde guardar sin volver a escribir los secretos los borraba.
Los cambios toman efecto en el próximo deploy o restart.
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e/env \ -X PUT \ -H "Authorization: Bearer $TRUO_TOKEN" \ -H "Content-Type: application/json" \ -d '{"vars":[]}'truo caas env set svc_10432 app_9f2c1b7eawait truo.caas.env.replace("svc_10432", "app_9f2c1b7e", {"vars":[]});truo_caas({ "action": "env_replace", "id": "svc_10432", "appId": "app_9f2c1b7e"})operationId: caas.env.replace
Obtener un servicio CaaS con su estado real
Sección titulada «Obtener un servicio CaaS con su estado real»GET /v1/caas/{id} · scope caas:read
Consulta el control plane. Si no responde, provisioning_state y machine vuelven en null en vez de fallar: un hipo del control plane no debería impedirte leer el resto del recurso ni sus capabilities.
curl https://api.truo.cloud/v1/caas/svc_10432 \ -H "Authorization: Bearer $TRUO_TOKEN"truo caas get svc_10432await truo.caas.instances.get("svc_10432");truo_caas({ "action": "get", "id": "svc_10432"})operationId: caas.instances.get
Listar los servicios CaaS de la cuenta
Sección titulada «Listar los servicios CaaS de la cuenta»GET /v1/caas · scope caas:read
Sale de la base, sin consultar el control plane: provisioning_state y machine vienen en null. Traerlos costaría dos llamadas por elemento de la página.
Una página puede venir con menos elementos que el limit aunque haya más: todos los productos del control plane comparten un mismo módulo de aprovisionamiento, así que el filtro por familia solo puede aplicarse después de leer la página. has_more sigue siendo la señal correcta de si queda algo por traer.
curl https://api.truo.cloud/v1/caas \ -H "Authorization: Bearer $TRUO_TOKEN"truo caas listawait truo.caas.instances.list();truo_caas({ "action": "list"})operationId: caas.instances.list