# Deployments

### Deploy a service

`POST /accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}/deploy`

**Required role:** editor

**Parameters**

- `name` _(path)_ · `string` · required — Service name within the environment.
- `environmentId` _(path)_ · `string` · required
- `projectId` _(path)_ · `string` · required
- `accountId` _(path)_ · `string` · required

**Request body**

- `image` · `string` · optional — Optionally pins an exact image ref; omit to deploy the service's configured source image ref.

**Returns**

- `202` · `DeploymentDto` — deployment accepted — the pipeline runs asynchronously; poll the deployment/service status
- `422` · `ErrorEnvelopeDto` — no deployable image yet

Attributes of `DeploymentDto`:

- `id` · `string` · read-only — Unique identifier of this deployment.
- `serviceId` · `string` · read-only — Identifier of the service this deployment belongs to.
- `version` · `integer` · read-only — Monotonic version number of the deployment within its service.
- `image` · `string` · optional — Resolved container image reference deployed by this release.
- `buildId` · `string` · read-only — Identifier of the build that produced this image, when built from source.
- `branch` · `string` · read-only — Git branch this release was built from, when built from a git source.
- `commit` · `string` · read-only — Resolved commit SHA this release was built from, when built from a git source.
- `archiveRef` · `string` · read-only — The uploaded build-context archive this release was built from (`koo up`).
- `status` · `"queued" | "building" | "built" | "applied" | "failed" | "superseded"` · read-only — Pipeline state, a fixed linear sequence: `queued` = accepted, waiting; `building` = the image builder is running (source builds only); `built` = image built and pushed, awaiting apply; `applied` = the release is applied to the platform — the pipeline is DONE (this is not a health verdict: the service may still be starting or unhealthy — see the service status); `failed` = the build or apply failed (see `errors`); `superseded` = a newer deployment replaced this one before it applied. Image deploys skip the build phases (queued → applied).
- `buildStage` · `string` · read-only — Live builder stage caption while `building` (e.g. "cloning", "building") — best-effort display detail; the authoritative build state is `status` + the timestamps.
- `errors` · `object[]` · read-only — Fatal pipeline failures (populated when `status` is `failed`).
- `warnings` · `object[]` · read-only — Non-fatal pipeline notes.
- `createdAt` · `string <date-time>` · read-only — When the deployment was created (= entered `queued`).
- `buildStartedAt` · `string <date-time>` · read-only — When the image build started (source builds only).
- `builtAt` · `string <date-time>` · read-only — When the image finished building and was pushed (source builds only).
- `appliedAt` · `string <date-time>` · read-only — When the release was applied to the platform.
- `healthyAt` · `string <date-time>` · read-only — When the applied release was first observed running (runtime healthy). Absent while the rollout is still in progress — and for releases that never reached healthy.
- `finishedAt` · `string <date-time>` · read-only — When the deployment terminally failed or was superseded.

**Example request**

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

**Example response** (`202`)

```json
{
  "id": "dep_01example0000000000000000x",
  "serviceId": "svc_01example0000000000000000x",
  "version": 3,
  "image": "example",
  "buildId": "bld_01example0000000000000000x",
  "branch": "example",
  "commit": "example",
  "archiveRef": "example",
  "status": "queued",
  "buildStage": "example",
  "errors": [
    {
      "message": "example",
      "at": "2026-01-01T00:00:00.000Z",
      "stage": "build"
    }
  ],
  "warnings": [
    {
      "message": "example",
      "at": "2026-01-01T00:00:00.000Z",
      "stage": "build"
    }
  ],
  "createdAt": "2026-01-01T00:00:00.000Z",
  "buildStartedAt": "2026-01-01T00:00:00.000Z",
  "builtAt": "2026-01-01T00:00:00.000Z",
  "appliedAt": "2026-01-01T00:00:00.000Z",
  "healthyAt": "2026-01-01T00:00:00.000Z",
  "finishedAt": "2026-01-01T00:00:00.000Z"
}
```

### Request a presigned upload URL for a build-context archive

`POST /accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}/uploads`

**Required role:** editor

Step 1 of `koo up`: returns a short-lived presigned PUT URL to upload a gzipped tarball of the working directory to, plus the `archiveRef` to pass to deploy-from-archive. The upload is namespaced to this service.

**Parameters**

- `name` _(path)_ · `string` · required — Service name within the environment.
- `environmentId` _(path)_ · `string` · required
- `projectId` _(path)_ · `string` · required
- `accountId` _(path)_ · `string` · required

**Request body**

- `sizeBytes` · `integer` · optional — Size of the gzipped archive in bytes (advisory; the server may cap uploads).

