NodeOps
FR

Webhooks

Register HTTPS endpoints that receive a signed POST whenever something happens to your sandboxes, disks, networks, or templates. Instead of polling GET /v1/sandboxes/{id}, let CreateOS push lifecycle events to your service in real time.

Get your API key from https://createos.nodeops.network/profile. Pass it as X-Api-Key: <token> on every request below.

Base URL: https://api.sb.createos.sh


At a glance

  • Base URL: https://api.sb.createos.sh
  • Auth: X-Api-Key: <token> header. Get a token
  • Response envelope: JSend, {"status": "...", "data": ...}
  • Delivery: POST to your URL, HMAC-SHA256 signed, retried with backoff.

An endpoint subscribes to a set of event actions (or all of them). When a matching action occurs, every active endpoint whose filter includes that action receives a delivery. Endpoints are scoped to the authenticated user.


Event actions

An endpoint's events filter is a list of action strings. Subscribe to all current actions available for filtering:

GET /v1/webhook-endpoints/actions

Auth required: Yes

Bash
1curl -s https://api.sb.createos.sh/v1/webhook-endpoints/actions \
2 -H "X-Api-Key: $TOKEN"
JSON
1{
2 "status": "success",
3 "data": [
4 "sandbox.create", "sandbox.destroy", "sandbox.pause", "sandbox.resume",
5 "sandbox.fork", "sandbox.patch", "sandbox.resize", "sandbox.egress.set",
6 "sandbox.ssh_pubkey.update", "sandbox.bandwidth.update",
7 "disk.create", "disk.delete", "disk.attach", "disk.detach",
8 "network.create", "network.delete", "network.attach", "network.detach",
9 "template.submit", "template.delete", "template.build.start", "template.build.complete"
10 ]
11}
CategoryActions
Sandboxsandbox.create, sandbox.destroy, sandbox.pause, sandbox.resume, sandbox.fork, sandbox.patch, sandbox.resize, sandbox.egress.set, sandbox.ssh_pubkey.update, sandbox.bandwidth.update
Diskdisk.create, disk.delete, disk.attach, disk.detach
Networknetwork.create, network.delete, network.attach, network.detach
Templatetemplate.submit, template.delete, template.build.start, template.build.complete

Always fetch this list at runtime rather than hard-coding it — new actions are added over time.


Create an endpoint

POST /v1/webhook-endpoints

Auth required: Yes

FieldTypeRequiredDescription
urlstringYesYour HTTPS receiver. Must be http(s)://….
eventsstring[]NoActions to subscribe to. Omit or pass [] to receive every action.
Bash
1# Subscribe to everything
2curl -s -X POST https://api.sb.createos.sh/v1/webhook-endpoints \
3 -H "X-Api-Key: $TOKEN" \
4 -H "Content-Type: application/json" \
5 -d '{"url": "https://example.com/webhook"}'
6
7# Subscribe to specific actions only
8curl -s -X POST https://api.sb.createos.sh/v1/webhook-endpoints \
9 -H "X-Api-Key: $TOKEN" \
10 -H "Content-Type: application/json" \
11 -d '{"url": "https://example.com/webhook", "events": ["sandbox.create", "sandbox.destroy"]}'
JSON
1{
2 "status": "success",
3 "data": {
4 "id": "eb081e4d-...",
5 "url": "https://example.com/webhook",
6 "secret": "whsec_a6ed6066...",
7 "events": [],
8 "active": true
9 }
10}

Save the secret. It is returned only once, at creation, and is required to verify delivery signatures. If you lose it, delete the endpoint and create a new one.


List endpoints

GET /v1/webhook-endpoints

Auth required: Yes

Bash
1curl -s https://api.sb.createos.sh/v1/webhook-endpoints \
2 -H "X-Api-Key: $TOKEN"
JSON
1{
2 "status": "success",
3 "data": [
4 {
5 "id": "eb081e4d-...",
6 "url": "https://example.com/webhook",
7 "events": [],
8 "active": true,
9 "failureCount": 0,
10 "createdAt": "2026-06-25T10:26:39Z"
11 }
12 ]
13}

The secret is never returned by list or get — only at creation.


Get an endpoint (with recent deliveries)

GET /v1/webhook-endpoints/{id}

Auth required: Yes

Bash
1curl -s https://api.sb.createos.sh/v1/webhook-endpoints/$ENDPOINT_ID \
2 -H "X-Api-Key: $TOKEN"
JSON
1{
2 "status": "success",
3 "data": {
4 "endpoint": {
5 "id": "eb081e4d-...",
6 "url": "https://example.com/webhook",
7 "active": true,
8 "failureCount": 0
9 },
10 "deliveries": [
11 {
12 "id": "2423f39d-...",
13 "eventAction": "sandbox.create",
14 "status": "delivered",
15 "attempts": 1,
16 "deliveredAt": "2026-06-25T10:32:48Z"
17 }
18 ]
19 }
20}

Delivery status is one of pending, delivered, or failed. Delivery records are short-lived — see Retention.


