Koo Docs
View as Markdown

Services

List the services in an environment

GET/accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services
Rolesreadereditoradminowner
Parameters
environmentIdstringpathrequired
projectIdstringpathrequired
accountIdstringpathrequired
Returns
200 · ServiceDto[]
cURL
GET /accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services
bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments/:environmentId/services \  -H "Authorization: Bearer kc_your_api_token"
Response
json
[  {    "id": "svc_01example0000000000000000x",    "name": "my-app",    "type": "web",    "cpu": 1,    "memory": 1,    "exposed": true,    "source": {      "type": "git",      "git": {        "provider": "github",        "repoUrl": "https://example.com",        "branch": "example",        "autoDeploy": true      },      "image": {        "ref": "example"      }    },    "imagePullCredentialsSet": true,    "runtime": {      "port": 8080,      "protocol": "http",      "healthCheckPath": "example",      "entrypoint": {        "command": "example",        "args": [          "example"        ]      }    },    "serverless": {      "enabled": true    },    "cron": {      "enabled": true,      "schedule": "example"    },    "volume": {      "id": "svc_01example0000000000000000x",      "mountPath": "example",      "sizeGb": 0,      "name": "my-app"    },    "locations": [      {        "name": "my-app",        "replicas": 1      }    ],    "domains": [      {        "hostname": "example",        "mode": "cname",        "status": "pending",        "statusReason": "example",        "dnsRecords": [          {            "type": "TXT",            "name": "my-app",            "value": "example"          }        ]      }    ],    "status": {      "applied": "pending",      "build": "pending",      "health": "starting",      "errors": [        {          "source": "applied",          "code": "dns_propagating",          "resource": "example",          "message": "example",          "at": "2026-01-01T00:00:00.000Z"        }      ],      "warnings": [        {          "source": "applied",          "code": "dns_propagating",          "resource": "example",          "message": "example",          "at": "2026-01-01T00:00:00.000Z"        }      ],      "url": "https://example.com",      "lastDeployment": {        "id": "svc_01example0000000000000000x",        "version": 3      },      "appliedAt": "2026-01-01T00:00:00.000Z",      "statusObservedAt": "2026-01-01T00:00:00.000Z"    },    "internalHost": "example",    "connection": {      "key": "example"    }  }]

Create a service in an environment

POST/accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services
Rolesreadereditoradminowner

Creates the service. A deployable web service (git/image source) starts rolling out immediately — create is deploy.

Parameters
environmentIdstringpathrequired
projectIdstringpathrequired
accountIdstringpathrequired
Request body
namestringrequired

Service name — lowercase letters, digits and dashes (3–16 chars, starts with a letter). The name is the service identity within the environment: renaming creates a new service.

type"web" | "postgres" | "redis"required

Service kind: `web` runs your own code; `postgres`/`redis` are managed addons. Immutable per name.

cpuintegerrequired

CPU limit in millicores (250, 500, or whole-vCPU multiples of 1000).

memoryintegerrequired

Memory limit in MiB (256, 512, or whole-GiB multiples of 1024).

exposedboolean

Expose the service publicly with its own URL (web services only).

addonCredentialsobject

Optional credential overrides for a managed database addon (postgres/redis), applied at create time. Ignored for web services.

imageCredentialsobject

Registry credentials for a private image source (requires an image source with a ref). Write-only — a read returns only `imagePullCredentialsSet`.

variablesstring[]

Variables to apply atomically with the service create (same shape as POST …/variables).

sourceobject

Where the deployable artifact comes from.

runtimeobject

Runtime configuration (port, protocol, health check, entrypoint). Variables are managed separately via the /variables endpoints.

serverlessobject

Run as a scale-to-zero serverless service (web only; mutually exclusive with cron/volume).

cronobject

Run as a scheduled cron job (web only; mutually exclusive with serverless/volume).

volumeobject

Attach, create, or detach a persistent volume (web only; mutually exclusive with serverless/cron).

locationsobject[]

Locations this service runs in, each with its replica count.

domainsstring[]

The full desired set of custom hostnames routed to this exposed service. Omit to leave unchanged; send `[]` to remove all. Re-read the service to see each hostname’s DNS records + live status.

