Docs

Webhook events

Every webhook event type K-Block sends, what triggers it and the fields of its data payload.

A webhook endpoint receives an event when something happens in your organization that it subscribed to: an approval is requested, a call is denied, a receipt is issued. There are 14 event types you can subscribe to, plus webhook.test, which is sent only when you ask for it.

K-Block records each event together with the change it reports, so an event exists only if the change really happened. Deliveries are created at that moment for the endpoints that are enabled and subscribed to the type: an endpoint that is disabled when an event is recorded never receives that event, even after it is enabled again. This page lists the events and their payloads. How deliveries are signed, retried and redelivered is described in Webhook delivery; creating endpoints in Webhooks.

Event envelope

Every delivery has the same JSON body:

{
  "id": "<event-id>",                 // a UUID, the same for every delivery and redelivery of this event
  "type": "approval.requested",
  "created_at": "2026-01-15T09:30:00.000Z",
  "organization_id": "<org-id>",
  "data": { /* depends on the type, see below */ }
}

Use id to ignore an event you already processed. Event data carries IDs you can look up in the Cloud API and short descriptions. It never contains tool arguments or the upstream's result; only error_detail of execution.failed may quote the upstream's error text.

Event types at a glance

The dashboard groups the types under Approvals, Decisions, Executions, Receipts, Policies and Observe mode when you choose an endpoint's events. It groups by the type's prefix, so action.observe_override is listed under Decisions.

TypeSent when
approval.requestedA call needs approval and an approval request is created
approval.approvedAn approver approves a request
approval.rejectedAn approver rejects a request
approval.expiredA pending request expires, or its action is superseded
action.allowedA call is allowed without approval
action.deniedA call is denied
action.authorizedA decision-only call is authorized for the caller to execute
execution.completedAn approved or allowed call ran and succeeded
execution.failedA started execution failed, or an interrupted one was recovered as failed
receipt.createdA receipt is issued
policy.activatedA policy version comes into force: activation, shadow promotion, rollback or emergency stop
agent.observe_startedAn observe window starts for an agent
agent.observe_endedAn observe window ends
action.observe_overrideAn observe window allowed a call the policy would have denied or held for approval
webhook.testYou send a test event to one endpoint

Common fields

Several events describe one protected action with these fields:

FieldMeaning
protected_action_idThe action's ID
agent_idThe agent that made the call
toolThe tool's name
actionThe tool's action name, which policies decide on
amount, currencyThe call's amount as a decimal string and its currency, or null when the call has none
environmentlive or test: the environment of the gateway key the call used
thread_idThe ID of the action's evidence thread (its TASK object), or null

The decision events (approval.requested, action.allowed, action.denied, action.observe_override) also carry a policy object:

FieldMeaning
policy_id, version, digestThe policy, version number and document digest that decided, or null when no policy was evaluated
rule_idThe rule that decided, or null when the default decided
policy_effectWhat the policy itself decided: allow, require_approval, deny, or null
enforcementenforce, or observe under an observe window
relaxedtrue when the decision applied allow although the policy said otherwise
observe_window_idThe observe window, or null

Approvals

approval.requested

Sent when the Gateway decides that a call requires approval. The action becomes pending_approval.

data: the common action fields, plus

FieldMeaning
approval_request_idThe approval request to decide
expires_atWhen the request expires if nobody decides
approver_kidsThe KIDs of the eligible approvers, fixed when the request was created
policyThe decision's policy object

approval.approved

Sent when an eligible approver signs an approval. The action becomes approved; it runs when the agent repeats the call, or at once if the agent is still waiting for the decision.

data:

FieldMeaning
approval_request_id, protected_action_idThe request and its action
agent_id, tool, actionThe call
decided_byThe user ID of the approver
kidThe KID the approver signed with
decision_object_idThe ID of the signed APPROVAL object
thread_idThe action's evidence thread

approval.rejected

Sent when an eligible approver signs a rejection. The action becomes rejected and a receipt is issued (a receipt.created event follows). data has the same fields as approval.approved; decision_object_id is the signed REJECTION.

approval.expired

Sent when a pending approval request closes without a decision:

  • it reached its expiry time (the action becomes expired with code APPROVAL_EXPIRED), or
  • its action was superseded because it could no longer run as decided, for example after a policy rollback or emergency stop (code SUPERSEDED).

data:

FieldMeaning
approval_request_id, protected_action_idThe request and its action
agent_id, tool, actionThe call
expires_atThe request's expiry time
reasonSUPERSEDED when the action was superseded; absent when the request expired

Decisions

action.allowed

Sent when the Gateway allows a call without approval. The Gateway then executes it, and normally an execution.completed or execution.failed event follows. For a decision-only tool, action.authorized follows instead. If a check refuses the call before it runs (for example UPSTREAM_CHANGED), no execution event follows.

data: the common action fields and policy.

action.denied

Sent when the Gateway denies a call. Nothing runs and no receipt is issued.

data: the common action fields (without thread_id), policy, and

FieldMeaning
reason.codeWhy it was denied, for example POLICY_DENIED or NO_DELEGATION (see Error codes)
reason.messageA readable explanation

action.authorized