**Returns**

- `200` · `UploadTargetDto`
- `422` · `ErrorEnvelopeDto` — not a deployable (web) service

Attributes of `UploadTargetDto`:

- `uploadUrl` · `string <uri>` · read-only — Presigned URL to PUT the gzipped build-context tarball to.
- `archiveRef` · `string` · read-only — Opaque reference to the uploaded archive; pass it to deploy-from-archive.
- `method` · `"PUT"` · read-only — HTTP method to use for the upload.
- `contentType` · `string` · read-only — Exact Content-Type header the upload must send (signed into the URL).
- `expiresInSeconds` · `integer` · read-only — Lifetime of the presigned URL in seconds.

**Example request**

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

**Example response** (`200`)

```json
{
  "uploadUrl": "https://example.com",
  "archiveRef": "example",
  "method": "PUT",
  "contentType": "example",
  "expiresInSeconds": 0
}
```

### Deploy a previously-uploaded build-context archive

`POST /accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}/deploy-from-archive`

**Required role:** editor

Step 2 of `koo up`: builds an image from the uploaded archive (`archiveRef` from the uploads endpoint) and ships it as a new deployment. The builder fetches + extracts the archive as the build context — no git clone.

**Parameters**

- `name` _(path)_ · `string` · required — Service name within the environment.
- `environmentId` _(path)_ · `string` · required
- `projectId` _(path)_ · `string` · required
- `accountId` _(path)_ · `string` · required

**Request body**

- `archiveRef` · `string` · required — The archive reference returned by POST …/uploads.

**Returns**

- `202` · `DeploymentDto` — deployment accepted (builds + ships asynchronously) — or, for a service still being staged on the environment canvas, a staged acknowledgement `{staged: true, reason}` instead of a deployment
- `412` · `ErrorEnvelopeDto` — account not provisioned yet
- `422` · `ErrorEnvelopeDto` — not deployable, or the archive ref is not this service’s

Attributes of `DeploymentDto`:

- `id` · `string` · read-only — Unique identifier of this deployment.
- `serviceId` · `string` · read-only — Identifier of the service this deployment belongs to.
- `version` · `integer` · read-only — Monotonic version number of the deployment within its service.
- `image` · `string` · optional — Resolved container image reference deployed by this release.
- `buildId` · `string` · read-only — Identifier of the build that produced this image, when built from source.
- `branch` · `string` · read-only — Git branch this release was built from, when built from a git source.
- `commit` · `string` · read-only — Resolved commit SHA this release was built from, when built from a git source.
- `archiveRef` · `string` · read-only — The uploaded build-context archive this release was built from (`koo up`).
- `status` · `"queued" | "building" | "built" | "applied" | "failed" | "superseded"` · read-only — Pipeline state, a fixed linear sequence: `queued` = accepted, waiting; `building` = the image builder is running (source builds only); `built` = image built and pushed, awaiting apply; `applied` = the release is applied to the platform — the pipeline is DONE (this is not a health verdict: the service may still be starting or unhealthy — see the service status); `failed` = the build or apply failed (see `errors`); `superseded` = a newer deployment replaced this one before it applied. Image deploys skip the build phases (queued → applied).
- `buildStage` · `string` · read-only — Live builder stage caption while `building` (e.g. "cloning", "building") — best-effort display detail; the authoritative build state is `status` + the timestamps.
- `errors` · `object[]` · read-only — Fatal pipeline failures (populated when `status` is `failed`).
- `warnings` · `object[]` · read-only — Non-fatal pipeline notes.
- `createdAt` · `string <date-time>` · read-only — When the deployment was created (= entered `queued`).
- `buildStartedAt` · `string <date-time>` · read-only — When the image build started (source builds only).
- `builtAt` · `string <date-time>` · read-only — When the image finished building and was pushed (source builds only).
- `appliedAt` · `string <date-time>` · read-only — When the release was applied to the platform.
- `healthyAt` · `string <date-time>` · read-only — When the applied release was first observed running (runtime healthy). Absent while the rollout is still in progress — and for releases that never reached healthy.
- `finishedAt` · `string <date-time>` · read-only — When the deployment terminally failed or was superseded.

**Example request**

```bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments/:environmentId/services/:name/deploy-from-archive \
  -X POST \
  -H "Authorization: Bearer kc_your_api_token" \
  -H "Content-Type: application/json" \
  -d '{
      "archiveRef": "example"
    }'
```

**Example response** (`202`)