Suspend / resume an endpoint

Suspending stops deliveries without deleting the endpoint. Resuming reactivates it and resets its failure count.

POST /v1/webhook-endpoints/{id}/suspend

POST /v1/webhook-endpoints/{id}/resume

Auth required: Yes

Bash
1curl -s -X POST https://api.sb.createos.sh/v1/webhook-endpoints/$ENDPOINT_ID/suspend \
2 -H "X-Api-Key: $TOKEN"
3
4curl -s -X POST https://api.sb.createos.sh/v1/webhook-endpoints/$ENDPOINT_ID/resume \
5 -H "X-Api-Key: $TOKEN"

An endpoint that accumulates too many delivery failures is auto-suspended (active: false) — see Retry policy. Call resume once your receiver is healthy again.


Delete an endpoint

DELETE /v1/webhook-endpoints/{id}

Auth required: Yes

Deletes the endpoint and all of its pending deliveries.

Bash
1curl -s -X DELETE https://api.sb.createos.sh/v1/webhook-endpoints/$ENDPOINT_ID \
2 -H "X-Api-Key: $TOKEN"

Delivery

When a subscribed action occurs, a POST is sent to each matching active endpoint:

POST https://example.com/webhook
Content-Type: application/json
User-Agent: CreateOS-Webhook/1.0
X-Webhook-Timestamp: 1750780801
X-Webhook-Signature: sha256=def789...
JSON
1{
2 "event": "sandbox.create",
3 "occurredAt": "2026-06-25T04:57:22Z",
4 "data": {
5 "shape": "s-1vcpu-1gb",
6 "disk_mib": 10240,
7 "region": "eu"
8 }
9}
  • event — the action string (matches one of the event actions).
  • occurredAt — RFC 3339 timestamp of when the event happened.
  • data — action-specific metadata. Shape varies by action; treat unknown fields as additive.

Respond with any 2xx status to acknowledge. Any non-2xx (or a timeout) is treated as a failed delivery and retried.

Verifying signatures

Every delivery is signed. Compute HMAC-SHA256 over <X-Webhook-Timestamp>.<raw-body> using your endpoint secret, prefix with sha256=, and compare against X-Webhook-Signature in constant time. Verify against the raw request body — do not re-serialize the parsed JSON.

Python
1import hmac, hashlib
2
3def verify(secret: str, headers, raw_body: bytes) -> bool:
4 ts = headers["X-Webhook-Timestamp"]
5 expected = "sha256=" + hmac.new(
6 secret.encode(), f"{ts}.".encode() + raw_body, hashlib.sha256
7 ).hexdigest()
8 return hmac.compare_digest(expected, headers["X-Webhook-Signature"])
JavaScript
1import crypto from "node:crypto";
2
3function verify(secret, headers, rawBody) {
4 const ts = headers["x-webhook-timestamp"];
5 const mac = crypto.createHmac("sha256", secret);
6 mac.update(`${ts}.`);
7 mac.update(rawBody); // Buffer of the raw request body
8 const expected = "sha256=" + mac.digest("hex");
9 return crypto.timingSafeEqual(
10 Buffer.from(expected),
11 Buffer.from(headers["x-webhook-signature"]),
12 );
13}
Go
1mac := hmac.New(sha256.New, []byte(secret))
2fmt.Fprintf(mac, "%s.", timestamp)
3mac.Write(body)
4expected := "sha256=" + hex.EncodeToString(mac.Sum(nil))
5// hmac.Equal([]byte(expected), []byte(signatureHeader))

The timestamp is part of the signed material — reject deliveries whose X-Webhook-Timestamp is outside your tolerated skew (e.g. more than a few minutes old) to defend against replay.

Retry policy

A failed delivery is retried up to 5 times with increasing delays:

AttemptDelay
1st retry5 seconds
2nd retry30 seconds
3rd retry2 minutes
4th retry10 minutes
5th retry1 hour

After 5 failed attempts the delivery is marked permanently failed and the endpoint's failureCount is incremented. Once an endpoint reaches 50 cumulative failures it is auto-suspended (active: false); resume it after fixing your receiver. Make your handler idempotent — a delivery may arrive more than once (retry after a slow 2xx).

Retention

Delivery records are ephemeral — they exist for observability, not durable storage:

  • Delivered and failed deliveries are removed after 30 minutes.
  • All deliveries are removed after 72 hours regardless of status.
  • Deleting an endpoint immediately removes all of its deliveries.

Persist anything you need to keep in your own system when the delivery arrives.


Plan limits

The number of webhook endpoints you can register depends on your plan:

PlanMax endpoints
Free2
Beginner4
Pro6
EnterpriseUnlimited

Creating an endpoint beyond your plan limit returns an error; delete an unused endpoint or upgrade your plan.

Plus de 100 000 créateurs. Un seul espace de travail.

Recevez les mises à jour produit, les témoignages de créateurs et un accès anticipé aux fonctionnalités qui vous aident à livrer plus vite.

NodeOps is the agentic operating system for production AI. CreateOS is its flagship product.