Sent when the Gateway hands the authorization of an allowed or approved decision-only call to the caller, which is responsible for executing it. The action becomes authorized and an authorization receipt is issued (receipt.created follows, with kind authorization). K-Block executes nothing, sends no execution event for it, and cannot confirm whether the caller executed the call.

data: the common action fields, and

FieldMeaning
approval_request_idThe approval request when a person approved the call, else null
receipt_idThe receipt of the authorization
executionAlways caller

Executions

execution.completed

Sent when the upstream call of an allowed or approved action succeeded and the result was recorded. The action becomes succeeded.

data:

FieldMeaning
protected_action_id, execution_idThe action and its execution
agent_id, tool, actionThe call
statussucceeded
result_object_idThe ID of the signed RESULT object
receipt_idThe receipt's Cloud API ID

execution.failed

Sent when an execution ends as failed, in two situations:

  • The Gateway recorded the failure: the upstream reported an error, could not be reached, or its result could not be accepted. data has the fields of execution.completed, with status failed and error_detail, a description of the failure (shortened when long). When the error text contains a value in a known secret format (a K-Block API key, a webhook signing secret, a payment provider's API key, a private key), error_detail is left out and error_detail_omitted is true. Any other text is sent as the upstream wrote it. (The audit log never stores this text: its execution.failed event has error_detail_omitted: true instead.)
  • An interrupted execution was recovered: the execution started but its outcome was never recorded, and recovery marked it failed later (code INTERRUPTED). data has protected_action_id, execution_id, agent_id, tool, action, status failed, error_detail, receipt_id (null when no receipt could be signed), result_object_id when a RESULT was signed, and upstream_called: false when the upstream is known not to have been called.

Receipts

receipt.created

Sent when a receipt is issued: after a successful or failed execution, a rejection, a cancellation, a recovered execution that could be signed, or a decision-only authorization.

data:

FieldMeaning
receipt_idThe receipt's Cloud API ID
protected_action_idThe action
receipt_object_idThe ID of the signed receipt object
thread_idThe action's evidence thread
outcomesucceeded, failed, final for rejections and cancellations, or pending / granted for a decision-only authorization
kindexecution, authorization (decision only: the receipt proves the authorization, not an execution) or closure (rejected or cancelled)
bundle_sha256The SHA-256 of the evidence bundle. Keep it with the bundle if you download it: K-Block Cloud deletes its hosted copy after the retention period

See Receipt fields.

Policies

policy.activated

Sent when a policy version comes into force.

data:

FieldMeaning
policy_id, policy_nameThe policy
version_id, version, digestThe version now in force
triggeractivate, promote_shadow, rollback or emergency
previous_version_id, previous_versionThe version it replaced, or null
restored_from_versionFor a rollback, the version number restored; otherwise null
emergency_modeFor an emergency stop, deny_all or require_approval_all; otherwise null

See Activate, roll out and roll back and Emergency stop.

Observe mode

agent.observe_started

Sent when an owner or admin starts an observe window for an agent.

data:

FieldMeaning
window_idThe observe window
agent_id, agent_nameThe agent
environmentsThe environments it covers: live, test or both
relaxdefault or default_and_approvals: which decisions the window relaxes
ends_atWhen the window ends at the latest
reasonThe reason given when it was started
started_byThe user ID of the person who started it

agent.observe_ended

Sent when an observe window ends.

data:

FieldMeaning
window_id, agent_idThe window and its agent
end_reasonended, expired, end_all, disabled_by_owner, live_disallowed, max_reduced, emergency_stop, agent_disabled or policy_changed (the agent was moved to another policy)
ended_atWhen it ended
relaxed_countHow many calls the window relaxed

action.observe_override

Sent once for each call an observe window relaxed: the policy would have denied it or held it for approval, but the window allowed it. It accompanies the call's action.allowed event.

data: the common action fields, policy, and observe with window_id, ends_at and relax.

See Observe and shadow.

webhook.test

Sent only to one endpoint, when someone selects Send test event on its page (or calls POST /api/v1/orgs/<org-id>/webhooks/<webhook-id>/test). The endpoint must be enabled. Endpoints cannot subscribe to this type, and other endpoints never receive it.

data:

FieldMeaning
endpoint_idThe endpoint the test was sent to
message"Test event sent from the K-Block Cloud dashboard"

Changes that send no event

Some changes are recorded only in the audit log, with no webhook event in this version:

  • Cancellations. Cancelling an action sends no approval.* or action.* event; the only event is receipt.created with outcome final.
  • Approved calls that expire or are superseded. When an approved action expires (TASK_EXPIRED) or is superseded before it runs, no event is sent. The approval request stays approved.
  • Execution start. There is no event when an execution starts; only its end is reported.
  • Administration. Member, invitation, API key, webhook endpoint, tool, MCP server, agent, delegation and organization settings changes, and policy drafts, shadow versions and examples, are audit events only. The exception is an observe window such a change ends (for example disabling an agent), which sends agent.observe_ended.

If you mirror action states from webhooks, also poll GET /api/v1/orgs/<org-id>/actions for actions that stay open, or listen to receipt.created to see cancellations.