```json
{
  "id": "dep_01example0000000000000000x",
  "serviceId": "svc_01example0000000000000000x",
  "version": 3,
  "image": "example",
  "buildId": "bld_01example0000000000000000x",
  "branch": "example",
  "commit": "example",
  "archiveRef": "example",
  "status": "queued",
  "buildStage": "example",
  "errors": [
    {
      "message": "example",
      "at": "2026-01-01T00:00:00.000Z",
      "stage": "build"
    }
  ],
  "warnings": [
    {
      "message": "example",
      "at": "2026-01-01T00:00:00.000Z",
      "stage": "build"
    }
  ],
  "createdAt": "2026-01-01T00:00:00.000Z",
  "buildStartedAt": "2026-01-01T00:00:00.000Z",
  "builtAt": "2026-01-01T00:00:00.000Z",
  "appliedAt": "2026-01-01T00:00:00.000Z",
  "healthyAt": "2026-01-01T00:00:00.000Z",
  "finishedAt": "2026-01-01T00:00:00.000Z"
}
```

### Roll back a service to a prior deployment version

`POST /accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}/rollback`

**Required role:** editor

Redeploys a prior retained version — its image and the service configuration captured with it — as a NEW deployment. History stays immutable. Bounded by your plan’s deployment history depth.

**Parameters**

- `name` _(path)_ · `string` · required — Service name within the environment.
- `environmentId` _(path)_ · `string` · required
- `projectId` _(path)_ · `string` · required
- `accountId` _(path)_ · `string` · required

**Request body**

- `version` · `integer` · required — The prior deployment version to roll back to (must be within your plan’s history depth).

**Returns**

- `202` · `DeploymentDto` — rollback accepted — ships as a NEW deployment; the pipeline runs asynchronously
- `403` · `ErrorEnvelopeDto` — beyond your plan’s history depth (quota_exceeded)
- `404` · `ErrorEnvelopeDto` — unknown version
- `409` · `ErrorEnvelopeDto` — version was never live, or is the current release
- `422` · `ErrorEnvelopeDto` — frozen configuration or image no longer restorable

Attributes of `DeploymentDto`:

- `id` · `string` · read-only — Unique identifier of this deployment.
- `serviceId` · `string` · read-only — Identifier of the service this deployment belongs to.
- `version` · `integer` · read-only — Monotonic version number of the deployment within its service.
- `image` · `string` · optional — Resolved container image reference deployed by this release.
- `buildId` · `string` · read-only — Identifier of the build that produced this image, when built from source.
- `branch` · `string` · read-only — Git branch this release was built from, when built from a git source.
- `commit` · `string` · read-only — Resolved commit SHA this release was built from, when built from a git source.
- `archiveRef` · `string` · read-only — The uploaded build-context archive this release was built from (`koo up`).
- `status` · `"queued" | "building" | "built" | "applied" | "failed" | "superseded"` · read-only — Pipeline state, a fixed linear sequence: `queued` = accepted, waiting; `building` = the image builder is running (source builds only); `built` = image built and pushed, awaiting apply; `applied` = the release is applied to the platform — the pipeline is DONE (this is not a health verdict: the service may still be starting or unhealthy — see the service status); `failed` = the build or apply failed (see `errors`); `superseded` = a newer deployment replaced this one before it applied. Image deploys skip the build phases (queued → applied).
- `buildStage` · `string` · read-only — Live builder stage caption while `building` (e.g. "cloning", "building") — best-effort display detail; the authoritative build state is `status` + the timestamps.
- `errors` · `object[]` · read-only — Fatal pipeline failures (populated when `status` is `failed`).
- `warnings` · `object[]` · read-only — Non-fatal pipeline notes.
- `createdAt` · `string <date-time>` · read-only — When the deployment was created (= entered `queued`).
- `buildStartedAt` · `string <date-time>` · read-only — When the image build started (source builds only).
- `builtAt` · `string <date-time>` · read-only — When the image finished building and was pushed (source builds only).
- `appliedAt` · `string <date-time>` · read-only — When the release was applied to the platform.
- `healthyAt` · `string <date-time>` · read-only — When the applied release was first observed running (runtime healthy). Absent while the rollout is still in progress — and for releases that never reached healthy.
- `finishedAt` · `string <date-time>` · read-only — When the deployment terminally failed or was superseded.

**Example request**

```bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments/:environmentId/services/:name/rollback \
  -X POST \
  -H "Authorization: Bearer kc_your_api_token" \
  -H "Content-Type: application/json" \
  -d '{
      "version": 3
    }'
```

**Example response** (`202`)

