Skip to content

Webhooks and events

Frazer sends an event for every change that matters: a server joined, a rollout succeeded, a backup failed, an agent waits for an approval, an invoice was paid. A webhook endpoint receives these events as CloudEvents-shaped JSON, signed with Standard Webhooks and delivered at least once, with retries for about 3 days. Events carry identifiers and states, never secret values.

Product page: Webhooks and events.

  • Event type: ai.frazer.<service>.<resource>.v1.<pastVerb>: the service (such as releases, kubernetes or monitoring), the resource in it, the version and what happened. For example, ai.frazer.releases.rollout.v1.succeeded. Each type has a JSON Schema in the event catalog.
  • Endpoint: a URL in a project (projects/{project}/webhookEndpoints/{endpoint}) with the event types it receives, a format, its signing secrets and a status: enabled, failing or disabled.
  • Event sink: delivery for a whole organization, aggregated over its projects (organizations/{organization}/eventSinks/{sink}).
  • Delivery: every attempt to send one event to one endpoint, kept in the delivery log with the request, the response and the latency.

Each event has the CloudEvents 1.0 attributes id, source, type, specversion, time and subject, plus data. By default data is a snapshot of the resource at the time of the event. An endpoint can ask for thin events instead, which carry only identifiers; you fetch the rest with the API.

event.json
{
"specversion": "1.0",
"type": "ai.frazer.releases.rollout.v1.succeeded",
"source": "projects/acme-production",
"subject": "environments/production/apps/checkout-api",
"id": "evt_01J9W3…",
"time": "2026-10-02T10:52:11Z",
"data": { "revision": "checkout-api-00042", "image": "sha256:4e1c…", "by": "users/noah" }
}
Delivery
POST https://hooks.acme.example/frazer
webhook-id: msg_2mQ8…
webhook-timestamp: 1759402331
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDDsrqsHU=

Slack, Teams and email notifications are rendered from the same events, so a channel and a webhook never disagree about what happened.

  1. Create the endpoint and choose its events. A pattern such as ai.frazer.releases.rollout.v1.* matches every rollout event. Match on IDs (organizationId, projectId), never on display names.

    Terminal window
    frazer integrations webhook-endpoints create --url https://hooks.acme.example/frazer \
    --events 'ai.frazer.releases.rollout.v1.*' --project acme-production
  2. Store the endpoint’s signing secret in your receiver. It starts with whsec_.

  3. Send a test event. In the console, choose Send test event on the endpoint, or run:

    Terminal window
    frazer integrations webhook-endpoints trigger ai.frazer.releases.rollout.v1.succeeded
  4. Check the delivery log. It keeps 30 days of attempts, with the request, the first 4 KB of each response and the latency.

    Terminal window
    frazer integrations webhook-endpoints deliveries acme-deploy-bot --status failed --since 24h

Every request carries three headers. webhook-signature holds one or more space-separated signatures of the form v1,<base64>: an HMAC-SHA256 of {webhook-id}.{webhook-timestamp}.{body}, keyed with your secret (the base64 part after whsec_).

verify.mjs
import { createHmac, timingSafeEqual } from "node:crypto";
const TOLERANCE_SECONDS = 5 * 60; // your replay window
export function verify(secret, headers, rawBody) {
const id = headers["webhook-id"];
const ts = headers["webhook-timestamp"];
if (Math.abs(Date.now() / 1000 - Number(ts)) > TOLERANCE_SECONDS) return false;
const key = Buffer.from(secret.replace(/^whsec_/, ""), "base64");
const expected = createHmac("sha256", key).update(`${id}.${ts}.${rawBody}`).digest();
return headers["webhook-signature"].split(" ").some((entry) => {
const [version, signature] = entry.split(",");
if (version !== "v1") return false;
const given = Buffer.from(signature, "base64");
return given.length === expected.length && timingSafeEqual(given, expected);
});
}
  • Sign the raw body exactly as received. A body parsed and serialized again does not match.
  • Compare in constant time, and reject old timestamps so a captured request cannot be replayed.
  • Any Standard Webhooks library verifies these requests, and the Frazer SDKs include typed verification helpers.
  • Receivers that prefer public keys can verify Ed25519 signatures, marked v1a.

