# Crusoe Cloud Webhooks

Crusoe Cloud's Notifications service routes alerts (resource health and automated
remediation from Command Center, budget alerts, organization changes, Managed AI
events) to email, the console, Slack and generic webhook endpoints. Webhook
endpoints are managed in a Svix dashboard opened from the Crusoe Cloud Console.

## When to Use This Skill

* How do I receive Crusoe Cloud webhooks?
* How do I verify Crusoe webhook signatures?
* How do I handle Crusoe `resource.automated_remediation` (node replacement) notifications?
* How do I route Crusoe budget alerts or resource health alerts to my own service?
* Why is my Crusoe webhook signature verification failing?

## Verification (core)

> **Inferred from Svix, not quoted from Crusoe.** Crusoe's docs say webhooks are
> configured "on the Svix dashboard" but publish no verification details. The
> headers, algorithm and `whsec_` secret format below are Svix defaults.

Each webhook carries `svix-id`, `svix-timestamp` (Unix seconds) and `svix-signature`
(space-separated `v1,<base64>` entries). The signature is base64 HMAC-SHA256 over
`${svix-id}.${svix-timestamp}.${raw body}`, keyed with the base64-decoded secret after
`whsec_`. Use the official `svix` SDK (Node and Python), which also enforces a
5-minute timestamp window and handles secret rotation:

```javascript
import { Webhook } from 'svix'; // svix 2.8+ is ESM-only

const wh = new Webhook(process.env.CRUSOE_WEBHOOK_SECRET); // "whsec_..."
wh.verify(rawBody, {                                       // raw Buffer/string, NOT parsed JSON
  'svix-id': req.headers['svix-id'],
  'svix-timestamp': req.headers['svix-timestamp'],
  'svix-signature': req.headers['svix-signature'],
}); // throws WebhookVerificationError; returns undefined in svix 2.x
const payload = JSON.parse(rawBody.toString('utf8'));     // parse only after verifying

```

Python: `from svix.webhooks import Webhook` and call `Webhook(secret).verify(raw_body, headers)` the same way.

> **For complete handlers with tests**, see [examples/express/](https://github.com/hookdeck/webhook-skills/tree/main/skills/crusoe-webhooks/examples/express/), [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/crusoe-webhooks/examples/nextjs/), [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/crusoe-webhooks/examples/fastapi/).

## Common Event Types

Crusoe documents one exact event type string; the rest are console categories you
subscribe to per endpoint in the Svix dashboard.

| Event / category | Description |
| --- | --- |
| `resource.automated_remediation` | Automated remediation of a node (e.g. Node Replacement after `XID 79: GPU has fallen off the bus`) |
| Resource Health | Hardware issues and automated remediation on your nodes |
| User Account and Organization Management | Changes to organization account settings and access controls |
| Billing | Budget alerts when a budget threshold is exceeded |
| Managed AI | Managed AI updates; self-serve deployment created / scaled / deleted |

**Parse defensively.** Crusoe says the body "varies by event type", and the documented
`resource.automated_remediation` example has no `type` field. The examples read
`type` / `event_type` when present, otherwise recognise remediation payloads by
`workflow_type` + `resource_id`, and log anything else without failing.

## Environment Variables

```bash
CRUSOE_WEBHOOK_SECRET=whsec_xxxxx   # endpoint signing secret from the Svix dashboard

```

## Local Development

```bash
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 crusoe --path /webhooks/crusoe

```

Add the tunnel URL as a **Webhook** endpoint (Console → bell icon → All Notifications
→ Manage Slack/Webhook → Add Endpoint).

## Reference Materials

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/crusoe-webhooks/references/overview.md) - Notification categories, events and payload structure
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/crusoe-webhooks/references/setup.md) - Add a webhook endpoint and get the signing secret
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/crusoe-webhooks/references/verification.md) - Svix signature verification details and gotchas