Skip to content

Event catalog

CAVS publishes internal events to a single Pub/Sub topic. A subset is mapped to public webhook events; only those ever leave the platform.

The complete list you can subscribe to. See Webhooks.

Public event Internal event Fires when
repository.created repository.created A repository is created
repository.deleted repository.deleted A repository is deleted
repository.push upload.session.finalized An upload session is finalized
repository.push.indexed repository.index.finalized A Git-index upload is finalized
release.published repository.release.published A release appears from a tag
storage.snapshot.created snapshot.created A snapshot capture completes
storage.quota.warning repository.quota.warning Storage crosses the warning threshold
storage.quota.exceeded repository.quota.exceeded Storage exceeds the plan limit
maintenance.gc.completed gc.completed A garbage-collection pass completes
{
"type": "repository.push",
"organization_id": "0a11bb22-…",
"repository_id": "0f8c3d4e-…",
"occurred_at": "2026-07-28T12:00:04.512Z",
"data": { "session_id": "3b1f…", "generation": 42 }
}

Treat data as open — new keys can appear. Use it as a pointer and read authoritative state from the API.

The full set. These drive workers, notifications and the activity feed; unmapped ones never reach a webhook.

Event Trigger
user.created First sign-in
organization.created An organization is created
organization.member.invited An invitation is sent → drives the email
organization.member.joined An invitation is accepted
Event Trigger Public
repository.created Repository created
repository.deleted Repository deleted
repository.usage.changed A push finalized → triggers reconciliation
repository.index.finalized Git-index session finalized
repository.release.published A tag became a release
repository.quota.warning Approaching the storage limit
repository.quota.exceeded Over the storage limit
Event Trigger Public
upload.session.created Session opened
upload.session.finalized Session finalized ✓ as repository.push
upload.session.failed Session failed
Event Trigger
token.created An API token is created
token.revoked An API token is revoked
Event Trigger Public
snapshot.requested Snapshot queued
snapshot.created Snapshot captured
gc.requested GC requested
gc.completed GC pass finished
repack.requested Repack requested
repack.completed Repack finished
index.compaction.requested Index compaction requested
index.compaction.completed Index compaction finished
Event Trigger
storage.connection.added A connection is created
storage.connection.tested The connectivity suite ran
storage.connection.failed A connection turned unhealthy
storage.connection.restored A connection recovered
storage.connection.removed A connection was deleted
Event Trigger
billing.subscription.updated Plan or subscription state changed
billing.payment.failed A payment failed
Event Trigger
notification.send Deliver an in-app notification and/or email
audit.event.created An audit entry was written
Property Internal (Pub/Sub) Outbound (webhooks)
Guarantee at-least-once at-least-once, 3 attempts
Ordering per repository, via the ordering key not guaranteed
Deduplication processed_events by event id yours, on X-CAVS-Delivery
Failure nack and redeliver logged as a delivery record; circuit breaker at 10 consecutive failures
{
"event_id": "…",
"event_type": "upload.session.finalized",
"organization_id": "…",
"repository_id": "…",
"occurred_at": "2026-07-28T12:00:04Z",
"payload": { }
}

event_type is a Pub/Sub message attribute, so consumers can filter without deserializing. repository_id is the ordering key.

If you self-host and want an internal event exposed to webhooks, add it to the publicEventName map in the worker. Only mapped events are forwarded — the mapping is the allowlist, which is what keeps internal detail from leaking.