```json
{
  "id": "dep_01example0000000000000000x",
  "serviceId": "svc_01example0000000000000000x",
  "version": 3,
  "image": "example",
  "buildId": "bld_01example0000000000000000x",
  "branch": "example",
  "commit": "example",
  "archiveRef": "example",
  "status": "queued",
  "buildStage": "example",
  "errors": [
    {
      "message": "example",
      "at": "2026-01-01T00:00:00.000Z",
      "stage": "build"
    }
  ],
  "warnings": [
    {
      "message": "example",
      "at": "2026-01-01T00:00:00.000Z",
      "stage": "build"
    }
  ],
  "createdAt": "2026-01-01T00:00:00.000Z",
  "buildStartedAt": "2026-01-01T00:00:00.000Z",
  "builtAt": "2026-01-01T00:00:00.000Z",
  "appliedAt": "2026-01-01T00:00:00.000Z",
  "healthyAt": "2026-01-01T00:00:00.000Z",
  "finishedAt": "2026-01-01T00:00:00.000Z"
}
```

### Build logs for one deployment (from-source deploys)

`GET /accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}/deployments/{version}/build-logs`

**Required role:** reader

The builder output for a from-source deployment: the persisted snapshot after the build finishes, or a live tail while it runs (`live: true` — poll again). Image deploys have no build and 404. Runtime logs are a separate endpoint (`…/services/:name/logs`).

**Parameters**

- `version` _(path)_ · `number` · required — Deployment version within the service.
- `name` _(path)_ · `string` · required — Service name within the environment.
- `environmentId` _(path)_ · `string` · required
- `projectId` _(path)_ · `string` · required
- `accountId` _(path)_ · `string` · required

**Returns**

- `200` · `BuildLogsResponseDto`
- `404` · `ErrorEnvelopeDto` — unknown service/version, or an image deploy (no build)

Attributes of `BuildLogsResponseDto`:

- `version` · `integer` · read-only — The deployment version these logs belong to.
- `logs` · `string` · read-only — The build output text. Empty when the build has not produced output yet.
- `truncated` · `boolean` · read-only — True when the log was tail-capped (the most recent output is kept).
- `live` · `boolean` · read-only — True when the text was proxied from the still-running builder (it may grow — poll again); false when it is the persisted terminal snapshot.
- `retrievedAt` · `string <date-time>` · read-only — When this text was read.

**Example request**

```bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments/:environmentId/services/:name/deployments/:version/build-logs \
  -H "Authorization: Bearer kc_your_api_token"
```

**Example response** (`200`)

```json
{
  "version": 3,
  "logs": "example",
  "truncated": true,
  "live": true,
  "retrievedAt": "2026-01-01T00:00:00.000Z"
}
```

### Deployment history, newest first

`GET /accounts/{accountId}/projects/{projectId}/environments/{environmentId}/services/{name}/deployments`

**Required role:** reader

**Parameters**

- `cursor` _(query)_ · `string` · optional — Opaque cursor (page.nextCursor).
- `limit` _(query)_ · `number` · optional — Page size (1–100, default 20).
- `name` _(path)_ · `string` · required — Service name within the environment.
- `environmentId` _(path)_ · `string` · required
- `projectId` _(path)_ · `string` · required
- `accountId` _(path)_ · `string` · required

**Returns**

- `200` · `DeploymentsPageDto`

Attributes of `DeploymentsPageDto`:

- `data` · `object[]` · read-only
- `page` · `object` · read-only

**Example request**

```bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments/:environmentId/services/:name/deployments \
  -H "Authorization: Bearer kc_your_api_token"
```

**Example response** (`200`)

```json
{
  "data": [
    {
      "id": "acct_01example0000000000000000x",
      "serviceId": "svc_01example0000000000000000x",
      "version": 3,
      "image": "example",
      "buildId": "bld_01example0000000000000000x",
      "branch": "example",
      "commit": "example",
      "archiveRef": "example",
      "status": "queued",
      "buildStage": "example",
      "errors": [
        {
          "message": "example",
          "at": "2026-01-01T00:00:00.000Z",
          "stage": "build"
        }
      ],
      "warnings": [
        {
          "message": "example",
          "at": "2026-01-01T00:00:00.000Z",
          "stage": "build"
        }
      ],
      "createdAt": "2026-01-01T00:00:00.000Z",
      "buildStartedAt": "2026-01-01T00:00:00.000Z",
      "builtAt": "2026-01-01T00:00:00.000Z",
      "appliedAt": "2026-01-01T00:00:00.000Z",
      "healthyAt": "2026-01-01T00:00:00.000Z",
      "finishedAt": "2026-01-01T00:00:00.000Z"
    }
  ],
  "page": {
    "nextCursor": "example",
    "hasMore": true
  }
}
```
