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.