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

ParameterTypeDescription
nodeId (path)*stringNode identifier: the node's ULID in lower case, prefixed with node_. Read in either case. Example: node_01j8x4v9k2n7q3r5s6t7v8w9xc.
Idempotency-Key (header)stringOptional 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.
FieldTypeDescription
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
  }
}
400
The Idempotency-Key header is not 1 to 255 visible ASCII characters (`idempotency_key_invalid`).

Body: Error

401
The API token is missing, unknown, expired or revoked, or the member it acts for left the organisation (`unauthenticated`).

Body: Error

403
The token lacks the ability the operation needs (`forbidden`).

Body: Error

404
The group or node does not exist or belongs to another organisation (`not_found`).

Body: Error

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.

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
  }
}
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`).

Body: Error

429
The organisation's API rate limit, 60 requests a minute by default, is exhausted (`rate_limited`); retry after the seconds in `Retry-After`.

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

ParameterTypeDescription
nodeId (path)*stringNode identifier: the node's ULID in lower case, prefixed with node_. Read in either case. Example: node_01j8x4v9k2n7q3r5s6t7v8w9xc.
Idempotency-Key (header)stringOptional 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.
FieldTypeDescription
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
  }
}
400
The Idempotency-Key header is not 1 to 255 visible ASCII characters (`idempotency_key_invalid`).

Body: Error

401
The API token is missing, unknown, expired or revoked, or the member it acts for left the organisation (`unauthenticated`).

Body: Error

403
The token lacks the ability the operation needs (`forbidden`).

Body: Error

404
The group or node does not exist or belongs to another organisation (`not_found`).

Body: Error

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.

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
  }
}
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`).

Body: Error

429
The organisation's API rate limit, 60 requests a minute by default, is exhausted (`rate_limited`); retry after the seconds in `Retry-After`.

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

ParameterTypeDescription
nodeId (path)*stringNode identifier: the node's ULID in lower case, prefixed with node_. Read in either case. Example: node_01j8x4v9k2n7q3r5s6t7v8w9xc.
Idempotency-Key (header)stringOptional 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

FieldTypeDescription
release*stringThe release deployed, prefixed with rel_.

* required

{
  "release": "rel_01j8x4v9k2n7q3r5s6t7v8w9xd"
}

Responses

200
The node and the release it runs now.
FieldTypeDescription
node*object

* required

400
The Idempotency-Key header is not 1 to 255 visible ASCII characters (`idempotency_key_invalid`).

Body: Error

401
The API token is missing, unknown, expired or revoked, or the member it acts for left the organisation (`unauthenticated`).

Body: Error

403
The token lacks the ability the operation needs (`forbidden`).

Body: Error

404
The group or node does not exist or belongs to another organisation (`not_found`).

Body: Error

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`.

Body: Error

422
The body is not valid (`validation_failed`), or the release is not one of the node's group (`release_unknown`).

Body: Error

429
The organisation's API rate limit, 60 requests a minute by default, is exhausted (`rate_limited`); retry after the seconds in `Retry-After`.

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" }'

See what Hetscale would have done with your real data — connect read-only, get your report in minutes.

Connect read-only