Answer with a 2xx status within 15 seconds; do slow work after you answer. A 3xx counts as a failure. Frazer makes up to 10 attempts, about 3 days in all, and stops at the first success:

Attempt After the previous attempt failed
1 Immediately, when the event happens
2 5 seconds
3 5 minutes
4 30 minutes
5 2 hours
6 5 hours
7 10 hours
8 10 hours
9 24 hours
10 24 hours
  • Delivery is at least once and unordered. Deduplicate on webhook-id: a redelivery keeps the same webhook-id.
  • When order matters, compare each event’s time, or fetch the resource’s current state with the API.
  • To stop the retries for one message, answer with the header webhook-delivery: abort-message.
  • After 3 failed attempts, the endpoint’s owner gets an email. After 5 days of failures, the endpoint is disabled, an email goes out, and your other endpoints receive frazer.webhook.endpoint_disabled.v1.

Forward live events to a port on your machine, then send yourself a test event:

Terminal window
frazer integrations webhook-endpoints listen --forward-to localhost:8080
frazer integrations webhook-endpoints trigger ai.frazer.releases.rollout.v1.succeeded

Redeliver one delivery from the log with Redeliver, or every failure since a time:

Terminal window
frazer integrations webhook-endpoints redeliver acme-deploy-bot --failed-since 2026-10-02T08:00Z

When you rotate an endpoint’s signing secret, the new secret signs alongside the old one for 24 hours, then the old one stops. During those 24 hours each request carries two v1 signatures: deploy the new secret to your receiver, and the code above accepts either.

Frazer sends from fixed egress addresses, IPv4 and IPv6, published with their reverse DNS names in frazer.ai/egress-ips.json. Webhooks prefer IPv4. An endpoint can choose IPv6 or either family instead (source_family: PREFER_IPV4, IPV6 or ANY).

Endpoint URLs are resolved through Frazer’s egress proxy. A URL that resolves to a private, link-local or metadata address is refused, and DNS is checked again when Frazer connects.

  • Endpoints belong to a project; an event sink delivers an organization’s events from all its projects.
  • Creating, changing, disabling, enabling and deleting endpoints, rotating their secrets and redelivering are audit events: webhooks.endpoint.create, update, delete, disable, enable, secret_rotate and webhooks.delivery.redeliver.
  • Events never carry secret values or log bodies. Untrusted text, such as commit messages and issue titles, is shortened and marked as untrusted.
  • An agent that has read untrusted content cannot call a webhook without approval.
Limit Default
Time to answer 15 seconds, with a 2xx status
Retries 10 attempts over about 3 days
Email to the endpoint’s owner After 3 failed attempts
Endpoint disabled After 5 days of failures
Delivery log 30 days; the first 4 KB of each response
Old and new secret both sign 24 hours

Webhooks are included in every organization.

Webhooks and eventsOn your serversOn the Frazer fleet
PriceIncludedIncluded

Every line, with the estimator: pricing.

  • The signature does not match. Verify the raw body, not a parsed copy; decode the part of the secret after whsec_ from base64; check your clock. During a rotation, accept either signature.
  • An endpoint shows failing. Your receiver answered with an error or a redirect, or took longer than 15 seconds. Fix it, then redeliver the failures from the log.
  • An endpoint is disabled. It failed for 5 days. Fix the receiver, enable the endpoint again and redeliver everything that failed since the first failure.
  • The same event arrived twice. Delivery is at least once. Deduplicate on webhook-id.
  • Events arrive out of order. Delivery is unordered. Compare time, or fetch the current state with the API.
  • The endpoint URL is refused. It resolves to a private, link-local or metadata address. Use a public address.
  • Requests never reach a receiver behind an allowlist. Allow the addresses in frazer.ai/egress-ips.json; webhooks use IPv4 unless the endpoint says otherwise.
  • Events carry only IDs. The endpoint uses the thin format. Switch it to snapshot, or fetch each resource with the API.

Every event type Frazer sends, by product, exactly as it arrives in the type attribute. An endpoint subscribes to exact types or to a pattern such as ai.frazer.releases.rollout.v1.*.

