ReferenceWebhooks & events

The orchestrator emits notifications on state changes (deployment lifecycle, cloud-account connect/disconnect, org membership, approvals). Each notification is fanned out across enabled channels: in-app banner, email, and (when configured) HTTP webhook to an URL of your choice.

This page is the authoritative reference for event types, payload shape, and delivery semantics. For the in-app/email workflow, see Guides: Notifications.

Event types

Every event emitted by the orchestrator falls under one of these event_type values:

Deployment lifecycle

EventEmitted whenDefault severity
session.createdA new gated session startsinfo
session.completedSession reaches gate 7 (done)ok
session.failedSession terminated by an error before gate 7fail
deployment.createdA deployment record is persisted at gate 5 reviewinfo
deployment.approval_requestedAdmin approval needed at gate 5warn
deployment.approval_decidedApprover approved or rejectedinfo
deployment.run_startedterraform apply job dispatchedinfo
deployment.run_succeededApply completed successfullyok
deployment.run_failedApply failed (partial or full)fail

Cloud accounts

EventEmitted whenDefault severity
cloud_account.connectedA new cloud account passed probe and was savedok
cloud_account.disconnectedA cloud account was removedinfo
cloud_account.credentials_rotatedOperator rotated credentials on an existing accountinfo

Org membership

EventEmitted whenDefault severity
org.invite_sentAn admin invited a new memberinfo
org.invite_acceptedAn invitee acceptedok
org.renamedOrg display name changedinfo
org.approval_required_toggledOrg’s approval-gate policy changedwarn
org.member_role_changedA member’s role changedinfo
org.member_removedA member was removedwarn

Payload shape

Every notification has the same envelope:

{
  "id": "ntfn_abc123",
  "org_id": "org_xyz789",
  "event_type": "deployment.run_succeeded",
  "entity_type": "deployment",
  "entity_id": "dep_456",
  "actor_id": "user_def",
  "actor_email": "alice@example.com",
  "actor_name": "Alice",
  "title": "Postgres deployment succeeded",
  "body": "Cloud SQL instance staging-pg is live.",
  "deep_link": "https://app.hivedeploy.in/deployments/dep_456",
  "payload": {
    "deployment_id": "dep_456",
    "session_id": "ses_789",
    "resource_kind": "postgres",
    "cloud_provider": "gcp"
  },
  "created_at": "2026-05-13T14:23:45Z"
}

Field reference

FieldTypeNotes
idstringStable notification ID (ntfn_…)
org_idstringTenant scope; matches the customer’s org
event_typeenumOne of the event types listed above
entity_typeenumOne of: session, deployment, approval_request, run, org, org_member, org_invite, cloud_account
entity_idstringID of the affected entity
actor_idstring | nullUser who triggered the event (null for system-emitted)
actor_emailstring | nullEmail of actor (denormalized for display)
actor_namestring | nullDisplay name of actor
titlestringHuman-readable summary, suitable for a one-line banner
bodystring | nullOptional longer description
deep_linkstringURL into the in-app UI for the affected entity
payloadobjectEvent-specific structured details (varies by event_type)
created_atISO 8601UTC timestamp

The payload object’s shape varies by event type — see the per-event section below for details. All other top-level fields have the same shape across all events.

Subscribing to webhooks

Webhook delivery to an external HTTP endpoint is currently an admin-only feature. Configure via the /settings/webhooks page in the app (or POST /api/webhooks to the API). Each webhook subscription has:

  • A target URL (HTTPS only)
  • An optional filter on event_type (subscribe to all, or a subset)
  • A shared secret used for HMAC signing (see below)

In-app and email channels are always-on for org members per their notification preferences (/settings/notifications).

Delivery semantics

  • At-least-once delivery. A webhook may be retried; ensure your receiver is idempotent (use id as the dedup key).
  • Retries. On 5xx responses or network error, the orchestrator retries with exponential backoff: 1s, 5s, 30s, 2min, 10min, 1h, 6h. After 7 failed attempts the event is marked permanently failed and surfaced in the audit log.
  • 4xx response halts retries — the orchestrator treats 4xx as a permanent client misconfiguration and gives up.
  • Timeout per delivery attempt: 10 seconds.
  • Ordering is best-effort within an org but not guaranteed across orgs.

Signature verification

When a webhook fires, the orchestrator includes an HMAC-SHA256 signature in the X-Hivedeploy-Signature header. The signing input is the raw request body; the key is your subscription’s shared secret.

Verify in Python:

import hmac
import hashlib
 
def verify(body: bytes, signature_header: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature_header)

Verify in Node.js:

import crypto from 'node:crypto'
 
function verify(body, signatureHeader, secret) {
  const expected = crypto.createHmac('sha256', secret).update(body).digest('hex')
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader))
}

If the signature does not match, drop the request — it may be a replay or a spoofed payload.

Receiver best practices

  • Respond with 2xx as soon as you’ve persisted the event; do real processing async. The orchestrator’s 10s timeout will retry you if you process synchronously and exceed it.
  • Use id for idempotency. The same event can be delivered more than once.
  • Watch for unknown event_type values — new events are added over time. Treat unknowns as no-ops, don’t crash.
  • The payload shape is event-specific; tolerate missing fields gracefully if you only handle a subset of events.

Audit trail

Every webhook delivery attempt is recorded in the audit log with the request URL, response status, and retry count. See Troubleshooting: Reading audit logs.

See also

Was this page helpful?