Skip to main content
Version: 2.0

Webhooks

KubeOpera uses webhooks in both directions:

  • Outbound — KubeOpera notifies your endpoint when something happens: an incident opens, a deploy finishes, an automated action runs.
  • Inbound — your Git host notifies KubeOpera when code is pushed, to record CI runs and trigger builds.

Outbound webhooks​

Subscribe​

In the dashboard, open Settings → Webhooks → New webhook:

  1. Enter your endpoint's HTTPS URL.
  2. Choose the events you want (or all events).
  3. Optionally limit it to specific clusters or CloudSpaces.
  4. Save. KubeOpera shows the webhook's signing secret once — store it safely.

Or with the API:

curl -X POST https://kubeopera.example.com/api/kubeopera/api/v1/webhooks \
-H "Authorization: Bearer $KUBEOPERA_TOKEN" -H "Content-Type: application/json" -d '{
"url": "https://hooks.example.com/kubeopera",
"events": ["incident.created", "incident.resolved", "app.deployed", "action.executed"]
}'

Tenant users receive events for their own tenant only.

Events​

EventSent when
incident.created / incident.updated / incident.resolvedAn incident opens, changes, or is resolved.
app.deployed / app.deploy_failedAn app deployment becomes reachable, or fails.
app.deletedAn app is deleted.
pipeline.run_completedA CI pipeline run finishes (success or failure).
build.completedAn image build finishes.
action.pendingAn action is waiting for approval.
action.executedAn automated or approved action ran, with its outcome.
anomaly.detectedA high or critical anomaly is detected.
scaling_decision.createdA new scaling decision is proposed.
agent_run.completedAn agent run finishes, with its findings.
cluster.phase_changedA cluster moves to a new setup phase, becomes Ready, or fails.
cloudspace.readyA CloudSpace finishes provisioning.

Payload​

Every delivery is a JSON POST with a common envelope:

{
"id": "evt_01J9ZK4Q2M…",
"type": "incident.created",
"occurred_at": "2026-09-26T14:02:31Z",
"tenant_id": "b1f0…",
"data": {
"incident_id": "inc-8f2a1c",
"cluster_id": "prod-us-east",
"title": "Elevated error rate on payments-api",
"severity": "critical",
"status": "open",
"category": "performance",
"namespace": "payments",
"affected_service": "payments-api",
"url": "https://kubeopera.example.com/incidents/inc-8f2a1c"
}
}

Verify the signature​

Every delivery includes:

KubeOpera-Signature: t=1790000000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd

v1 is the HMAC-SHA256 of <t>.<raw request body> using your signing secret. Verify it, and reject deliveries whose timestamp t is more than five minutes old:

import hmac, hashlib, time

def verify(secret: bytes, header: str, body: bytes) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
t, sig = parts["t"], parts["v1"]
if abs(time.time() - int(t)) > 300:
return False
expected = hmac.new(secret, f"{t}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, sig)

Delivery and retries​

  • Respond with any 2xx within 10 seconds to acknowledge a delivery.
  • Failed deliveries are retried with exponential backoff for up to 24 hours.
  • Each event has a unique id; deliveries can occasionally repeat, so make your handler idempotent.
  • See recent deliveries, responses and retries — and redeliver an event — under Settings → Webhooks.

Inbound webhooks​

Connect your repositories so KubeOpera knows when code changes:

ForWhere you get the URLWhat it does
CI pipelinesCreating a pipeline in PipelinesEach push creates a run you can follow stage by stage.
Automatic buildsCreating a build configuration (see build-service)Each push to the configured branch builds a new image and, optionally, redeploys.

Add the URL and its secret to your repository's webhook settings (trigger: push). KubeOpera accepts the provider's standard payload and verifies each request with the provider's own scheme — X-Hub-Signature-256 for GitHub and X-Gitlab-Token for GitLab — so there's nothing KubeOpera-specific to implement.

Next steps​