Servers and pools

Event typeWhen it is sent
frazer.server.joined.v1A server presented a valid join token and appears as pending.
frazer.server.accepted.v1A person or a pool rule accepted a pending server.
frazer.server.unhealthy.v1A server reported a failing health condition.
frazer.server.burnin.completed.v1A server finished its burn-in tests.
frazer.server.removed.v1A server was removed from Frazer.

Kubernetes

Event typeWhen it is sent
frazer.cluster.created.v1A cluster was created.
frazer.cluster.ready.v1A cluster reached Ready.
frazer.cluster.upgrade.started.v1An upgrade of a cluster started.
frazer.cluster.upgrade.completed.v1An upgrade of a cluster completed.
frazer.cluster.degraded.v1A cluster's health degraded.

Serverless

Event typeWhen it is sent
frazer.service.deployed.v1A deploy of a service finished.
frazer.service.revision.ready.v1A new revision is ready and can receive traffic.
frazer.service.revision.failed.v1A revision failed to become ready. It receives no traffic.
frazer.stack.created.v1A stack and its resources were created.

Devboxes

Event typeWhen it is sent
frazer.devbox.created.v1A devbox was created.
frazer.devbox.stopped.v1A devbox stopped (idle, schedule, a person, or a spend cap).
frazer.devbox.change.reported.v1The box agent filed a change report for something a person added, removed or changed on a box.

Registry

Event typeWhen it is sent
frazer.image.pushed.v1A version was pushed to a repository.
frazer.image.scan.completed.v1A version's vulnerability scan finished.

Environments and GitOps

Event typeWhen it is sent
frazer.environment.synced.v1An environment finished a sync.
frazer.environment.sync_failed.v1An environment's sync failed.
ai.frazer.releases.rollout.v1.startedA rollout started in an environment.
ai.frazer.releases.rollout.v1.succeededA rollout finished successfully.
ai.frazer.releases.rollout.v1.failedA rollout failed.
ai.frazer.releases.rollout.v1.rolledbackA rollout was rolled back.

AI and GPUs

Event typeWhen it is sent
frazer.endpoint.ready.v1A model endpoint finished deploying and is ready to serve.
frazer.endpoint.failed.v1A model endpoint failed to deploy or to stay healthy.
frazer.finetune.completed.v1A fine-tuning job finished.
frazer.job.completed.v1An AI job ran to completion.

LLM gateway

Event typeWhen it is sent
frazer.llm.budget.threshold.v1A gateway budget crossed one of its alert thresholds (50, 80 or 100 %).

Knowledge

Event typeWhen it is sent
frazer.knowledge.sync.failed.v1A source of a knowledge base failed to sync.

Frazer Agents

Event typeWhen it is sent
frazer.session.started.v1An agent or devbox session started.
frazer.session.waiting_approval.v1A session stopped at an action that waits for a person.
frazer.session.completed.v1A session finished.

Frazer Skills

Event typeWhen it is sent
skills.version.allowedA skill version was allowed; created, held, blocked and yanked are sent too.
skills.import.decidedAn import was allowed or refused.
skills.suggestion.openedA suggestion to change a skill was opened as a pull request.
skills.gap.openedA gap was found where agents struggled with no helpful skill.
skills.lock.refreshedA running session moved to a newer skill lock.

Harnesses

Event typeWhen it is sent
agents.harness.simulation_completedA simulation finished, with its results.
agents.harness.assignment_changedA use moved to another harness profile.
agents.harness.process_audit_failedA harness version failed the process audit and left the uses that need it.
agents.harness.postmortem_publishedA postmortem of a Frazer harness regression was published.

Squads and campaigns

Event typeWhen it is sent
campaigns.startedA campaign started, with who started it for whom.
campaigns.trippedA campaign's kill switch tripped, with the cause.
campaigns.not_run_no_fundsTasks did not start because the budget or the balance could not cover them.
campaigns.successor_openedA restarted session's successor opened from its checkpoint.

Frazer Reviewer

Event typeWhen it is sent
frazer.review.completed.v1A review finished and was posted to the pull request.

Lanes, verdicts and outcomes

