Webhooks

Generated from openapi.json 0.12.0-draft (draft)

Hetscale sends node.created, node.terminating and group.release_changed to a node group's deployment webhook (the webhook adapter), and timeline, alert and ping to an organisation's webhook integration (Integrations). Every delivery is signed and carries replay protection; deliveries are deduplicated by delivery_id, and a retry repeats the same delivery_id and body, so a receiver that stores seen delivery ids can process a duplicate safely. Respond with any 2xx status; failed deliveries are retried with backoff.

timeline

A timeline event of one of the organisation's groups

Sent to an integration webhook that takes every event (Pro, the Integrations page): one delivery per event of the organisation's groups' timelines, the moment the write it describes commits. event and the X-Hetscale-Event header carry the event's name, such as node.routed, decision.scale_out or group.settings_changed; the timeline's own figures are not sent. Deliveries are not ordered: order them by occurred_at, and deduplicate them by delivery_id.

Headers

HeaderTypeDescription
X-Hetscale-Signature*stringOne v1=<hex> value per secret that signs now, comma-separated: the HMAC-SHA256 of <timestamp>.<body> with the endpoint's signing secret, where <timestamp> is X-Hetscale-Timestamp and <body> the raw request body. After a rotation the previous secret signs alongside the new one for 24 hours. Accept the delivery when one value matches, before you parse the body.
X-Hetscale-Timestamp*stringUnix time of this attempt, in seconds. Every retry is signed again with its own timestamp while the body stays the same; refuse a delivery whose timestamp is more than five minutes old.
X-Hetscale-Delivery*stringThe delivery id, equal to delivery_id in the body. A retry repeats it with the same body, so a receiver that stores the ids it has seen can process a duplicate safely.
X-Hetscale-Event*stringThe event, equal to event in the body.

* required

Payload

FieldTypeDescription
event*stringThe timeline event's name.
delivery_id*stringIdentifier of this delivery, a ULID; the same value is sent in the delivery header. A retry repeats it.
sent_at*string (date-time)When the delivery was queued; every retry repeats it.
occurred_at*string (date-time)When the event happened.
organization*DeliveryOrganizationThe organisation an integration's delivery comes from.
group*DeliveryGroupThe group a delivery is about.
node*object
actor*stringWho acted: system, policy, user, api_token and the like.
text*string | nullThe reason the timeline shows, in English, or null.
url*string (uri)The group's timeline on the panel.

* required

alert

An alert of the organisation

Sent to an integration webhook that takes alerts (Pro, the Integrations page): every alert the organisation's members are mailed, one delivery each, the moment it is raised, never batched. event is alert; alert.kind names it and alert.level is critical, warning or notice. Use it for an on-call tool, a bot or a status page.

Headers

HeaderTypeDescription
X-Hetscale-Signature*stringOne v1=<hex> value per secret that signs now, comma-separated: the HMAC-SHA256 of <timestamp>.<body> with the endpoint's signing secret, where <timestamp> is X-Hetscale-Timestamp and <body> the raw request body. After a rotation the previous secret signs alongside the new one for 24 hours. Accept the delivery when one value matches, before you parse the body.
X-Hetscale-Timestamp*stringUnix time of this attempt, in seconds. Every retry is signed again with its own timestamp while the body stays the same; refuse a delivery whose timestamp is more than five minutes old.
X-Hetscale-Delivery*stringThe delivery id, equal to delivery_id in the body. A retry repeats it with the same body, so a receiver that stores the ids it has seen can process a duplicate safely.
X-Hetscale-Event*stringThe event, equal to event in the body.

* required

Payload

FieldTypeDescription
event*"alert"
delivery_id*stringIdentifier of this delivery, a ULID; the same value is sent in the delivery header. A retry repeats it.
sent_at*string (date-time)When the delivery was queued; every retry repeats it.
raised_at*string (date-time)When the alert was raised.
alert*object
organization*DeliveryOrganizationThe organisation an integration's delivery comes from.
group*object
node*object
text*stringThe alert's line from the alert mail, in English.
url*string | null (uri)The group's timeline on the panel, or null.

* required

ping

The Integrations page's test

Sent when a member sends a test from the Integrations page. event is ping. It goes even to a suspended integration, and a success resumes it.

Headers

HeaderTypeDescription
X-Hetscale-Signature*stringOne v1=<hex> value per secret that signs now, comma-separated: the HMAC-SHA256 of <timestamp>.<body> with the endpoint's signing secret, where <timestamp> is X-Hetscale-Timestamp and <body> the raw request body. After a rotation the previous secret signs alongside the new one for 24 hours. Accept the delivery when one value matches, before you parse the body.
X-Hetscale-Timestamp*stringUnix time of this attempt, in seconds. Every retry is signed again with its own timestamp while the body stays the same; refuse a delivery whose timestamp is more than five minutes old.
X-Hetscale-Delivery*stringThe delivery id, equal to delivery_id in the body. A retry repeats it with the same body, so a receiver that stores the ids it has seen can process a duplicate safely.
X-Hetscale-Event*stringThe event, equal to event in the body.