Returns
201 · ServiceDto
idstringread-only

Unique identifier of the service (read-only).

namestringrequired

Service name — lowercase letters, digits and dashes (3–16 chars, starts with a letter). The name is the service identity within the environment: renaming creates a new service.

type"web" | "postgres" | "redis"required

Service kind: `web` runs your own code; `postgres`/`redis` are managed addons.

cpuintegerrequired

CPU limit in millicores (250, 500, or whole-vCPU multiples of 1000).

memoryintegerrequired

Memory limit in MiB (256, 512, or whole-GiB multiples of 1024).

exposedbooleanrequired

Whether the service is publicly reachable with its own URL (web services only).

sourceobject

Where the deployable artifact comes from.

imagePullCredentialsSetbooleanread-only

Read-only: true when private-image registry credentials are stored for this service. The credentials themselves are never returned.

runtimeobject

Runtime configuration (port, protocol, health check, entrypoint). Variables are managed separately.

serverlessobject

Present when the service runs in scale-to-zero serverless mode.

cronobject

Present when the service runs as a scheduled cron job.

volumeobject

Present when the service has an attached persistent volume.

locationsobject[]required

Locations this service runs in, each with its replica count.

domainsobject[]required

Read-only: the custom domains routing to this service, with DNS records + live status.

statusobjectread-only

Read-only: live status of the service.

internalHoststringread-only

Read-only: the internal DNS host other services reach this one at, for service-to-service wiring.

connectionRecord<string, string>read-only

Read-only: non-secret connection details for a managed addon (postgres/redis).

cURL
POST /accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services
bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments/:environmentId/services \  -X POST \  -H "Authorization: Bearer kc_your_api_token" \  -H "Content-Type: application/json" \  -d '{      "name": "my-app",      "type": "web",      "cpu": 1,      "memory": 1    }'
Response
json
{  "id": "svc_01example0000000000000000x",  "name": "my-app",  "type": "web",  "cpu": 1,  "memory": 1,  "exposed": true,  "source": {    "type": "git",    "git": {      "provider": "github",      "repoUrl": "https://example.com",      "branch": "example",      "autoDeploy": true    },    "image": {      "ref": "example"    }  },  "imagePullCredentialsSet": true,  "runtime": {    "port": 8080,    "protocol": "http",    "healthCheckPath": "example",    "entrypoint": {      "command": "example",      "args": [        "example"      ]    }  },  "serverless": {    "enabled": true  },  "cron": {    "enabled": true,    "schedule": "example"  },  "volume": {    "id": "svc_01example0000000000000000x",    "mountPath": "example",    "sizeGb": 0,    "name": "my-app"  },  "locations": [    {      "name": "my-app",      "replicas": 1    }  ],  "domains": [    {      "hostname": "example",      "mode": "cname",      "status": "pending",      "statusReason": "example",      "dnsRecords": [        {          "type": "TXT",          "name": "my-app",          "value": "example"        }      ]    }  ],  "status": {    "applied": "pending",    "build": "pending",    "health": "starting",    "errors": [      {        "source": "applied",        "code": "dns_propagating",        "resource": "example",        "message": "example",        "at": "2026-01-01T00:00:00.000Z"      }    ],    "warnings": [      {        "source": "applied",        "code": "dns_propagating",        "resource": "example",        "message": "example",        "at": "2026-01-01T00:00:00.000Z"      }    ],    "url": "https://example.com",    "lastDeployment": {      "id": "svc_01example0000000000000000x",      "version": 3    },    "appliedAt": "2026-01-01T00:00:00.000Z",    "statusObservedAt": "2026-01-01T00:00:00.000Z"  },  "internalHost": "example",  "connection": {    "key": "example"  }}

Get a service

GET/accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}
Rolesreadereditoradminowner
Parameters
namestringpathrequired

Service name within the environment.

environmentIdstringpathrequired
projectIdstringpathrequired
accountIdstringpathrequired
Returns
200 · ServiceDto
idstringread-only

Unique identifier of the service (read-only).

namestringrequired

Service name — lowercase letters, digits and dashes (3–16 chars, starts with a letter). The name is the service identity within the environment: renaming creates a new service.