Event typeWhen it is sent
evt.reviewer.verdict.issuedA verdict was issued for a pull request version.
evt.reviewer.outcome.linkedAn incident, revert or hotfix was linked to the review of the change behind it.
evt.reviewer.miss.analyzedA miss analysis finished, with its remedies.
evt.reviewer.lane.revisedA lane revision entered shadow or was sealed.

Databases

Event typeWhen it is sent
frazer.database.created.v1A database instance was created.
frazer.database.failover.v1A standby took over from the primary.
frazer.database.backup.completed.v1A backup finished.
frazer.database.backup.failed.v1A backup failed.
frazer.database.restore.completed.v1A restore into a new instance finished.

In-memory store

Event typeWhen it is sent
frazer.keyvalue.failover.v1A replica took over from the primary.

Secrets

Event typeWhen it is sent
frazer.secret.rotate_due.v1A secret with the notify rotator is due for rotation.

Frazer Monitoring

Event typeWhen it is sent
frazer.alert.firing.v1An alert policy started firing.
frazer.alert.resolved.v1A firing alert policy stopped firing.
frazer.incident.opened.v1An alert with a new fingerprint opened an incident.
frazer.incident.acknowledged.v1A person acknowledged an incident.
frazer.incident.resolved.v1An incident was resolved.
frazer.uptime.check.failed.v1An uptime check went down under its failure rule.
frazer.uptime.check.recovered.v1A failed uptime check is up again.

Security Center

Event typeWhen it is sent
frazer.finding.opened.v1A new finding was opened, or a muted one reopened.
frazer.finding.resolved.v1A finding was verified as fixed.
frazer.threat.detected.v1A runtime, account, agent or network detection was raised.

Identity and access

Event typeWhen it is sent
frazer.member.added.v1A person joined the organization or a project.
frazer.member.removed.v1A person was removed from the organization or a project.

Billing and budgets

Event typeWhen it is sent
frazer.budget.threshold.v1A budget crossed one of its thresholds, on actual or forecast cost.
frazer.budget.cap_reached.v1A budget with a cap reached 100 % and Frazer paused work in its scope.
frazer.invoice.created.v1An invoice was issued.
frazer.invoice.paid.v1An invoice was paid.
frazer.invoice.payment_failed.v1A payment for an invoice failed.

Integrations

Event typeWhen it is sent
frazer.connection.health_changed.v1A connection moved to another health state.
frazer.connection.expiring.v1A connection's token, key or certificate expires within 30 days, or its import window ends within 7.

Webhooks and events

Event typeWhen it is sent
frazer.webhook.endpoint_disabled.v1An endpoint was disabled after 5 days of failed deliveries.
frazer.approval.requested.v1A change is waiting for an approval.
frazer.approval.decided.v1An approval was decided.
frazer.plan.applied.v1An approved plan was applied.
frazer.audit.event.v1An audit record was written; for a SIEM.

CLI

CommandWhat it does
frazer integrations webhook-endpoints createCreate a webhook endpoint in a project, with the event types it receives.
frazer integrations webhook-endpoints deliveriesList an endpoint's deliveries, filtered by status and time.
frazer integrations webhook-endpoints redeliverRedeliver an endpoint's failed deliveries since a given time.
frazer integrations webhook-endpoints listenForward events to a local port while you develop a receiver.
frazer integrations webhook-endpoints triggerSend a test event of a given type.

All of them: CLI reference.

Terraform and OpenTofu

ResourceWhat it manages
frazer_integrations_webhook_endpointA webhook endpoint; its signing secret is a write-only attribute.

All of them: Terraform and OpenTofu reference.

Event typeWhen it is sent
frazer.webhook.endpoint_disabled.v1An endpoint was disabled after 5 days of failed deliveries.
frazer.approval.requested.v1A change is waiting for an approval.
frazer.approval.decided.v1An approval was decided.
frazer.plan.applied.v1An approved plan was applied.
frazer.audit.event.v1An audit record was written; for a SIEM.

The API is WebhookEndpointsService (with deliveries, redeliver, send test and rotate secret) and EventTypesService, which serves each event type’s JSON Schema. On mcp.frazer.ai, webhook tools are in the toolset webhooks.