Skip to content

Webhooks

Webhooks let Sencai push events to an HTTP endpoint you control, instead of you polling the API. Endpoints are managed at Settings → Webhooks (/gravity/settings/webhooks); the history of what’s been sent to them is on the Webhook Delivery Log screen (/gravity/settings/webhook-deliveries), reached from the Delivery log (all) button on the Webhooks screen - it has no sidebar entry of its own.

  1. On the Webhooks screen, click Add webhook.
  2. Give it a name and the URL Sencai should send events to. The URL must be a real, publicly reachable http:// or https:// address - Sencai refuses to save a URL pointing at localhost or a private/internal address range. Use https:// unless you have a specific reason not to (see Endpoint security below).
  3. Choose which event types you want (see the table below).
  4. Leave it active (the default) or switch it off without deleting it.
  5. Save. A signing secret is generated and shown to you once, in a reveal dialog - copy it now. It’s used to verify requests actually came from Sencai (see below) and can’t be retrieved again afterward. If you lose it, delete the webhook (the trash icon on its row) and register it again - the new webhook gets a new secret, shown once on creation.

Managing webhooks requires the Owner or Admin role in the organization; other roles can view the list.

EventFires when
instance.provisionedA cloud instance finishes provisioning successfully
instance.provision_failedCloud instance provisioning fails
drift.detectedConfiguration drift is detected on a managed resource
budget.thresholdA spend cap or budget threshold is reached
member.addedA member is added to the organization
member.removedA member is removed from the organization

Every request Sencai sends to your endpoint - today, that’s the test event described below - is a JSON body shaped like:

{
"event": "webhook.test",
"data": {
"timestamp": "2026-03-01T12:00:00Z",
"webhook_id": "a1b2c3d4e5f6..."
}
}

Two headers let you verify it’s genuinely from Sencai and wasn’t tampered with in transit:

  • X-Sencai-Event - the event name, matching the event field in the body.
  • X-Sencai-Signature - sha256=<hex-encoded HMAC-SHA256 of the raw request body, keyed with your webhook's signing secret>.

Recompute the same HMAC over the raw bytes you received (not a re-serialized version of the parsed JSON - whitespace differences will break the comparison) and check it matches before trusting the payload. There’s no timestamp embedded in the signature today, so build your own idempotency handling if you need protection against a captured request being replayed.

Click Test on a webhook’s row to have Sencai make an HTTP POST to your URL with the payload shown above, signed with that webhook’s secret. The response - success or failure, with the status code and any error - is recorded as a delivery you can inspect on the Webhook Delivery Log screen. This is the practical way to confirm your endpoint is reachable and your signature verification is correct.

Webhook Delivery Log lists every delivery attempt for the organization: endpoint, event type, status (delivered, failed, pending, or replayed), HTTP response code, attempt count, and the time of the last attempt. You can filter the list by status.

Replay is available on deliveries whose status is failed. It marks the delivery as replayed and updates its attempt count for your own tracking - since automatic dispatch isn’t fully wired up yet (see above), Test on the Webhooks screen is currently the reliable way to generate a fresh delivery to verify your endpoint end to end.

  • Always verify the signature before trusting a payload’s contents.
  • Prefer https:// for your endpoint - http:// is accepted, but the payload and signature both travel unencrypted over a plain HTTP connection.
  • Treat the signing secret like a password. There’s no way to reveal or change the secret of an existing webhook, so if you suspect it’s been exposed, delete that webhook and register a new one, then update your endpoint to verify against the new secret.
  • Keep your endpoint idempotent where practical, since there’s no timestamp or delivery ID binding built into the signature yet.