POST requests with a JSON body. This
page defines the receiver contract, event schemas, signature verification, and
delivery behavior.
For dashboard setup and testing, see
Receive run events with webhooks.
Request contract
Your receiver must:- Accept HTTPS
POSTrequests. - Read and retain the exact request body bytes.
- Verify the timestamp and HMAC signature before parsing or processing the event.
- Deduplicate events by their stable
id. - Durably accept the event and return a
2xxresponse quickly. - Process expensive work asynchronously.
Content-Type: application/json and include these headers:
string
required
The stable event ID. It matches the
id field in the body and is included in
the signed message.string
required
The Unix timestamp, in seconds, when the delivery attempt was signed.
string
required
The HMAC-SHA256 signature, formatted as
v1,<hex digest>.string
required
Identifies the EigenPal webhook sender and release.
Event envelope
Every request has a versioned JSON envelope:Envelope fields
string
required
Stable event ID with a
whev_ prefix. Use this value as the idempotency key.run.created | run.status_changed
required
Identifies the event schema.
string
required
Version of the webhook wire contract. The current version is
2026-07-01.string
required
ISO 8601 timestamp for when the event was created.
boolean
required
true for events created with Send test; otherwise false.test is true, data.run contains synthetic sample data. Its run and
automation IDs do not identify persisted resources. Verify and acknowledge the
request normally, but do not fetch or process the sample as a real run.
object
required
Event-specific payload.
Run fields
string
required
Run ID.
string
required
Automation that owns the run.
workflow | agent
required
Runtime used by the automation.
string
required
Current persisted run status.
string
required
How the run was started, such as
api, manual, email, or cron.string
required
ISO 8601 timestamp for when the run was created.
string | null
required
ISO 8601 timestamp for when execution started, or
null.string | null
required
ISO 8601 timestamp for when the run reached a terminal status, or
null.unknown
Public run output, when available and small enough to include.
boolean
true when output was removed to keep the complete event within the payload
limit. Retrieve the canonical result with
GET /api/v1/runs/{id}.Event types
run.created
Sent when a top-level workflow or agent run is durably created. data.run
contains the initial run snapshot. Most workflow runs are already pending when
this event is sent; agent runs can initially be created while preparation
completes.
This event does not include previousStatus or currentStatus. Test deliveries
use the same schema with synthetic run data.
run.status_changed
Sent whenever a top-level run moves from one persisted status to another.
Test deliveries simulate this transition with synthetic run data.
string
required
Status the run moved from.
string
required
Status the run moved to. This matches
data.run.status.action.invoke-workflow step and evaluation runs
do not emit webhook events.
Run statuses
created— The run exists and is being prepared before it enters the queue.pending— The run is queued and eligible for a worker.running— A worker is actively executing the run.waiting— The workflow is paused for a human, tool, or step continuation. Not all run types use this status.finalizing— Primary execution has finished, but outputs or other post-run work are still being saved.completed— The run finished successfully. Terminal.failed— The run ended because of an error or timeout. Terminal.cancelled— The run was cancelled before completion. Terminal.rejected— The run was refused before it started, for example because of an inbound email policy. Terminal.
queued is an execution phase, not a run status. The externally visible status
for a run waiting in the queue is pending.
Verify webhook signatures
Do not process an event until its signature and timestamp have been verified. EigenPal signs this message with the endpoint’swhsec_... secret:
Delivery and retries
Delivery is asynchronous and at least once. Duplicate events are expected, and events are not guaranteed to arrive in order.- Deduplicate by the event
id. - Use
previousStatus,currentStatus, andcreatedAtinstead of inferring lifecycle order from delivery order. - Return
2xxas soon as the event is durably accepted. - Process expensive work after acknowledging the request.
2xx response marks a delivery successful. EigenPal retries network
failures, timeouts, 408, 425, 429, and 5xx responses with bounded
backoff. Other 4xx responses end automatic delivery. A valid Retry-After
response header can delay the next retry within EigenPal’s configured limit.
Manual redelivery preserves the event ID and payload, so normal deduplication
still applies.