Skip to content

Webhook payload

Agent sends JSON by HTTPS POST to each configured webhook channel. Authenticate the exact received bytes, check freshness and deduplicate before acting. A notification is not an execution report.

All envelopes have type, UTC timestamp and data. data.schema is debyko.agent.event/1; data.event_id identifies the event. Fields differ by event type: do not assume every notice is a firing.

For watch.became_true, data contains:

Field Meaning
event_id, firing_id The same stable firing identifier for this event; preserve data.firing_id with the position actually opened.
destination_seq Monotonic sequence for this destination; retries do not create a new firing.
watch Saved rule id, version, name, and rule_set (id, name).
tag Configured channel action tag, or null. It is not authorization to execute an unknown action.
instrument Canonical instrument the rule fired for.
edge seq, false_seen_t, true_seen_t, blind_ms, rearm; optional kind for reminder/enabled events. These extra kinds are not sent to Runner channels.
evaluation dql, parsed query, units, effective mode, t, nullable bar_end, evaluated_at, nullable as_of, settled; optional receipt_id. Live-series attempts also include nominal_t, data_as_of, started_at, finished_at, attempt. A retry may use a new data slice.
fired_at, expires_at UTC event time and delivery/action expiry. Do not execute an expired signal.
answer The emitted DQL answer; inspect its values, statuses and provenance.
answer_truncated, answer_dropped Whether the bounded answer omitted detail, and which detail was removed.

For Arena, debyko_firing_id is the firing_id from the webhook body, specifically data.firing_id, not a destination sequence or a new client-generated UUID. Arena signal verification checks the account/public rule, instrument and entry time; the link does not prove execution.

  • watch.became_true: a recorded rule firing.
  • firing.verified: later verification with data.watch, t, verified_at and firings[] (firing_id, instrument, status, nullable reason); an optional answer describes contradictions. This event has its own event ID and refers back to original firing IDs.
  • watch.paused, watch.resumed, watch.flapping, watch.blind, watch.recovered: rule status notices, not entry signals. They include the watch and reason/status-specific evidence (for example blind since, reason, window_s, or recovered blind_from/blind_to).
  • agent.resumed: account-level recovery notice, without a watch.
  • account.stop_all: the configured stop tag, pressed_at, paused counts, expires_at and null firing_id; handle separately from entries.
  • watch.test: connectivity/preview test with test: true, null firing_id and edge, optional watch, nullable instrument/answer and optional evaluated_at. Never trade a test.
  • destination.verify: channel setup challenge, not a firing. Its data contains challenge, expires_at and nullable report_token. After verifying the request, answer HTTP 200 with {"verify":"<base64 HMAC-SHA256 of UTF-8 verify.<challenge> under the decoded webhook key>"}. It has no ordinary retry loop; a failed verification must be requested again. It is not an ordinary successful test delivery.

Agent uses Standard Webhooks v1:

  • webhook-id: stable delivery event ID.
  • webhook-timestamp: Unix seconds for this delivery attempt.
  • webhook-signature: one or more space-separated v1,<base64 HMAC> signatures; rotation may send two.
  • debyko-attempt: attempt number (informational, not part of the signed input).
  • Content-Type: application/json; charset=utf-8, User-Agent: DEBYKO-Agent/1 (+https://debyko.com).

Decode the base64 secret after its whsec_ prefix. Compute HMAC-SHA256 over UTF-8 webhook-id + "." + webhook-timestamp + "." + raw_body, base64 the digest and compare a v1 signature in constant time. Use a Standard Webhooks library where possible. Require a timestamp within a bounded clock-skew window (for example five minutes), and persist processed event IDs. Do not parse and reserialize before verification; never log the secret or full credentials.

Return a 2xx after safely recording the event for processing. Ordinary delivery retries transport failures, timeouts, HTTP 408/425/429 and 5xx. Other non-2xx statuses are not retried as transient failures. Redirects are not followed. The retry delays are approximately 1, 3, 10, 20 seconds, then 30 seconds, with ±20% jitter; a longer Retry-After on 429 wins. No attempt starts after expires_at.

Retries keep the same body and ID but carry a fresh timestamp/signature. A late verification/correction is a separate event, linked by its original firing IDs. Webhook absence is not a false result for a rule.

Use the existing channel/rule Send test action to verify delivery. Tests have their own IDs and cannot provide an Arena verified firing. Rules and channels · Public rules.