type"web" | "postgres" | "redis"required

Service kind: `web` runs your own code; `postgres`/`redis` are managed addons.

cpuintegerrequired

CPU limit in millicores (250, 500, or whole-vCPU multiples of 1000).

memoryintegerrequired

Memory limit in MiB (256, 512, or whole-GiB multiples of 1024).

exposedbooleanrequired

Whether the service is publicly reachable with its own URL (web services only).

sourceobject

Where the deployable artifact comes from.

imagePullCredentialsSetbooleanread-only

Read-only: true when private-image registry credentials are stored for this service. The credentials themselves are never returned.

runtimeobject

Runtime configuration (port, protocol, health check, entrypoint). Variables are managed separately.

serverlessobject

Present when the service runs in scale-to-zero serverless mode.

cronobject

Present when the service runs as a scheduled cron job.

volumeobject

Present when the service has an attached persistent volume.

locationsobject[]required

Locations this service runs in, each with its replica count.

domainsobject[]required

Read-only: the custom domains routing to this service, with DNS records + live status.

statusobjectread-only

Read-only: live status of the service.

internalHoststringread-only

Read-only: the internal DNS host other services reach this one at, for service-to-service wiring.

connectionRecord<string, string>read-only

Read-only: non-secret connection details for a managed addon (postgres/redis).

cURL
GET /accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}
bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments/:environmentId/services/:name \  -H "Authorization: Bearer kc_your_api_token"
Response
json
{  "id": "svc_01example0000000000000000x",  "name": "my-app",  "type": "web",  "cpu": 1,  "memory": 1,  "exposed": true,  "source": {    "type": "git",    "git": {      "provider": "github",      "repoUrl": "https://example.com",      "branch": "example",      "autoDeploy": true    },    "image": {      "ref": "example"    }  },  "imagePullCredentialsSet": true,  "runtime": {    "port": 8080,    "protocol": "http",    "healthCheckPath": "example",    "entrypoint": {      "command": "example",      "args": [        "example"      ]    }  },  "serverless": {    "enabled": true  },  "cron": {    "enabled": true,    "schedule": "example"  },  "volume": {    "id": "svc_01example0000000000000000x",    "mountPath": "example",    "sizeGb": 0,    "name": "my-app"  },  "locations": [    {      "name": "my-app",      "replicas": 1    }  ],  "domains": [    {      "hostname": "example",      "mode": "cname",      "status": "pending",      "statusReason": "example",      "dnsRecords": [        {          "type": "TXT",          "name": "my-app",          "value": "example"        }      ]    }  ],  "status": {    "applied": "pending",    "build": "pending",    "health": "starting",    "errors": [      {        "source": "applied",        "code": "dns_propagating",        "resource": "example",        "message": "example",        "at": "2026-01-01T00:00:00.000Z"      }    ],    "warnings": [      {        "source": "applied",        "code": "dns_propagating",        "resource": "example",        "message": "example",        "at": "2026-01-01T00:00:00.000Z"      }    ],    "url": "https://example.com",    "lastDeployment": {      "id": "svc_01example0000000000000000x",      "version": 3    },    "appliedAt": "2026-01-01T00:00:00.000Z",    "statusObservedAt": "2026-01-01T00:00:00.000Z"  },  "internalHost": "example",  "connection": {    "key": "example"  }}

Update a service spec

PATCH/accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}
Rolesreadereditoradminowner

A deployable source change rolls out automatically.

Parameters
namestringpathrequired

Service name within the environment.

environmentIdstringpathrequired
projectIdstringpathrequired
accountIdstringpathrequired
Request body
cpuinteger

CPU limit in millicores (250, 500, or whole-vCPU multiples of 1000).

memoryinteger

Memory limit in MiB (256, 512, or whole-GiB multiples of 1024).

exposedboolean

Expose the service publicly with its own URL (web services only).

confirmDataLossboolean

Acknowledge a change that loses access to persistent-volume data: moving a volume service to a different location (destroys the disk), or attaching an existing volume to a service running in a different location than the disk (mounts a new, empty disk — the data stays with the disk). Required for those specific changes.

