Load Balancer
Add a backend to a listener
Section titled “Add a backend to a listener”POST /v1/load-balancers/{id}/backends · scope lb:write · reversible · idempotent
A shortcut over PUT /listeners for the common case of adding a machine. It revalidates and applies the full configuration, so it inherits the same guarantee: either the backend ends up receiving traffic, or nothing changed.
curl https://api.truo.cloud/v1/load-balancers/svc_10432/backends \ -X POST \ -H "Authorization: Bearer $TRUO_TOKEN" \ -H "Content-Type: application/json" \ -d '{"listener":"<listener>","ip":"<ip>","port":1}'truo lb backend add svc_10432await truo.lb.backends.create("svc_10432", {"listener":"<listener>","ip":"<ip>","port":1});truo_lb({ "action": "backend_create", "id": "svc_10432"})operationId: lb.backends.create
Remove a backend from a listener
Section titled “Remove a backend from a listener”DELETE /v1/load-balancers/{id}/backends/{listener}/{ip}/{port} · scope lb:write · destructive — cannot be undone · idempotent
The three values identifying the backend go in the path. The upstream expects them in the body of a DELETE, which proxies and CDNs discard and several HTTP clients refuse to send; the body is built on this side.
A listener cannot be left without backends. Removing the last one returns 400 validation_failed: to remove the whole listener, use PUT /listeners without it.
curl https://api.truo.cloud/v1/load-balancers/svc_10432/backends/web/10.0.0.5/8080 \ -X DELETE \ -H "Authorization: Bearer $TRUO_TOKEN"truo lb backend remove svc_10432 web 10.0.0.5 8080await truo.lb.backends.delete("svc_10432", "web", "10.0.0.5", "8080");truo_lb({ "action": "backend_delete", "id": "svc_10432", "listener": "web", "ip": "10.0.0.5", "port": "8080"})operationId: lb.backends.delete
List the backends
Section titled “List the backends”GET /v1/load-balancers/{id}/backends · scope lb:read
The backends of every listener, flattened, each with the listener it belongs to. It is a view over the same configuration that GET /listeners returns.
curl https://api.truo.cloud/v1/load-balancers/svc_10432/backends \ -H "Authorization: Bearer $TRUO_TOKEN"truo lb backend list svc_10432await truo.lb.backends.list("svc_10432");truo_lb({ "action": "backend_list", "id": "svc_10432"})operationId: lb.backends.list
Get a load balancer with its live state
Section titled “Get a load balancer with its live state”GET /v1/load-balancers/{id} · scope lb:read
Queries the control plane, which in turn probes the balancer. If it does not respond, the state fields come back null instead of failing.
curl https://api.truo.cloud/v1/load-balancers/svc_10432 \ -H "Authorization: Bearer $TRUO_TOKEN"truo lb get svc_10432await truo.lb.instances.get("svc_10432");truo_lb({ "action": "get", "id": "svc_10432"})operationId: lb.instances.get
List load balancers
Section titled “List load balancers”GET /v1/load-balancers · scope lb:read
Served from the database, without querying the control plane: provisioning_state, healthy, and listener_count come back null. Fetching them would cost one call 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.
curl https://api.truo.cloud/v1/load-balancers \ -H "Authorization: Bearer $TRUO_TOKEN"truo lb listawait truo.lb.instances.list();truo_lb({ "action": "list"})operationId: lb.instances.list
List the listeners
Section titled “List the listeners”GET /v1/load-balancers/{id}/listeners · scope lb:read
The balancer’s full configuration, including each listener’s backends. It is what you read, modify, and send back in PUT.
curl https://api.truo.cloud/v1/load-balancers/svc_10432/listeners \ -H "Authorization: Bearer $TRUO_TOKEN"truo lb listener list svc_10432await truo.lb.listeners.list("svc_10432");truo_lb({ "action": "listener_list", "id": "svc_10432"})operationId: lb.listeners.list
Replace the listener configuration
Section titled “Replace the listener configuration”PUT /v1/load-balancers/{id}/listeners · scope lb:write · destructive — cannot be undone · idempotent
Replaces the entire set: listeners missing from listeners are deleted, along with their backends. Sending [] leaves the balancer with nothing listening and cuts traffic. Read GET /listeners, modify, and send everything back.
The change is applied within the call: by the time this returns, the new configuration is already serving traffic. If the resulting configuration is invalid, nothing is applied and the response is 400 validation_failed — the service is never left half-configured.
curl https://api.truo.cloud/v1/load-balancers/svc_10432/listeners \ -X PUT \ -H "Authorization: Bearer $TRUO_TOKEN" \ -H "Content-Type: application/json" \ -d '{"listeners":[]}'truo lb listener apply svc_10432await truo.lb.listeners.replace("svc_10432", {"listeners":[]});truo_lb({ "action": "listener_replace", "id": "svc_10432"})operationId: lb.listeners.replace
Get per-listener state and traffic
Section titled “Get per-listener state and traffic”GET /v1/load-balancers/{id}/stats · scope lb:read
A point-in-time snapshot: current connections and bytes accumulated since the balancer’s last start, plus each backend’s health from the latest probe. There is no historical series.
If the balancer does not answer the probe, the listeners still appear —they come from the stored configuration— with state: unknown and zeroed counters. A listener that exists but does not respond and one that exists with no traffic cannot be told apart by the counters: check state.
curl https://api.truo.cloud/v1/load-balancers/svc_10432/stats \ -H "Authorization: Bearer $TRUO_TOKEN"truo lb stats svc_10432await truo.lb.stats.get("svc_10432");truo_lb({ "action": "stats", "id": "svc_10432"})operationId: lb.stats.get