REST API Reference
The Zerokie CLI is a thin wrapper around the REST API. You can call the API directly for automation, CI/CD integration, or building custom tooling.
Base URL
Section titled “Base URL”https://api.platform-dev.zerokie.comAuthentication
Section titled “Authentication”All requests require an Authorization header with your API key:
Authorization: Bearer YOUR_API_KEYEndpoints
Section titled “Endpoints”Create an app
Section titled “Create an app”POST /v1/appsRequest body (container app):
{ "name": "my-app", "type": "container", "image": "nginx:alpine", "port": 80, "env": { "NODE_ENV": "production" }, "cpu": 256, "memory": 512, "registry_auth": { "username": "deploy-token", "password": "glpat-xxxx", "server_address": "registry.gitlab.com" }}Request body (static app):
{ "name": "my-site", "type": "static"}The type field is optional and defaults to "container". When type is "static", the image, port, cpu, memory, and registry_auth fields are ignored. The registry_auth object is only needed for private registries. The app type is immutable after creation.
Response (201 Created):
{ "name": "my-app", "image": "nginx:alpine", "port": 80, "status": "deploying", "url": "https://my-app.platform-dev.zerokie.com"}List apps
Section titled “List apps”GET /v1/appsResponse (200 OK):
[ { "name": "my-app", "image": "nginx:alpine", "port": 80, "status": "running", "url": "https://my-app.platform-dev.zerokie.com" }]Get app details
Section titled “Get app details”GET /v1/apps/:nameResponse (200 OK):
{ "name": "my-app", "image": "nginx:alpine", "port": 80, "status": "running", "url": "https://my-app.platform-dev.zerokie.com", "instances": 1, "cpu": 256, "memory": 512, "created_at": "2026-01-15T10:30:00Z", "updated_at": "2026-01-15T10:30:00Z"}Delete an app
Section titled “Delete an app”DELETE /v1/apps/:nameResponse (204 No Content)
Redeploy an app
Section titled “Redeploy an app”POST /v1/apps/:name/deployRequest body (optional):
{ "image": "my-registry.com/my-app:v2", "registry_auth": { "username": "deploy-token", "password": "glpat-xxxx", "server_address": "registry.gitlab.com" }}| Field | Type | Required | Description |
|---|---|---|---|
image | string | No | New Docker image to deploy. If omitted, the app re-pulls and restarts with the current image tag. |
registry_auth | object | No | Credentials for pulling from a private registry. |
registry_auth.username | string | No | Registry username or deploy token name. |
registry_auth.password | string | No | Registry password or deploy token. |
registry_auth.server_address | string | No | Registry server address (e.g. registry.gitlab.com). |
Response (200 OK):
{ "name": "my-app", "image": "my-registry.com/my-app:v2", "status": "deploying"}Static app endpoints
Section titled “Static app endpoints”The following endpoints are specific to static apps.
List remote files
Section titled “List remote files”GET /v1/apps/:name/filesReturns a flat JSON array of all files in the app’s storage zone.
Response (200 OK):
[ {"path": "index.html", "length": 1024, "lastModified": "2026-03-07T17:00:00Z"}, {"path": "assets/style.css", "length": 2048, "lastModified": "2026-03-07T17:00:00Z"}]Upload a file
Section titled “Upload a file”PUT /v1/apps/:name/files/{path}Upload a single file to the app’s storage zone. The request body is the raw file content. Set Content-Type based on the file extension.
Response (200 OK)
Delete a file
Section titled “Delete a file”DELETE /v1/apps/:name/files/{path}Delete a file from the app’s storage zone.
Response (204 No Content)
Acquire deploy lock
Section titled “Acquire deploy lock”POST /v1/apps/:name/deploy/lockAcquire a deploy lock to prevent concurrent deploys.
Request body:
{ "deploy_session_id": "550e8400-e29b-41d4-a716-446655440000"}Response (200 OK):
{ "locked": true, "deploy_session_id": "550e8400-e29b-41d4-a716-446655440000"}Returns 409 Conflict if another deploy is already in progress.
Deploy lock heartbeat
Section titled “Deploy lock heartbeat”PUT /v1/apps/:name/deploy/lockKeep the deploy lock alive during long-running deploys. Send the current deploy_session_id in the request body. The CLI sends this every 3 minutes. Locks expire after 30 minutes without a heartbeat.
Finalize deploy
Section titled “Finalize deploy”POST /v1/apps/:name/deploy/finalizeFinalize a deployment: purge the CDN cache, release the deploy lock, and record the deployment.
Request body:
{ "deploy_session_id": "550e8400-e29b-41d4-a716-446655440000", "files_uploaded": 42, "files_deleted": 3, "total_bytes": 1048576}Response (200 OK):
{ "deploy_id": "d-20260307-170000", "timestamp": "2026-03-07T17:00:00Z", "cache_purged": true, "summary": { "files_uploaded": 42, "files_deleted": 3, "total_bytes": 1048576 }}Add custom domain
Section titled “Add custom domain”POST /v1/apps/:name/domainsAdd a custom domain to a static app. Apex domains are not supported.
Request body:
{ "domain": "www.example.com"}Response (201 Created):
{ "domain": "www.example.com", "cname_target": "my-site.platform-dev.zerokie.com", "tls_status": "pending"}Remove custom domain
Section titled “Remove custom domain”DELETE /v1/apps/:name/domains/:domainRemove a custom domain from a static app.
Response (204 No Content)
Error responses
Section titled “Error responses”All errors follow a consistent format:
{ "error": "app not found"}| Status Code | Meaning |
|---|---|
400 | Invalid request (missing required fields, invalid values) |
401 | Missing or invalid API key |
404 | App not found |
409 | App name already exists / deploy lock conflict |
500 | Internal server error |
502 | Upstream service error (e.g. CDN failure) |
Rate limits
Section titled “Rate limits”The API currently does not enforce rate limits. This may change in the future.