API: Nodes
Generated from openapi.json 0.12.0-draft (draft)
Optional callbacks a deploy pipeline sends about a single node.
Report that a node has been deployed
post/nodes/{nodeId}/readystable
Required for a node of a webhook group, with a token that has the nodes:report ability. Tells Hetscale the deploy pipeline has finished with the node: Hetscale then adds it to the load balancer, and traffic opens only when the balancer's per-target health check passes, whatever this report says. A node without the report before deadline_at is destroyed. The report is bound to the node's release and generation, as node.created sent them, so a late report of an older rollout changes nothing: another release or generation, or a node that no longer waits for its deploy, is answered 409 with the node as it stands. An ACTIVE node takes the report; a repeated report is answered like the first.
Parameters
| Parameter | Type | Description |
|---|---|---|
| nodeId (path)* | string | Node identifier: the node's ULID in lower case, prefixed with node_. Read in either case. Example: node_01j8x4v9k2n7q3r5s6t7v8w9xc. |
| 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
Body: NodeReport
{
"release": "rel_01j8x4v9k2n7q3r5s6t7v8w9xd",
"generation": 42
}Responses
- 202
- The report was taken, or had been taken before; the node as it stands.
- 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 report changed nothing: it names another generation (`stale_generation`) or release (`stale_release`), the node no longer waits for its deploy (`not_in_readiness`), or a failure was reported before a ready report (`failure_reported`); the body carries the node as it stands. Also `idempotency_key_in_flight` while a request with the same key still runs.
- 422
- The request body failed validation (`validation_failed`, with the messages per field), or its Idempotency-Key was sent with a different request or by another token (`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`.
| Field | Type | Description |
|---|---|---|
| node* | NodeState |
* required
{
"node": {
"id": "node_01j8x4v9k2n7q3r5s6t7v8w9xc",
"phase": "DEPLOYING",
"generation": 42,
"release": "rel_01j8x4v9k2n7q3r5s6t7v8w9xd",
"ready_reported_at": "2026-09-15T13:09:40Z",
"failed_reported_at": null
}
}Body: Error
Body: Error
Body: Error
Body: Error
Body: Error
{
"message": "The report names another generation than the node's.",
"code": "stale_generation",
"node": {
"id": "node_01j8x4v9k2n7q3r5s6t7v8w9xc",
"phase": "DEPLOYING",
"generation": 42,
"release": "rel_01j8x4v9k2n7q3r5s6t7v8w9xd",
"ready_reported_at": "2026-09-15T13:09:40Z",
"failed_reported_at": null
}
}Body: Error
Body: Error
Example
curl -X POST https://api.hetscale.com/v1/nodes/node_01j8x4v9k2n7q3r5s6t7v8w9xc/ready \
-H "Authorization: Bearer $HETSCALE_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "release": "rel_01j8x4v9k2n7q3r5s6t7v8w9xd", "generation": 42 }'Report that the deploy to a node failed
post/nodes/{nodeId}/failedstable
Optional report, with a token that has the nodes:report ability. Moves the node to DEPLOY_FAILED at once instead of waiting for the readiness deadline and records the reason in the event timeline. The failure counts toward the group's bad-release brake: three consecutive failures pause the group. The report is bound to the node's release and generation like the ready report and is taken only while the node waits for its deploy (BOOTING, DEPLOYING or HEALTH_CHECKING); a repeated report is answered like the first.
Parameters
| Parameter | Type | Description |
|---|---|---|
| nodeId (path)* | string | Node identifier: the node's ULID in lower case, prefixed with node_. Read in either case. Example: node_01j8x4v9k2n7q3r5s6t7v8w9xc. |
| 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
{
"release": "rel_01j8x4v9k2n7q3r5s6t7v8w9xd",
"generation": 42,
"reason": "docker compose up exited with status 1"
}Responses
- 202
- The report was taken, or had been taken before; the node as it stands.
- 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 report changed nothing: it names another generation (`stale_generation`) or release (`stale_release`), the node no longer waits for its deploy (`not_in_readiness`), or a failure was reported before a ready report (`failure_reported`); the body carries the node as it stands. Also `idempotency_key_in_flight` while a request with the same key still runs.
- 422
- The request body failed validation (`validation_failed`, with the messages per field), or its Idempotency-Key was sent with a different request or by another token (`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`.
| Field | Type | Description |
|---|---|---|
| node* | NodeState |
* required
{
"node": {
"id": "node_01j8x4v9k2n7q3r5s6t7v8w9xc",
"phase": "DEPLOYING",
"generation": 42,
"release": "rel_01j8x4v9k2n7q3r5s6t7v8w9xd",
"ready_reported_at": "2026-09-15T13:09:40Z",
"failed_reported_at": null
}
}Body: Error
Body: Error
Body: Error
Body: Error
Body: Error
{
"message": "The report names another generation than the node's.",
"code": "stale_generation",
"node": {
"id": "node_01j8x4v9k2n7q3r5s6t7v8w9xc",
"phase": "DEPLOYING",
"generation": 42,
"release": "rel_01j8x4v9k2n7q3r5s6t7v8w9xd",
"ready_reported_at": "2026-09-15T13:09:40Z",
"failed_reported_at": null
}
}Body: Error
Body: Error
Example
curl -X POST https://api.hetscale.com/v1/nodes/node_01j8x4v9k2n7q3r5s6t7v8w9xc/failed \
-H "Authorization: Bearer $HETSCALE_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "release": "rel_01j8x4v9k2n7q3r5s6t7v8w9xd", "generation": 42, "reason": "docker compose up exited with status 1" }'Report an in-place deploy on a node
post/nodes/{nodeId}/deployedstable
With a token that has the nodes:report ability, of a member who sees the node's group. A webhook group's pipeline says it deployed a release of the group onto the running node in place: the node runs that release now, so a rollout no longer counts it older, and node.deployed goes on the group's timeline. The release the node already runs changes nothing.
Parameters
| Parameter | Type | Description |
|---|---|---|
| nodeId (path)* | string | Node identifier: the node's ULID in lower case, prefixed with node_. Read in either case. Example: node_01j8x4v9k2n7q3r5s6t7v8w9xc. |
| 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 |
|---|---|---|
| release* | string | The release deployed, prefixed with rel_. |
* required
{
"release": "rel_01j8x4v9k2n7q3r5s6t7v8w9xd"
}Responses
- 200
- The node and the release it runs now.
- 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 node's group takes no in-place report (`not_webhook_group`), or the node is not managed (`node_not_managed`) or not serving (`node_not_active`). Also `idempotency_key_in_flight`.
- 422
- The body is not valid (`validation_failed`), or the release is not one of the node's group (`release_unknown`).
- 429
- The organisation's API rate limit, 60 requests a minute by default, is exhausted (`rate_limited`); retry after the seconds in `Retry-After`.
| Field | Type | Description |
|---|---|---|
| node* | object |
* required
Body: Error
Body: Error
Body: Error
Body: Error
Body: Error
Body: Error
Body: Error
Example
curl -X POST https://api.hetscale.com/v1/nodes/node_01j8x4v9k2n7q3r5s6t7v8w9xc/deployed \
-H "Authorization: Bearer $HETSCALE_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "release": "rel_01j8x4v9k2n7q3r5s6t7v8w9xd" }'