# client.deployments

> client.deployments — the deployments operations.

`client.deployments` — the `deployments` operations.

On `AsyncKindgi` every method is the same, awaited.

## `client.deployments.list()`

```python signature
list(
    *,
    limit: int | None = None,
    cursor: str | None = None,
    image_ref_prefix: str | None = None,
    signer_key_id: str | UUID | None = None,
    project_id: str | UUID | None = None,
    pack_id: str | UUID | None = None,
    timeout: float | None = None,
) -> DeploymentCollectionPage
```

List signed deployments. `GET /v1/deployments`

Cursor-paginated. Sort order: `activatedAt` descending (binding-defined tiebreak on `deploymentId`). Only the deployments in projects the caller reads are listed (a deployment naming no project is the Default project's), so a page can hold fewer than `limit` with `hasMore` true: page by `nextCursor`, not by count. Optional `?imageRefPrefix=` narrows to deployments whose `imageRef` starts with the prefix; `?signerKeyId=` narrows to a specific signing key (useful for revocation audits); `?projectId=` to one environment (the Default also finds those naming no project); `?packId=` to one pack.

## `client.deployments.register()`

```python signature
register(
    body: DeploymentRegistrationBody | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> DeploymentRecord
```

Register a signed deployment. `POST /v1/deployments`

Atomic transaction: check the signing key against the tenant's trust list (the `signingKeyRegistry` binding), verify the Ed25519 signature over the canonical envelope, read the image's `/app/index.json` and verify it hashes to the signed `indexHash` and names the signed `artifactVersion` (`ImageRegistryBinding`), validate every tool / guardrail / agent / flow it declares (the image's index is what registers; the request carries none), upsert into the corresponding registries (in the body's `projectId`, one project per client, else the tenant's Default project), then record the deployment. Where each tool's secrets are read is recorded on its version (`RecordedSecretScope`); one set nowhere yet is read where this deployment's secrets sync writes (`POST /v1/deployments/{deploymentId}/secrets`), the scope this route needs `admin` on. All-or-nothing rollback on any failure. Idempotency: same `imageDigest` re-submitted returns 200 with the existing record (no new version bump). `Idempotency-Key` also applies at the HTTP layer.

## `client.deployments.get()`

```python signature
get(deployment_id: str | UUID, /, *, timeout: float | None = None) -> DeploymentRecord
```

Fetch a signed deployment record. `GET /v1/deployments/{deploymentId}`

## `client.deployments.pack_env()`

```python signature
pack_env(deployment_id: str | UUID, /, *, timeout: float | None = None) -> PackEnvNames
```

Show where each name a deployment's pack declares is set. `GET /v1/deployments/{deploymentId}/pack-env`

On a server that runs a pack service per deployment and gives it the env its pack declares: each declared name, where it's set (the deployment's project, then its org, then the tenant, at the env the server serves) and why it can't be given, if it can't. Never a value. A name set only as a secret can't be given into the pack service's environment yet: a tool reads it per call (`ctx.secrets`).

## `client.deployments.sync_secrets()`

```python signature
sync_secrets(
    deployment_id: str | UUID,
    body: DeploymentSecretsSyncRequest | Mapping[str, Any] | None = None,
    /,
    *,
    idempotency_key: str | None = None,
    timeout: float | None = None,
    **fields: Any,
) -> DeploymentSecretsSyncResponse
```

Sync secrets against a deployment. `POST /v1/deployments/{deploymentId}/secrets`

Deployment-scoped bulk secret sync. Body carries `{ envName, secrets: Array<{ name, ref } | { name, value }> }`. `{ name, ref }` entries validate against `SecretBinding.get` — no bytes cross the wire; missing → 404 `secret-not-found`. `{ name, value }` entries write via `SecretBinding.set` with `writeMode: add-version` + `tags.deployment = deploymentId` and return the created reference. The write scope is derived from the deployment record itself (tenant scope, or project scope when the deployment carries a `projectId`) and CANNOT be overridden on the wire. A secret the tools of this deployment name that was set nowhere when a deploy or a promotion published them is read at that scope, when whoever published them administers it: a deploy needs `admin` there, while a promotion into the Default project needs it only on that project. Requires the `secrets:write` capability. Idempotency-Key applies.

## `client.deployments.promote()`

```python signature
promote(
    deployment_id: str | UUID,
    body: DeploymentPromotionBody | Mapping[str, Any] | None = None,
    /,
    *,
    timeout: float | None = None,
    **fields: Any,
) -> DeploymentPromotion
```

Promote a deployment to the next environment. `POST /v1/deployments/{deploymentId}/promotions`

Moves the exact build a deployment runs into the next environment of its environment order: a new deployment of the target project with the same image, signature, signer and contents, and `promotedFromDeploymentId`. Nothing is built again and no registry is written. The edits of the build's agents and flows (versions made from a version it ships) move with it (`moved.agents[].carried`); edits made from a version it doesn't ship stay (`leftBehind`). Needs `read` on the deployment's project and `admin` on the target. Refused, with nothing written, when the target isn't the next environment, the deployment (or the target's copy) no longer serves, its signer is no longer trusted or its signature doesn't verify, or a value the build needs isn't ready in the target. The target having this build already answers `200` with its deployment, and records the edits made since.

## `client.deployments.promote_check()`

```python signature
promote_check(
    deployment_id: str | UUID,
    body: DeploymentPromotionCheckBody | Mapping[str, Any] | None = None,
    /,
    *,
    timeout: float | None = None,
    **fields: Any,
) -> DeploymentPromotionCheck
```

Check a promotion without making it. `POST /v1/deployments/{deploymentId}/promotions/check`

Runs every check a promotion makes and writes nothing: what would move, the next environment, and each value with a problem in the target (where a promotion refuses with `promotion-values-not-ready`). Refused as the promotion is for every other check. Needs `read` on the deployment's project and `admin` on the target.
