API: Releases
Generated from openapi.json 0.12.0-draft (draft)
The release pointer every scale-out and healing action boots from.
Create a release and move the group's current pointer to it
post/groups/{groupId}/releasesstable
With a token that has the releases:write ability, of a member who may change the group. Records a release and makes it the group's current release. Every scale-out and every healing action boots or deploys from current; :latest is never used. The group's generation is incremented, which discards scaling decisions made against the previous release, and group.release_changed goes on the group's timeline; servers already running keep the release they booted from. For a snapshot group, ref is the numeric id of a snapshot in the group's Hetzner project, and Hetscale reads it back before it takes it: a snapshot, available, of the group's CPU architecture and no larger than the disk of the group's server type. For a webhook group, ref names the build its pipeline deploys — an image digest, a tag or a commit, 1 to 200 visible characters — never a mutable :latest; the group's endpoint receives group.release_changed, and every later node.created names the new release. The group must be Live or paused, have release v1 and no snapshot of its seed in progress. Naming the current ref and build again changes nothing and answers 200 with the current release; naming an earlier ref again is a new release.
Parameters
| Parameter | Type | Description |
|---|---|---|
| groupId (path)* | string | Group identifier: the group's ULID in lower case, prefixed with grp_. Read in either case. Example: grp_01j8x4v9k2n7q3r5s6t7v8w9xb. |
| Idempotency-Key (header) | string | Optional on every state-changing request: 1 to 255 visible ASCII characters, kept for 24 hours per organisation and bound to the token that first sent it. A retry by the same token with the same key and the same request (method, path, query string and exact body) gets the first answer again, marked Idempotent-Replayed: true, instead of a second effect. The same key with a different request, or from another token of the organisation, is answered 422 idempotency_key_reused; while the first request still runs, its own token gets 409 idempotency_key_in_flight. A request that failed validation or on the server leaves no answer behind, so its retry runs again. Example: deploy-4711-node-01j8x4v9k2n7q3r5s6t7v8w9xc. |
* required
Request body
| Field | Type | Description |
|---|---|---|
| ref* | string | The artefact to boot or deploy from: for a snapshot group the numeric id of a snapshot in the group's Hetzner project, for a webhook group the build its pipeline deploys, such as an image digest. |
| build_id | string | null | The customer's own build identifier for this release; nodes report it so stale nodes can be found. |
* required
{
"ref": "231456789",
"build_id": "4712"
}Responses
- 200
- The group already points at this image and build; nothing changed.
- 201
- The release was recorded and is now the group's current release; the group with its new generation.
- 400
- The Idempotency-Key header is not 1 to 255 visible ASCII characters (`idempotency_key_invalid`).
- 401
- The API token is missing, unknown, expired or revoked, or the member it acts for left the organisation (`unauthenticated`).
- 403
- The token lacks the ability the operation needs (`forbidden`).
- 404
- The group or node does not exist or belongs to another organisation (`not_found`).
- 409
- The group's state stands in the way: not Live or paused (`not_live`), releases from Coolify deployments (`not_snapshot_group`), no release v1 (`release_missing`) or a snapshot of the seed in progress (`snapshot_in_progress`). Also `idempotency_key_in_flight`.
- 422
- The ref cannot become the release: `ref_invalid`, `ref_mutable` (a `:latest` tag), `image_not_found`, `image_not_snapshot`, `image_not_available`, `architecture_mismatch` or `image_too_large`. Also `validation_failed` and `idempotency_key_reused`.
- 429
- The organisation's API rate limit, 60 requests a minute by default, is exhausted (`rate_limited`); retry after the seconds in `Retry-After`.
- 502
- Hetzner refused to describe the image with the project's token (`provider_error`); a retry will not help until the connection is fixed.
- 503
- Hetzner could not be asked just now (`provider_unavailable`), or Hetscale could not open the stored secrets: its key service did not answer (`key_service_unavailable`) or its master key is unavailable (`secrets_unavailable`); retry, after the seconds in `Retry-After` when it is sent.
{
"release": {
"id": "rel_01j8x4v9k2n7q3r5s6t7v8w9xe",
"version": 4,
"ref": "231456789",
"build_id": "4712",
"source": "api",
"created_at": "2026-09-15T12:40:00Z"
},
"group": {
"id": "grp_01j8x4v9k2n7q3r5s6t7v8w9xb",
"name": "api-prod",
"generation": 43
}
}Body: Error
Body: Error
Body: Error
Body: Error
Body: Error
Body: Error
Body: Error
Body: Error
Body: Error
Example
curl -X POST https://api.hetscale.com/v1/groups/grp_01j8x4v9k2n7q3r5s6t7v8w9xb/releases \
-H "Authorization: Bearer $HETSCALE_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "ref": "231456789", "build_id": "4712" }'