Revoke a release
Marks the release revoked, so that its content is never served again.
From then on the release cannot be deployed and is refused on every path
that would serve it, including to a build that pins its digest, with
rel.revoked.
A release that any origin still serves cannot be revoked. An origin
serves the release of the newest deployment to it, so the call answers
409 with rel.in_use, naming each such origin and that deployment.
Deploy another release there or roll back first, then revoke. Revoking
therefore never takes an origin down. Deployments that named the release
earlier stay in the history.
Idempotent: revoking a release that is already revoked answers 200
with the release unchanged, revoked_at still naming the first
revocation. There is no un-revoke; build a new release instead.
Takes no body. The lookup is scoped to the project in project_id, so a
release id of another project answers not found exactly as an unknown id
does.
AuthorizationBearer <token>Scope: release.write
release_id*stringThe unique identifier of the release.
^rel_[a-zA-Z0-9_-]+$project_id*stringThe unique identifier of the project
^[a-zA-Z0-9_-]+$The release is revoked.
application/json- response
An immutable, project-scoped snapshot that pins one revision of every resource it includes.
A release owns pointers and metadata, not content — it records which
revisions belong together. Callers that need the resource bytes resolve each
revision_id through the per-kind read endpoints (GET /schemas/{id},
GET /flow_definitions/{id}, …).
A release exists on its own and is not tied to an origin. Deploying it is a separate call.
Two identifiers: id is the one paths and release_id fields take;
content_hash is the digest of the content the release pins, printed by
the CLI and pinned by builds, and looked up through fields that name it.
id*release-idThe opaque, immutable resource id, assigned at construction.
^rel_[a-zA-Z0-9_-]+$project_id*project-idThe project this release belongs to.
^[a-zA-Z0-9_-]+$content_hash*ReleaseContentHashThe digest of the pinned content. Identical for two releases with the same content, which is why a project never holds two such releases.
^sha256:[0-9a-f]{64}$71 <= length <= 71metadata*Who assembled the release, when, and from what source. Set when the release is assembled and never mutated afterwards.
revoked_at*|When the release was revoked, or null while it is not. A revoked release cannot be deployed and is refused on every path that would serve it, including to a build that pins its digest. No origin serves a revoked release, since a release an origin still serves cannot be revoked; earlier deployments that named it stay in the history.
pointers*array<>The revisions this release pins, one entry per (kind, handle). Never
empty: a release must contain at least one resource, and never longer
than the set POST /releases accepts.
1 <= items <= 50import { configureZitadel, getApi } from "@zitadel/api/config";import { setApiCsrfToken } from "@zitadel/api/runtime/auth";// In the browser, through the SDK proxy: the session cookie authenticates the call.const client = getApi(configureZitadel({ projectId: "proj_01KWH1P4MYS7F0N9WD3P2E4YM5" }));// A write the session cookie authenticates carries the session's CSRF token.setApiCsrfToken((await client.getMySessionCsrfToken()).csrf_token);const release = await client.revokeRelease( "rel_01KX3RG8A7F0N9WD3P2E4YM5C1", { project_id: "proj_01KWH1P4MYS7F0N9WD3P2E4YM5" },);Only revoked_at changed; the pinned set and the metadata are
immutable and stay as they were.
{ "id": "rel_01KX3RG8A7F0N9WD3P2E4YM5C1", "project_id": "proj_01KWH1P4MYS7F0N9WD3P2E4YM5", "content_hash": "sha256:9f2c1a7b4e83d05f6c2b19ae7d430f821c6b5de90a4f73829f2c1a7b4e83d05f", "metadata": { "message": "add phone_number to human-user", "git_sha": "4a5b6c7d8e9f0a1b2c3d4e5f60718293a4b5c6d7", "git_dirty": false, "created_at": "2026-07-14T09:11:00Z", "created_by": "user_01KWH3B72K7M7F0N9WD3P2E4YM", "created_by_type": "human" }, "revoked_at": "2026-07-16T16:20:00Z", "pointers": [ { "kind": "schema", "handle": "human-user", "revision_id": "sch_01KWHF18816ZQE7F0N9WD3P2E4" }, { "kind": "flow_definition", "handle": "default-login", "revision_id": "flowdef_01KWHG09JXA7F0N9WD3P2E4YM5" }, { "kind": "branding", "handle": "default", "revision_id": "brnd_01KWH1P4MYS7F0N9WD3P2E4YM5" } ]}Was this helpful?