Webhooks
Generated from openapi.json 0.1.0-draft (draft)
Hetscale sends these events to the webhook URL of a group. Every delivery is signed and carries replay protection; deliveries are idempotent by node id, so a duplicate is safe to process twice. Respond with any 2xx status; failed deliveries are retried with backoff.
node.created
A new node is booted and reachable
Sent when the server is booted and reachable, so the customer's pipeline can deploy the current release to it. The node must pass the load balancer health check before deadline_at, by default 15 minutes after this event; on expiry the node is destroyed and an alert is raised. Three consecutive deploy failures pause the group. Deliveries are idempotent by node id: a duplicate delivery is safe to process twice.
Headers
| Header | Type | Description |
|---|---|---|
| X-Hetscale-Signature* | string | Proposed header name. HMAC-SHA256 over the raw request body and the timestamp, keyed with the webhook's signing secret; verify it before processing the body. |
| X-Hetscale-Timestamp* | string | Proposed header name. When the request was signed; reject deliveries outside the replay window. |
| X-Hetscale-Delivery* | string | Proposed header name. The delivery id, equal to delivery_id in the body; deliveries are idempotent by node id, so a duplicate is safe to process twice. |
* required
Payload
| Field | Type | Description |
|---|---|---|
| event* | "node.created" | The event name. |
| delivery_id* | string | Identifier of this delivery, a ULID; the same value is sent in the delivery header. |
| sent_at* | string (date-time) | When the delivery was sent. |
| group* | Group | |
| node* | Node | |
| release* | Release | |
| deadline_at* | string (date-time) | When the readiness deadline expires; by default 15 minutes after the event, after which the node is destroyed and an alert is raised. |
* required
{
"event": "node.created",
"delivery_id": "01J8X4V9K2N7Q3R5S6T7V8W9XA",
"sent_at": "2026-09-15T13:02:11Z",
"group": {
"id": "grp_01J8X4V9K2N7Q3R5S6T7V8W9XB",
"name": "api-prod",
"generation": 42
},
"node": {
"id": "node_01J8X4V9K2N7Q3R5S6T7V8W9XC",
"server_id": 12345678,
"name": "hetscale-api-prod-01J8X4V9K2N7Q3R5S6T7V8W9XC",
"class": "managed",
"phase": "DEPLOYING",
"ipv4": "203.0.113.10",
"ipv6": "2001:db8::10",
"private_ip": "10.0.1.10",
"location": "nbg1",
"server_type": "cx23",
"release": {
"id": "rel_01J8X4V9K2N7Q3R5S6T7V8W9XD",
"ref": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"build_id": "4711",
"source": "api",
"created_at": "2026-09-15T12:40:00Z"
},
"build_id": null,
"phase_entered_at": "2026-09-15T13:02:10Z"
},
"release": {
"id": "rel_01J8X4V9K2N7Q3R5S6T7V8W9XD",
"ref": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"build_id": "4711",
"source": "api",
"created_at": "2026-09-15T12:40:00Z"
},
"deadline_at": "2026-09-15T13:17:11Z"
}node.terminating
A node is leaving the group
Sent when the node enters DRAINING, before it is removed from the load balancer. After removal the load balancer sends no new connections to the node and keeps existing ones alive for the group's drain window (default 60 seconds, at most 300 seconds); the node is then shut down and deleted. Deliveries are idempotent by node id: a duplicate delivery is safe to process twice.
Headers
| Header | Type | Description |
|---|---|---|
| X-Hetscale-Signature* | string | Proposed header name. HMAC-SHA256 over the raw request body and the timestamp, keyed with the webhook's signing secret; verify it before processing the body. |
| X-Hetscale-Timestamp* | string | Proposed header name. When the request was signed; reject deliveries outside the replay window. |
| X-Hetscale-Delivery* | string | Proposed header name. The delivery id, equal to delivery_id in the body; deliveries are idempotent by node id, so a duplicate is safe to process twice. |
* required
Payload
| Field | Type | Description |
|---|---|---|
| event* | "node.terminating" | The event name. |
| delivery_id* | string | Identifier of this delivery, a ULID; the same value is sent in the delivery header. |
| sent_at* | string (date-time) | When the delivery was sent. |
| group* | Group | |
| node* | object | The node that is leaving, identified by the same values as in the inventory API. |
| reason* | string | Why the node is being removed. |
* required
{
"event": "node.terminating",
"delivery_id": "01J8X4V9K2N7Q3R5S6T7V8W9XE",
"sent_at": "2026-09-15T14:55:20Z",
"group": {
"id": "grp_01J8X4V9K2N7Q3R5S6T7V8W9XB",
"name": "api-prod",
"generation": 42
},
"node": {
"id": "node_01J8X4V9K2N7Q3R5S6T7V8W9XC",
"server_id": 12345678,
"name": "hetscale-api-prod-01J8X4V9K2N7Q3R5S6T7V8W9XC"
},
"reason": "scale-in: CPU below 35% for 10 minutes"
}group.release_changed
The group's current release changed
Sent when the group's current release pointer changes, whether through the releases endpoint or a new snapshot of the seed. Every scale-out and healing action from now on boots from the new release; nodes still running the previous one are stale.
Headers
| Header | Type | Description |
|---|---|---|
| X-Hetscale-Signature* | string | Proposed header name. HMAC-SHA256 over the raw request body and the timestamp, keyed with the webhook's signing secret; verify it before processing the body. |
| X-Hetscale-Timestamp* | string | Proposed header name. When the request was signed; reject deliveries outside the replay window. |
| X-Hetscale-Delivery* | string | Proposed header name. The delivery id, equal to delivery_id in the body; deliveries are idempotent by node id, so a duplicate is safe to process twice. |
* required
Payload
| Field | Type | Description |
|---|---|---|
| event* | "group.release_changed" | The event name. |
| delivery_id* | string | Identifier of this delivery, a ULID; the same value is sent in the delivery header. |
| sent_at* | string (date-time) | When the delivery was sent. |
| group* | Group | |
| previous_release* | Release | |
| release* | Release |
* required
{
"event": "group.release_changed",
"delivery_id": "01J8X4V9K2N7Q3R5S6T7V8W9XF",
"sent_at": "2026-09-15T12:40:01Z",
"group": {
"id": "grp_01J8X4V9K2N7Q3R5S6T7V8W9XB",
"name": "api-prod",
"generation": 42
},
"previous_release": {
"id": "rel_01J8X4V9K2N7Q3R5S6T7V8W9XG",
"ref": "sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
"build_id": "4710",
"source": "api",
"created_at": "2026-09-14T09:15:00Z"
},
"release": {
"id": "rel_01J8X4V9K2N7Q3R5S6T7V8W9XD",
"ref": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"build_id": "4711",
"source": "api",
"created_at": "2026-09-15T12:40:00Z"
}
}