confirmAppImpactboolean

Acknowledge that unexposing this service degrades an active published app that points at it (the listing loses its Visit URL). Required for that specific change.

imageCredentialsobject | null

Credentials for pulling a private container image (write-only).

sourceobject

Where the deployable artifact comes from.

runtimeobject

Runtime configuration (port, protocol, health check, entrypoint). Variables are managed separately via the /variables endpoints.

serverlessobject

Run as a scale-to-zero serverless service (web only; mutually exclusive with cron/volume).

cronobject

Run as a scheduled cron job (web only; mutually exclusive with serverless/volume).

volumeobject

Attach, create, or detach a persistent volume (web only; mutually exclusive with serverless/cron).

locationsobject[]

Locations this service runs in, each with its replica count.

domainsstring[]

The full desired set of custom hostnames routed to this exposed service. Omit to leave unchanged; send `[]` to remove all. Re-read the service to see each hostname’s DNS records + live status.

Returns
200 · ServiceDto
idstringread-only

Unique identifier of the service (read-only).

namestringrequired

Service name — lowercase letters, digits and dashes (3–16 chars, starts with a letter). The name is the service identity within the environment: renaming creates a new service.

type"web" | "postgres" | "redis"required

Service kind: `web` runs your own code; `postgres`/`redis` are managed addons.

cpuintegerrequired

CPU limit in millicores (250, 500, or whole-vCPU multiples of 1000).

memoryintegerrequired

Memory limit in MiB (256, 512, or whole-GiB multiples of 1024).

exposedbooleanrequired

Whether the service is publicly reachable with its own URL (web services only).

sourceobject

Where the deployable artifact comes from.

imagePullCredentialsSetbooleanread-only

Read-only: true when private-image registry credentials are stored for this service. The credentials themselves are never returned.

runtimeobject

Runtime configuration (port, protocol, health check, entrypoint). Variables are managed separately.

serverlessobject

Present when the service runs in scale-to-zero serverless mode.

cronobject

Present when the service runs as a scheduled cron job.

volumeobject

Present when the service has an attached persistent volume.

locationsobject[]required

Locations this service runs in, each with its replica count.

domainsobject[]required

Read-only: the custom domains routing to this service, with DNS records + live status.

statusobjectread-only

Read-only: live status of the service.

internalHoststringread-only

Read-only: the internal DNS host other services reach this one at, for service-to-service wiring.

connectionRecord<string, string>read-only

Read-only: non-secret connection details for a managed addon (postgres/redis).

cURL
PATCH /accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}
bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments/:environmentId/services/:name \  -X PATCH \  -H "Authorization: Bearer kc_your_api_token" \  -H "Content-Type: application/json" \  -d '{}'
Response
json
{  "id": "svc_01example0000000000000000x",  "name": "my-app",  "type": "web",  "cpu": 1,  "memory": 1,  "exposed": true,  "source": {    "type": "git",    "git": {      "provider": "github",      "repoUrl": "https://example.com",      "branch": "example",      "autoDeploy": true    },    "image": {      "ref": "example"    }  },  "imagePullCredentialsSet": true,  "runtime": {    "port": 8080,    "protocol": "http",    "healthCheckPath": "example",    "entrypoint": {      "command": "example",      "args": [        "example"      ]    }  },  "serverless": {    "enabled": true  },  "cron": {    "enabled": true,    "schedule": "example"  },  "volume": {    "id": "svc_01example0000000000000000x",    "mountPath": "example",    "sizeGb": 0,    "name": "my-app"  },  "locations": [    {      "name": "my-app",      "replicas": 1    }  ],  "domains": [    {      "hostname": "example",      "mode": "cname",      "status": "pending",      "statusReason": "example",      "dnsRecords": [        {          "type": "TXT",          "name": "my-app",          "value": "example"        }      ]    }  ],  "status": {    "applied": "pending",    "build": "pending",    "health": "starting",    "errors": [      {        "source": "applied",        "code": "dns_propagating",        "resource": "example",        "message": "example",        "at": "2026-01-01T00:00:00.000Z"      }    ],    "warnings": [      {        "source": "applied",        "code": "dns_propagating",        "resource": "example",        "message": "example",        "at": "2026-01-01T00:00:00.000Z"      }    ],    "url": "https://example.com",    "lastDeployment": {      "id": "svc_01example0000000000000000x",      "version": 3    },    "appliedAt": "2026-01-01T00:00:00.000Z",    "statusObservedAt": "2026-01-01T00:00:00.000Z"  },  "internalHost": "example",  "connection": {    "key": "example"  }}

