Events
Each webhook delivery carries an event type and an event-specific data
payload inside the envelope. An endpoint
receives an event only if its subscription list includes that type — or the
wildcard *, which matches every event, including types added in future.
An explicit subscription receives only the types you list — it won't start
getting a newly added type until you update the endpoint's eventTypes
(subscribe to * to receive new ones automatically). Either way, write your
receiver to ignore event types it doesn't recognise rather than erroring, so
new events can never break it.
Catalogue
Environments
| Type | Fires when |
|---|---|
environment.created | A new environment was created (before the box boots). |
environment.started | An environment finished provisioning and is running. |
environment.stopped | An environment was stopped (the box is paused). |
environment.terminated | An environment was terminated (the box is gone). |
environment.failed | An environment failed to launch. |
Members
| Type | Fires when |
|---|---|
member.added | A user joined the organization. |
member.removed | A user was removed from the organization. |
member.role_changed | A member's role changed. |
Connections
| Type | Fires when |
|---|---|
connection.verified | An AWS connection was verified and is active. |
connection.failed | An AWS connection failed verification. |
Billing
| Type | Fires when |
|---|---|
billing.trialing | The subscription entered its trial period. |
billing.active | The subscription became active. |
billing.past_due | A payment failed and the subscription is past due. |
billing.canceled | The subscription was canceled. |
Webhook system
| Type | Fires when |
|---|---|
webhook.ping | A test event you triggered from the web app or the ping API. |
webhook.endpoint.disabled | An endpoint was auto-disabled after sustained delivery failures. Fans out to your other enabled endpoints that subscribe to it (or to *); the disabled endpoint itself gets nothing. |
Payloads
Most events describe the resource they're about with a data.resource object —
{ type, id, name } — alongside any event-specific fields. The examples below
show the full envelope.
Treat the payload as a notification, not the source of truth. Use the data to
know what changed, then call the API if you need the full,
current state of the resource.
Environment events
created, started, stopped, and terminated carry just the resource:
{
"id": "msg_01HXYZ",
"type": "environment.started",
"timestamp": "2026-05-30T14:23:00.000Z",
"data": { "resource": { "type": "environment", "id": "env_...", "name": "my-box" } }
}
environment.failed adds a reason:
{
"type": "environment.failed",
"data": {
"resource": { "type": "environment", "id": "env_...", "name": "my-box" },
"reason": "Capacity unavailable in eu-west-2"
}
}
Member events
For member events resource.id is the user id and resource.name is the user's
email (their login identity) — not their display name, which arrives separately as
member.name on member.added. The fields inside member vary by event:
{
"type": "member.added",
"data": {
"resource": { "type": "member", "id": "usr_...", "name": "ada@example.com" },
"member": { "userId": "usr_...", "email": "ada@example.com", "name": "Ada", "role": "member" }
}
}
member.added—memberincludesuserId,email,name, androle.member.role_changed—memberincludesuserId,email, and the newrole.member.removed—memberincludes justuserIdandemail.
Connection events
{
"type": "connection.verified",
"data": {
"resource": { "type": "connection", "id": "con_...", "name": "prod-account" },
"awsAccountId": "123456789012"
}
}
connection.failed replaces awsAccountId with a reason:
{
"type": "connection.failed",
"data": {
"resource": { "type": "connection", "id": "con_...", "name": "prod-account" },
"reason": "AssumeRole failed"
}
}
Billing events
Billing events don't use the resource shape — they carry the org id and the
new status (one of trialing, active, past_due, canceled):
{
"type": "billing.past_due",
"data": { "orgId": "org_...", "billingStatus": "past_due" }
}
Webhook system events
{
"type": "webhook.ping",
"data": {
"message": "This is a test webhook from Slothbox.",
"endpointId": "whe_...",
"triggeredBy": "usr_..."
}
}
{
"type": "webhook.endpoint.disabled",
"data": { "endpointId": "whe_...", "url": "https://example.com/...", "reason": "..." }
}