Skip to content

Apps API

Manage containerized apps over the REST API. See Apps for the conceptual model.

Method Path Description
POST /apps Create an app
GET /apps List apps
PUT /apps Update an app (requires id)
DELETE /apps/{id} Delete an app
GET /logs/{id}?max=N Fetch recent log lines

All requests require Authorization: Bearer <token> and project scoping (see Overview).

{
"id": "…",
"project_id": "…",
"name": "my-api",
"image": "docker.io/nginx:latest",
"args": ["--production"],
"ports": [
{ "name": "web", "number": 80, "hostname": "my-api-web-7f3a9c.hosted.ghaymah.systems" }
],
"env": [{ "name": "NODE_ENV", "value": "production" }],
"mounts": [{ "volume_id": "…", "path": "/data" }],
"cpu": 256,
"memory": 512,
"instances": 1,
"hibernated": false,
"ephemeral": false,
"pull_secret_id": "",
"version": "1.0.0",
"tags": { "team": "core" },
"status": "running",
"created_at": 1720000000,
"updated_at": 1720000123
}
Field Type Description
name string Friendly name — lowercase letters, numbers, hyphens
image string Container image to run
args string[] Arguments passed to the container command
ports Port[] Exposed ports; see below
env EnvVar[] Environment variables
mounts Mount[] Volume mounts; see Volumes API
cpu int CPU in millicores (e.g. 256 = 0.25 CPU)
memory int Memory in MB
instances int Number of replicas (1–10)
hibernated bool Sleep the app and release resources
ephemeral bool Discard the container filesystem on restart
pull_secret_id string Optional private-registry credential
version string Arbitrary app version label
tags object Free-form key: value metadata
status string Lifecycle status (running, error, failed, …)
created_at / updated_at int Unix seconds
Field Type Description
name string Port name (e.g. web)
number int Container port number
hostname string Auto-assigned public hostname (read-only)
health object Optional health check: { path, interval, timeout }
Field Type Description
name string Variable name
value string Variable value
is_secret bool Mark the value as sensitive
file_path string Mount the value as a file at this path
Terminal window
curl -X POST https://api.cumin.dev/apps \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"project_id": "…",
"name": "my-api",
"image": "docker.io/nginx:latest",
"ports": [{ "name": "web", "number": 80 }],
"env": [{ "name": "NODE_ENV", "value": "production" }],
"cpu": 256,
"memory": 512,
"instances": 1,
"hibernated": false
}'

Response:

{ "id": "…" }

The app’s status transitions to running and its public hostname is assigned automatically.

Terminal window
curl https://api.cumin.dev/apps \
-H "Authorization: Bearer $TOKEN"

PUT /apps fully replaces the app’s configuration, so include all fields. The body must include the app’s id. Use it to scale, change env vars, attach mounts, or hibernate:

Terminal window
curl -X PUT https://api.cumin.dev/apps \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "id": "<app-id>", "project_id": "…", "name": "my-api", "image": "docker.io/nginx:latest", "ports": [{ "name": "web", "number": 80 }], "instances": 3, "hibernated": false }'
Terminal window
curl -X DELETE https://api.cumin.dev/apps/<app-id> \
-H "Authorization: Bearer $TOKEN"
Terminal window
curl "https://api.cumin.dev/logs/<app-id>?max=100" \
-H "Authorization: Bearer $TOKEN"

Returns an array of log entries:

[
{ "timestamp": "2026-09-16T02:00:00Z", "message": "Listening on :80", "source": "stdout", "severity": "info" }
]

max is the number of lines to return (server-capped).

Everything above can also be done with gy:

API CLI
POST /apps gy deploy
GET /apps gy list apps
PUT /apps gy config set … && gy config sync
DELETE /apps/{id} gy delete app <name>
GET /logs/{id} gy logs <name>