Delete a service

DELETE/accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}
Rolesreadereditoradminowner

Deleting a service that backs an active published app degrades its listing; pass confirmAppImpact to proceed (412 otherwise).

Parameters
namestringpathrequired

Service name within the environment.

environmentIdstringpathrequired
projectIdstringpathrequired
accountIdstringpathrequired
Request body
confirmAppImpactboolean

Must be true to proceed when this service backs an active published app: deleting it leaves the listing degraded.

Returns
204
cURL
DELETE /accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}
bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments/:environmentId/services/:name \  -X DELETE \  -H "Authorization: Bearer kc_your_api_token" \  -H "Content-Type: application/json" \  -d '{}'

Reveal a managed service’s connection details (incl. password)

GET/accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}/connection
Rolesreadereditoradminowner

The host/port/user/db + the connection URL and password for a postgres/redis service. Editor+ and audited; web services have no connection details (422).

Parameters
namestringpathrequired

Service name within the environment.

environmentIdstringpathrequired
projectIdstringpathrequired
accountIdstringpathrequired
Returns
200 · ServiceConnectionDto
cURL
GET /accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}/connection
bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments/:environmentId/services/:name/connection \  -H "Authorization: Bearer kc_your_api_token"
Response
json
{  "key": "example"}

Get the data to open an interactive shell into a running replica

GET/accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}/exec-connection
Rolesreadereditoradminowner

Returns everything the browser needs to open an interactive shell DIRECTLY against the replica’s terminal WebSocket — there is no Koo-side proxy: the per-location endpoint, the opaque connection coordinates the client passes through in the handshake, container choices, and a connect-only per-environment token (minted lazily; rotated on membership changes). List replicas via exec-replicas. Editor+ and audited; not available to OAuth authorizations.

Parameters
namestringpathrequired

Service name within the environment.

environmentIdstringpathrequired
projectIdstringpathrequired
accountIdstringpathrequired
Returns
200 · ExecConnectionDto
locationstringread-only

The location whose replicas the shell targets.

containersstring[]read-only

Container names in the service (the shell target choices).

remotestringread-only

The per-location terminal endpoint (https://…) — the browser opens the shell WebSocket at wss://{host}/remote.

orgstringread-only

Opaque account-level connection coordinate — pass it through verbatim in the terminal handshake.

gvcstringread-only

Opaque environment-level connection coordinate — pass it through verbatim in the terminal handshake.

workloadstringread-only

Opaque service-level connection coordinate — pass it through verbatim in the terminal handshake.

tokenstringread-only

A connect-only credential scoped to this environment — sent inside the binary exec-WebSocket handshake (never in the URL). Minted lazily per environment; revoked and re-minted when a member is removed or downgraded below editor.

cURL
GET /accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}/exec-connection
bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments/:environmentId/services/:name/exec-connection \  -H "Authorization: Bearer kc_your_api_token"
Response
json
{  "location": "example",  "containers": [    "example"  ],  "remote": "example",  "org": "example",  "gvc": "example",  "workload": "example",  "token": "example"}

List running replicas for an interactive shell

GET/accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}/exec-replicas
Rolesreadereditoradminowner

Lists running replicas, resolved server-side from live hosting state. Editor+.

Parameters
namestringpathrequired

Service name within the environment.

environmentIdstringpathrequired
projectIdstringpathrequired
accountIdstringpathrequired
Returns
200 · ExecReplicasDto
itemsstring[]read-only

Running replica (pod) names available to open a shell into.

cURL
GET /accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}/exec-replicas
bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments/:environmentId/services/:name/exec-replicas \  -H "Authorization: Bearer kc_your_api_token"
Response
json
{  "items": [    "example"  ]}