Apps API
Container App Platform. Deploy and manage container apps with scaling controls, scale-to-zero, persistent storage, and HTTPS with automated certificate management.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /v1/apps/plans | List app plans |
GET | /v1/apps/regions | List app regions |
GET | /v1/apps | List apps |
POST | /v1/apps | Create app |
GET | /v1/apps/{app_id} | Get app |
PATCH | /v1/apps/{app_id} | Update app |
DELETE | /v1/apps/{app_id} | Delete app |
POST | /v1/apps/{app_id}/deploy/image | Deploy from image |
POST | /v1/apps/{app_id}/start | Start app |
POST | /v1/apps/{app_id}/stop | Stop app |
POST | /v1/apps/{app_id}/restart | Restart app |
GET | /v1/apps/{app_id}/logs | Get app logs |
GET /v1/apps/plans
List app plans
Get available App Platform plans with CPU, memory, storage, and pricing information.
Response example:
[
{
"id": "app-starter",
"name": "Starter",
"description": "For small production workloads",
"cpu_cores": 1.0,
"memory_mb": 1024,
"disk_gb": 10,
"max_instances": 2,
"max_apps_per_customer": 5,
"max_custom_domains": 3,
"bandwidth_gb_included": 100,
"price_monthly": 99.0,
"hourly_rate": 0.15,
"currency": "NOK",
"features": {}
}
]Example:
curl https://api.wayscloud.services/v1/apps/plans \
-H "X-API-Key: wayscloud_api_abc12_YOUR_SECRET"Response:
[
{
"id": "app-starter",
"name": "Starter",
"description": "For small production workloads",
"cpu_cores": 1.0,
"memory_mb": 1024,
"disk_gb": 10,
"max_instances": 2,
"max_apps_per_customer": 5,
"max_custom_domains": 3,
"bandwidth_gb_included": 100,
"price_monthly": 99.0,
"hourly_rate": 0.15,
"currency": "NOK",
"features": {}
}
]GET /v1/apps/regions
List app regions
Get available regions for App Platform with availability status.
Response example:
[
{
"code": "no",
"name": "Norge",
"country_code": "NO",
"app_platform_available": true
}
]Example:
curl https://api.wayscloud.services/v1/apps/regions \
-H "X-API-Key: wayscloud_api_abc12_YOUR_SECRET"Response:
[
{
"code": "no",
"name": "Norge",
"country_code": "NO",
"app_platform_available": true
}
]GET /v1/apps
List apps
Get a paginated list of all apps for the authenticated account.
Response:
| Field | Type | Description |
|---|---|---|
apps | array | |
total | integer | |
page | integer | |
page_size | integer |
Example:
curl https://api.wayscloud.services/v1/apps \
-H "X-API-Key: wayscloud_api_abc12_YOUR_SECRET"Response:
{
"apps": [
{
"id": "app_01jxr4m8k2w9n5v3q7b6t1y0z",
"name": "invoice-api-prod",
"slug": "invoice-api-prod",
"short_id": "q7b6t1y0",
"region": "no",
"plan_id": "app-starter",
"plan_name": "Starter",
"status": "running",
"default_url": "invoice-api-prod-q7b6t1y0.apps.wayscloud.services",
"instance_count": 1,
"running_instances": 1,
"max_instances": 2,
"domain_count": 0,
"scale_to_zero_enabled": false,
"is_scaled_to_zero": false,
"created_at": "2026-03-15T09:30:00Z",
"last_deployed_at": "2026-04-10T14:22:00Z",
"plan_max_apps": 5,
"plan_max_domains": 3
}
],
"total": 1,
"page": 1,
"page_size": 20
}POST /v1/apps
Create app
Create a new container app. Only name is required — all other fields have sensible defaults.
Request Body:
| Field | Type | Description |
|---|---|---|
name | string | Required. Display name for the app |
slug | string | URL slug. Auto-generated from name if omitted. Lowercase letters, numbers, and hyphens only. |
region | string | Region code (from GET /v1/apps/regions) |
plan | string | Plan ID (from GET /v1/apps/plans). Uses account default if omitted. |
port | integer | Port the app listens on |
health_check_path | string | Health check endpoint path |
env_vars | object | Environment variables as key-value pairs |
Response:
| Field | Type | Description |
|---|---|---|
id | string | |
name | string | |
slug | string | |
short_id | string | |
region | string | |
plan_id | string | |
plan_name | string | |
status | string | Values: creating, building, deploying, running, stopped, stopping, error, failed, deleting |
status_message | string | |
default_url | string | |
port | integer | |
health_check_path | string | |
min_instances | integer | |
max_instances | integer | |
scale_to_zero_enabled | boolean | |
idle_timeout_minutes | integer | |
is_scaled_to_zero | boolean | |
active_revision_id | string | |
active_deployment_id | string | |
last_deployed_at | string | |
active_image | string | Currently deployed container image URI |
created_at | string | |
updated_at | string | |
volume | object | Persistent volume metadata. Null if no volume attached. |
Example:
curl -X POST https://api.wayscloud.services/v1/apps \
-H "X-API-Key: wayscloud_api_abc12_YOUR_SECRET" \
-H "Content-Type: application/json" \
-d '{
"name": "invoice-api-prod",
"region": "no",
"plan": "app-starter",
"port": 3000,
"env_vars": {
"NODE_ENV": "production"
}
}'Response:
{
"id": "app_01jxr4m8k2w9n5v3q7b6t1y0z",
"name": "invoice-api-prod",
"slug": "invoice-api-prod",
"short_id": "q7b6t1y0",
"region": "no",
"plan_id": "app-starter",
"plan_name": "Starter",
"status": "running",
"status_message": null,
"default_url": "invoice-api-prod-q7b6t1y0.apps.wayscloud.services",
"port": 3000,
"health_check_path": "/health",
"min_instances": 1,
"max_instances": 2,
"scale_to_zero_enabled": false,
"idle_timeout_minutes": 15,
"is_scaled_to_zero": false,
"active_revision_id": "rev_01jxr5n4p8m2w7k3q9b6t0y1z",
"active_deployment_id": "dep_01jxr5n4p8m2w7k3q9b6t0y1z",
"last_deployed_at": "2026-04-10T14:22:00Z",
"active_image": "ghcr.io/acme-corp/invoice-api:v2.4.1",
"created_at": "2026-03-15T09:30:00Z",
"updated_at": "2026-04-10T14:22:00Z",
"volume": null
}GET /v1/apps/
Get app
Get full details of a specific app including configuration, deployment status, and scaling settings.
Response:
| Field | Type | Description |
|---|---|---|
id | string | |
name | string | |
slug | string | |
short_id | string | |
region | string | |
plan_id | string | |
plan_name | string | |
status | string | Values: creating, building, deploying, running, stopped, stopping, error, failed, deleting |
status_message | string | |
default_url | string | |
port | integer | |
health_check_path | string | |
min_instances | integer | |
max_instances | integer | |
scale_to_zero_enabled | boolean | |
idle_timeout_minutes | integer | |
is_scaled_to_zero | boolean | |
active_revision_id | string | |
active_deployment_id | string | |
last_deployed_at | string | |
active_image | string | Currently deployed container image URI |
created_at | string | |
updated_at | string | |
volume | object | Persistent volume metadata. Null if no volume attached. |
Example:
curl https://api.wayscloud.services/v1/apps/{app_id} \
-H "X-API-Key: wayscloud_api_abc12_YOUR_SECRET"Response:
{
"id": "app_01jxr4m8k2w9n5v3q7b6t1y0z",
"name": "invoice-api-prod",
"slug": "invoice-api-prod",
"short_id": "q7b6t1y0",
"region": "no",
"plan_id": "app-starter",
"plan_name": "Starter",
"status": "running",
"status_message": null,
"default_url": "invoice-api-prod-q7b6t1y0.apps.wayscloud.services",
"port": 3000,
"health_check_path": "/health",
"min_instances": 1,
"max_instances": 2,
"scale_to_zero_enabled": false,
"idle_timeout_minutes": 15,
"is_scaled_to_zero": false,
"active_revision_id": "rev_01jxr5n4p8m2w7k3q9b6t0y1z",
"active_deployment_id": "dep_01jxr5n4p8m2w7k3q9b6t0y1z",
"last_deployed_at": "2026-04-10T14:22:00Z",
"active_image": "ghcr.io/acme-corp/invoice-api:v2.4.1",
"created_at": "2026-03-15T09:30:00Z",
"updated_at": "2026-04-10T14:22:00Z",
"volume": null
}PATCH /v1/apps/
Update app
Update app configuration. All fields are optional — only provided fields are updated.
Mutable fields: name, port, health_check_path, min_instances, max_instances, env_vars, scale_to_zero_enabled, idle_timeout_minutes
Not mutable: plan, region, slug cannot be changed after creation.
Warning: Providing env_vars replaces the entire environment variable set for the app. To add a single variable, first GET the current app, merge your changes, then PATCH with the full set.
Request Body:
| Field | Type | Description |
|---|---|---|
name | string | |
port | integer | |
health_check_path | string | |
min_instances | integer | Minimum instances. Set to 0 to allow scale-to-zero. |
max_instances | integer | |
env_vars | object | Replaces the entire environment variable set. Not a merge — omitted variables are removed. |
scale_to_zero_enabled | boolean | Enable scale-to-zero when app is idle |
idle_timeout_minutes | integer | Minutes of inactivity before scaling to zero |
Response:
| Field | Type | Description |
|---|---|---|
id | string | |
name | string | |
slug | string | |
short_id | string | |
region | string | |
plan_id | string | |
plan_name | string | |
status | string | Values: creating, building, deploying, running, stopped, stopping, error, failed, deleting |
status_message | string | |
default_url | string | |
port | integer | |
health_check_path | string | |
min_instances | integer | |
max_instances | integer | |
scale_to_zero_enabled | boolean | |
idle_timeout_minutes | integer | |
is_scaled_to_zero | boolean | |
active_revision_id | string | |
active_deployment_id | string | |
last_deployed_at | string | |
active_image | string | Currently deployed container image URI |
created_at | string | |
updated_at | string | |
volume | object | Persistent volume metadata. Null if no volume attached. |
Example:
curl -X PATCH https://api.wayscloud.services/v1/apps/{app_id} \
-H "X-API-Key: wayscloud_api_abc12_YOUR_SECRET" \
-H "Content-Type: application/json" \
-d '{
"port": 3000,
"min_instances": 1,
"max_instances": 3,
"env_vars": {
"NODE_ENV": "production",
"LOG_LEVEL": "info"
}
}'Response:
{
"id": "app_01jxr4m8k2w9n5v3q7b6t1y0z",
"name": "invoice-api-prod",
"slug": "invoice-api-prod",
"short_id": "q7b6t1y0",
"region": "no",
"plan_id": "app-starter",
"plan_name": "Starter",
"status": "running",
"status_message": null,
"default_url": "invoice-api-prod-q7b6t1y0.apps.wayscloud.services",
"port": 3000,
"health_check_path": "/health",
"min_instances": 1,
"max_instances": 2,
"scale_to_zero_enabled": false,
"idle_timeout_minutes": 15,
"is_scaled_to_zero": false,
"active_revision_id": "rev_01jxr5n4p8m2w7k3q9b6t0y1z",
"active_deployment_id": "dep_01jxr5n4p8m2w7k3q9b6t0y1z",
"last_deployed_at": "2026-04-10T14:22:00Z",
"active_image": "ghcr.io/acme-corp/invoice-api:v2.4.1",
"created_at": "2026-03-15T09:30:00Z",
"updated_at": "2026-04-10T14:22:00Z",
"volume": null
}DELETE /v1/apps/
Delete app
Soft-delete an app. The app is marked as deleted and permanent cleanup happens asynchronously according to platform retention policies.
Response:
| Field | Type | Description |
|---|---|---|
success | boolean | |
message | string |
Example:
curl -X DELETE https://api.wayscloud.services/v1/apps/{app_id} \
-H "X-API-Key: wayscloud_api_abc12_YOUR_SECRET"Response:
{
"success": true,
"message": "App started"
}POST /v1/apps/{app_id}/deploy/image
Deploy from image
Deploy the app from a container image. The deployment is asynchronous — poll GET /v1/apps/{app_id} for status updates.
Supported registries include: registry.wayscloud.services/, ghcr.io/, docker.io/, and Docker Hub shorthand (e.g. nginx:latest, traefik/whoami).
Request Body:
| Field | Type | Description |
|---|---|---|
image_uri | string | Required. Container image URI |
Response:
| Field | Type | Description |
|---|---|---|
app_id | string | |
revision_id | string | |
deployment_id | string | |
status | string | Initial deployment status (pending) |
message | string | |
preflight_warnings | array | Warnings from pre-deploy checks |
Example:
curl -X POST https://api.wayscloud.services/v1/apps/{app_id}/deploy/image \
-H "X-API-Key: wayscloud_api_abc12_YOUR_SECRET" \
-H "Content-Type: application/json" \
-d '{
"image_uri": "ghcr.io/acme-corp/invoice-api:v2.4.1"
}'Response:
{
"app_id": "app_01jxr4m8k2w9n5v3q7b6t1y0z",
"revision_id": "rev_01jxr6a2b3c4d5e6f7g8h9i0j",
"deployment_id": "dep_01jxr6a2b3c4d5e6f7g8h9i0j",
"status": "pending",
"message": "Deployment started for image ghcr.io/acme-corp/invoice-api:v2.4.1",
"preflight_warnings": []
}POST /v1/apps/{app_id}/start
Start app
Start a stopped app or wake it from scale-to-zero state.
Response:
| Field | Type | Description |
|---|---|---|
success | boolean | |
message | string |
Example:
curl -X POST https://api.wayscloud.services/v1/apps/{app_id}/start \
-H "X-API-Key: wayscloud_api_abc12_YOUR_SECRET"Response:
{
"success": true,
"message": "App started"
}POST /v1/apps/{app_id}/stop
Stop app
Stop all running instances. The app can be restarted later.
Response:
| Field | Type | Description |
|---|---|---|
success | boolean | |
message | string |
Example:
curl -X POST https://api.wayscloud.services/v1/apps/{app_id}/stop \
-H "X-API-Key: wayscloud_api_abc12_YOUR_SECRET"Response:
{
"success": true,
"message": "App started"
}POST /v1/apps/{app_id}/restart
Restart app
Restart the app by recreating running instances.
Response:
| Field | Type | Description |
|---|---|---|
success | boolean | |
message | string |
Example:
curl -X POST https://api.wayscloud.services/v1/apps/{app_id}/restart \
-H "X-API-Key: wayscloud_api_abc12_YOUR_SECRET"Response:
{
"success": true,
"message": "App started"
}GET /v1/apps/{app_id}/logs
Get app logs
Returns the most recent container log output (stdout/stderr). This is live container output, not a historical log archive. Logs may be empty for stopped or idle apps. For persistent logging, configure your app to ship logs to an external service.
Response:
| Field | Type | Description |
|---|---|---|
app_id | string | |
instance_id | string | |
logs | array | Log entries from container output |
has_more | boolean | True if more log lines are available beyond the requested limit |
Example:
curl https://api.wayscloud.services/v1/apps/{app_id}/logs \
-H "X-API-Key: wayscloud_api_abc12_YOUR_SECRET"Response:
{
"app_id": "app_01jxr4m8k2w9n5v3q7b6t1y0z",
"instance_id": null,
"logs": [
{
"timestamp": "2026-04-12T14:22:01Z",
"message": "Server listening on port 3000",
"stream": "stdout"
},
{
"timestamp": "2026-04-12T14:22:03Z",
"message": "Connected to database",
"stream": "stdout"
}
],
"has_more": false
}