# Events and webhooks

Your org's events tell your own systems what happened to your machines, as it happens. They're
kept 7 days.

| Event | When |
|---|---|
| `machine.created`, `machine.deleted` | a machine is made or deleted |
| `machine.awake`, `machine.asleep` | it wakes or goes to sleep |
| `machine.error` | it stopped with an error |
| `machine.expired` | its lifetime ended and it was deleted |
| `exec.finished` | a command finished (`ok`: whether it did; never the command or its output) |
| `snapshot.created` | a snapshot was taken |
| `limit.reached` | you reached one of your limits |

Each is `{"id", "org", "type", "machine", "at", "data"}`. Events carry names, states and outcomes,
never commands, output, notes or secrets.

## Reading them

```sh
curl -H "Authorization: Bearer $KEY" 'https://api.shell.639cloud.com/v1/events?type=machine.error'
curl -N -H "Authorization: Bearer $KEY" -H 'Accept: text/event-stream' https://api.shell.639cloud.com/v1/events
```

The list gives `next`, the id to pass as `after` for the next page. The stream sends new events as
they happen and picks up after `Last-Event-ID` when it reconnects; it re-checks your key and role as
it goes and ends after an hour (reconnect). A member's key sees the events of machines their teams
can reach; owners and admins see the whole org's. SDKs: `events()`, `stream_events()` /
`streamEvents()`.

## Webhooks

Owners and admins can add up to 5 webhooks per org: each gets every event of the types it asks for
(all, if none), as a JSON POST, in order, from the moment it's added.

```sh
curl -X POST -H "Authorization: Bearer $KEY" https://api.shell.639cloud.com/v1/webhooks \
  -d '{"url": "https://example.com/hooks/639", "types": ["machine.error", "limit.reached"]}'
```

- **Signed.** The reply's `secret` is shown once. Each delivery has
  `639-Signature: t=<unix>,v1=<hex>`, where `<hex>` is HMAC-SHA256 of `<t>.<body>` with the secret.
  Check it (and that `t` is recent) before trusting a delivery; the SDKs have `verify_webhook` /
  `verifyWebhook`.
- **Delivery.** Answer `2xx` within 10 seconds. Anything else (redirects aren't followed) is
  retried with backoff, from 10 seconds growing to 30 minutes; a webhook failing for a day is turned
  off and your owners and admins are told. Add it again to turn it back on.
- **Where.** `https://` on port 443, to a name that resolves to an internet address (checked when
  connecting; private and local addresses are refused).
