Skip to content

CaaS

POST /v1/caas/{id}/apps · scope caas:write · reversible · idempotent

Creates the app and configures its source, but does not deploy it: it stays idle until you call POST /v1/caas/{id}/apps/{app_id}/deploy. Separating the two is what lets you create the app, load its variables, and only then deploy — the reverse order would start the application without its configuration.

Terminal window
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"}'

operationId: caas.apps.create

DELETE /v1/caas/{id}/apps/{app_id} · scope caas:write · destructive — cannot be undone · idempotent

Destructive. Deletes the app, its variables, and its domains. The service’s database data is untouched: it lives separately.

Terminal window
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e \
-X DELETE \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: caas.apps.delete

POST /v1/caas/{id}/apps/{app_id}/deploy · scope caas:deploy · reversible · asynchronous · idempotent

Returns 202 as soon as the deployment starts. The operation resolves by looking up that deployment in the app’s history, the only place the backend reports its outcome. Wait on it with GET /v1/operations/{id}; failure details are in GET /v1/caas/{id}/apps/{app_id}/logs.

It lives in its own scope (caas:deploy) because deploying executes whatever code is in the configured source — which is different from editing the app’s configuration.

Terminal window
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e/deploy \
-X POST \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: caas.apps.deploy

GET /v1/caas/{id}/apps/{app_id} · scope caas:read

Returns only the declared fields. The backend responds with the deployment engine’s full internal object —including plaintext environment variables—; none of that leaves through here. For variable names, use GET /v1/caas/{id}/apps/{app_id}/env.

Terminal window
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: caas.apps.get

GET /v1/caas/{id}/apps · scope caas:read

source comes back null: the backend does not include it in the listing.

Terminal window
curl https://api.truo.cloud/v1/caas/svc_10432/apps \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: caas.apps.list

GET /v1/caas/{id}/apps/{app_id}/logs · scope caas:read

A snapshot, not a stream. Returns whatever the backend has at call time, and there is no way to ask for “what came after”: the backend accepts a cursor but never emits the next one, so this endpoint publishes none. To follow an application live, call again.

Terminal window
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e/logs \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: caas.apps.logs

POST /v1/caas/{id}/apps/{app_id}/restart · scope caas:write · reversible · idempotent

Restarts the process without rebuilding the image: it picks up the current environment variables but does not pull new code. That is what deploy is for.

Terminal window
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e/restart \
-X POST \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: caas.apps.restart

POST /v1/caas/{id}/databases · scope caas:write · reversible · idempotent

The platform generates the password and it is not returned here or by any other /v1 endpoint: there is no way to recover it through this API. Connect from an app in the same service, where the connection string is already available.

Deleting a database is not in this version: the backend does not implement it yet, and publishing an endpoint that always fails would be publishing roadmap.

Terminal window
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":"main"}'

operationId: caas.databases.create

GET /v1/caas/{id}/databases · scope caas:read

They belong to the service, not to an app: several apps in the same service can use the same database. Credentials are not returned by any endpoint of this API.

Terminal window
curl https://api.truo.cloud/v1/caas/svc_10432/databases \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: caas.databases.list

GET /v1/caas/{id}/apps/{app_id}/deployments · scope caas:read

Newest first, as the backend returns it.

Terminal window
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e/deployments \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: caas.deployments.list

POST /v1/caas/{id}/apps/{app_id}/domains · scope caas:write · reversible · idempotent

The host’s DNS must point at the service’s IP before you call: certificate issuance is validated over HTTP.

Two more things to know:

  • It is not atomic. Creation registers the domain and then rebuilds the ingress routing; if the second step fails, the call returns an error with the domain already created. Retrying is safe and is the right move — creation is idempotent per host.
  • The certificate is issued afterwards, asynchronously, with no state or id to query. That is why certificate_type comes back null here. The only real check is an HTTPS request to the host.
Terminal window
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.example.com"}'

operationId: caas.domains.create

DELETE /v1/caas/{id}/apps/{app_id}/domains/{host} · scope caas:write · destructive — cannot be undone · idempotent

Deleting a host that is not on the app is not an error: the ingress routing is rebuilt either way, which is what makes retrying safe.

Terminal window
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e/domains/app.example.com \
-X DELETE \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: caas.domains.delete

GET /v1/caas/{id}/apps/{app_id}/domains · scope caas:read

Terminal window
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e/domains \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: caas.domains.list

GET /v1/caas/{id}/apps/{app_id}/env · scope caas:read

Returns names, never values. There is no version of this endpoint that returns them: once written, a value is read only by the application. The backend masks by applying a regex to the key name, which lets anything not named like a secret (DATABASE_URL, SENTRY_DSN) through in plaintext; that is not a classification policy and it is not published.

Terminal window
curl https://api.truo.cloud/v1/caas/svc_10432/apps/app_9f2c1b7e/env \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: caas.env.list

PUT /v1/caas/{id}/apps/{app_id}/env · scope caas:write · destructive — cannot be undone · idempotent

Replaces the entire set: anything missing from vars is deleted. Not a limitation — it is the semantics of the backend, which writes the whole block at once.

Since GET /env returns no values, the set has to come from your side — your secrets manager or your configuration repository. That is the natural shape for declarative infrastructure, and it also removes the panel’s failure mode, where saving without rewriting the secrets erased them.

Changes take effect on the next deploy or restart.

Terminal window
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":[]}'

operationId: caas.env.replace

GET /v1/caas/{id} · scope caas:read

Queries the control plane. If it does not respond, provisioning_state and machine come back null instead of failing: a control plane hiccup should not stop you from reading the rest of the resource or its capabilities.

Terminal window
curl https://api.truo.cloud/v1/caas/svc_10432 \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: caas.instances.get

GET /v1/caas · scope caas:read

Served from the database, without querying the control plane: provisioning_state and machine come back null. Fetching them would cost two calls per page item.

A page can come back with fewer items than limit even when more exist: every control plane product shares the same provisioning module, so the family filter can only be applied after reading the page. has_more remains the correct signal for whether anything is left to fetch.

Terminal window
curl https://api.truo.cloud/v1/caas \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: caas.instances.list