* required

Payload

FieldTypeDescription
event*"ping"
delivery_id*stringIdentifier of this delivery, a ULID; the same value is sent in the delivery header. A retry repeats it.
sent_at*string (date-time)When the delivery was queued; every retry repeats it.
organization*DeliveryOrganizationThe organisation an integration's delivery comes from.
group*null
node*null
text*string
url*null

* required

node.created

A new node is booted and reachable

Sent to a webhook group's endpoint once per node, when its server has booted and is reachable (after a boot grace of 30 seconds), so the customer's pipeline deploys the current release to it. The node joins the load balancer once the pipeline reports it ready and takes traffic when its health check then passes; both must happen before deadline_at, or the node is destroyed and an alert is raised, and three consecutive deploy failures pause the group. group.generation is the generation the node was created for: send it back, with release.id, in the node's ready and failed reports. Deliveries are deduplicated by delivery_id, never by node id; a delivery is retried for about 38 minutes and then given up.

Headers

HeaderTypeDescription
X-Hetscale-Signature*stringOne v1=<hex> value per secret that signs now, comma-separated: the HMAC-SHA256 of <timestamp>.<body> with the endpoint's signing secret, where <timestamp> is X-Hetscale-Timestamp and <body> the raw request body. After a rotation the previous secret signs alongside the new one for 24 hours. Accept the delivery when one value matches, before you parse the body.
X-Hetscale-Timestamp*stringUnix time of this attempt, in seconds. Every retry is signed again with its own timestamp while the body stays the same; refuse a delivery whose timestamp is more than five minutes old.
X-Hetscale-Delivery*stringThe delivery id, equal to delivery_id in the body. A retry repeats it with the same body, so a receiver that stores the ids it has seen can process a duplicate safely.
X-Hetscale-Event*stringThe event, equal to event in the body.

* required

Payload

FieldTypeDescription
event*"node.created"The event name.
delivery_id*stringIdentifier 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 node's readiness deadline expires; the node is then 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 to a webhook group's endpoint once per node, 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 deduplicated by delivery_id, never by node id.

Headers

HeaderTypeDescription
X-Hetscale-Signature*stringOne v1=<hex> value per secret that signs now, comma-separated: the HMAC-SHA256 of <timestamp>.<body> with the endpoint's signing secret, where <timestamp> is X-Hetscale-Timestamp and <body> the raw request body. After a rotation the previous secret signs alongside the new one for 24 hours. Accept the delivery when one value matches, before you parse the body.
X-Hetscale-Timestamp*stringUnix time of this attempt, in seconds. Every retry is signed again with its own timestamp while the body stays the same; refuse a delivery whose timestamp is more than five minutes old.
X-Hetscale-Delivery*stringThe delivery id, equal to delivery_id in the body. A retry repeats it with the same body, so a receiver that stores the ids it has seen can process a duplicate safely.
X-Hetscale-Event*stringThe event, equal to event in the body.

* required

Payload

FieldTypeDescription
event*"node.terminating"The event name.
delivery_id*stringIdentifier 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*objectThe node that is leaving, identified by the same values as in the inventory API.
reason*string | nullWhy the node is leaving, as Hetscale recorded it: for example scale_in, rehearsal, user_destroy, heal or manual.

* 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 to a webhook group's endpoint when its current release changes: through the releases endpoint, or when a member makes an earlier release current again on the group's Deployment page. Every node created from now on names the new release in node.created; nodes already running keep the release they were deployed with until a member's rollout replaces them. The group carries its new generation.

Headers

HeaderTypeDescription
X-Hetscale-Signature*stringOne v1=<hex> value per secret that signs now, comma-separated: the HMAC-SHA256 of <timestamp>.<body> with the endpoint's signing secret, where <timestamp> is X-Hetscale-Timestamp and <body> the raw request body. After a rotation the previous secret signs alongside the new one for 24 hours. Accept the delivery when one value matches, before you parse the body.
X-Hetscale-Timestamp*stringUnix time of this attempt, in seconds. Every retry is signed again with its own timestamp while the body stays the same; refuse a delivery whose timestamp is more than five minutes old.
X-Hetscale-Delivery*stringThe delivery id, equal to delivery_id in the body. A retry repeats it with the same body, so a receiver that stores the ids it has seen can process a duplicate safely.
X-Hetscale-Event*stringThe event, equal to event in the body.

* required

Payload

FieldTypeDescription
event*"group.release_changed"The event name.
delivery_id*stringIdentifier 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"
  }
}

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

Connect read-only