Skip to main content
Webhooks let you receive real-time execution notifications from Asteroid over HTTP.
Only Webhook V2 is supported. Webhook V1 is deprecated and no longer accepted by the API.

Overview

Real-time Notifications

Get updates as execution events happen

Secure Delivery

Every request includes an RSA signature in X-Asteroid-Signature

Event Coverage

Subscribe to status, step, action, file, message, workflow, and batch events

Filterable Notifications

Filter by event type, payload fields, and execution metadata

Configuration

Setting Up Your Webhook

1

Create a Webhook Integration

In Asteroid, go to IntegrationsAdd IntegrationWebhook, then set:
  • URL: The endpoint that will receive execution events
  • Headers: Optional custom headers Asteroid should include
Webhook requests are always POST with a JSON body in the V2 format documented below.
2

Attach the Integration to an Agent

Attach the webhook integration to each agent you want notifications from. You can configure:
  • Event rules: choose which event types should trigger notifications
  • Field filters: filter by payload fields for specific event types
  • Metadata filter: only trigger when execution metadata key/value pairs match
  • Unwrap result (optional): for ExecutionCompleted, send only payload.result instead of the full envelope
See Filtering & Rules for rule semantics.
3

Verify Signatures in Your Endpoint

Validate the X-Asteroid-Signature header against the raw request body before processing.

V2 Payload Structure

Each webhook request body is a JSON object with this top-level shape:
{
  "type": "execution",
  "event_id": "83b7b49f-1f73-4f86-9d89-6fd8dd2557f3",
  "timestamp": "2024-01-15T10:30:00Z",
  "info": {
    "event": "EXECUTION_COMPLETED",
    "execution_id": "a2c7f3b3-cbc8-4b6a-a5f2-c5f6cb548e95",
    "execution_url": "https://platform.asteroid.ai/executions/a2c7f3b3-cbc8-4b6a-a5f2-c5f6cb548e95",
    "agent_id": "6bf63aaf-6e3e-4115-8f13-e707d627582f",
    "agent_name": "Data Extraction Agent",
    "metadata": {
      "environment": "production"
    },
    "payload": {
      "result": { /* execution result data */ },
      "reasoning": "Task completed successfully",
      "outcome": "success"
    }
  }
}

Top-Level Fields

type
string
required
The category of the notification. Currently only "execution" is supported.
event_id
string
required
Unique identifier generated for this specific webhook notification payload.
timestamp
string
required
ISO 8601 timestamp when the event occurred.
info
object
required
Execution event context and event-specific payload. See Execution Info.

Execution Info Structure

info contains execution context plus an event-specific payload.
info.event
string
required
Event name. See Execution Events for supported values.
info.execution_id
string
required
Execution UUID.
info.execution_url
string
required
URL to view this execution (or batch for batch events) in Asteroid.
info.agent_id
string
required
Agent UUID.
info.agent_name
string
required
Agent display name.
info.metadata
object
Optional execution metadata map. Included when metadata was supplied at execution creation time.
info.payload
object
required
Event-specific data. The schema depends on info.event.

Execution Events

Asteroid currently emits the following webhook events:

Core execution status

  • EXECUTION_STARTED -> payload: {}
  • EXECUTION_COMPLETED -> payload: { result: object, reasoning: string, outcome: string }
  • EXECUTION_FAILED -> payload: { reason: string }
  • EXECUTION_CANCELLED -> payload: { reason: string, cancelled_by: string }
  • EXECUTION_PAUSED -> payload: { reason: string, paused_by: string }
  • EXECUTION_RESUMED -> payload: { reason: string }
  • EXECUTION_AWAITING_CONFIRMATION -> payload: { reason: string }

Action and step events

  • EXECUTION_ACTION_STARTED -> { action_id, action_name, arguments, step_number }
  • EXECUTION_ACTION_COMPLETED -> { action_id, action_name, output, step_number, duration? }
  • EXECUTION_ACTION_FAILED -> { action_id, action_name, failure, step_number, duration?, os_error? }
  • EXECUTION_STEP_STARTED -> { step }
  • EXECUTION_STEP_PROCESSED -> { step }

Execution detail events

  • EXECUTION_MESSAGE_ADDED -> { message }
  • EXECUTION_REASONING_ADDED -> { reasoning }
  • EXECUTION_FILE_ADDED -> { file_id, file_name, mime_type, file_size, source, presigned_url }
  • EXECUTION_PLAYWRIGHT_SCRIPT_GENERATED -> { node_id, node_name, script, context, generated_at }
  • EXECUTION_TRANSITIONED -> { to_node, from_node_duration?, transition_type? }
  • EXECUTION_WORKFLOW_UPDATED -> { workflow_update: [...] }
  • USER_MESSAGE_RECEIVED -> { user_id, message, execution_was, injected_into }

Batch and test events

  • BATCH_STARTED -> { batch_id, batch_name, item_count }
  • BATCH_COMPLETED -> { batch_id, batch_name, triggered_count, cancelled_count }
  • EXECUTION_TEST -> { message } (used when testing integration connectivity)
For batch events, info.execution_url points to the agent batch page (/agents/{agent_id}/batch) rather than an execution page.

Example: EXECUTION_ACTION_FAILED

{
  "type": "execution",
  "event_id": "f0df4bd4-fdf8-445b-b870-1cd6ed329f39",
  "timestamp": "2026-03-27T16:10:05Z",
  "info": {
    "event": "EXECUTION_ACTION_FAILED",
    "execution_id": "a2c7f3b3-cbc8-4b6a-a5f2-c5f6cb548e95",
    "execution_url": "https://platform.asteroid.ai/executions/a2c7f3b3-cbc8-4b6a-a5f2-c5f6cb548e95",
    "agent_id": "6bf63aaf-6e3e-4115-8f13-e707d627582f",
    "agent_name": "Data Extraction Agent",
    "payload": {
      "action_id": "playwright_script-node-123",
      "action_name": "playwright_script",
      "failure": "Timeout waiting for selector",
      "step_number": 7,
      "duration": 1432,
      "os_error": {
        "message": "Target page, context or browser has been closed"
      }
    }
  }
}

Security & Signature Verification

Asteroid signs every webhook body using:
  • SHA-256 digest of the raw body bytes
  • RSA PKCS#1 v1.5 signing
  • Base64-encoded signature in the header

Signature Header

X-Asteroid-Signature: <base64-signature>
Verify signatures using the raw request body bytes before JSON parsing.

Public Key

Use the webhook verification public key provided for your Asteroid environment/workspace.

JavaScript (Node.js) verification example

import crypto from "node:crypto";

export function verifyWebhookSignature(rawBodyBuffer, signatureBase64, publicKeyPem) {
  const verifier = crypto.createVerify("sha256");
  verifier.update(rawBodyBuffer);
  verifier.end();

  return verifier.verify(publicKeyPem, signatureBase64, "base64");
}

// Example Express handler
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
  const signature = req.header("X-Asteroid-Signature");
  const isValid = verifyWebhookSignature(req.body, signature, process.env.ASTEROID_WEBHOOK_PUBLIC_KEY_PEM);

  if (!isValid) {
    return res.status(401).json({ error: "Invalid signature" });
  }

  const event = JSON.parse(req.body.toString("utf8"));
  // process event...
  res.status(200).json({ received: true });
});

Best Practices

Return a 2xx response as quickly as possible, then process asynchronously in your own job queue.
Duplicate deliveries can happen. Use your own idempotency key strategy based on stable business identifiers.
event_id is generated per notification payload and can change across retries/redeliveries, so do not rely on it as the only dedupe key.
Validate X-Asteroid-Signature against the raw body and reject invalid requests with 401.
Asteroid performs up to 3 send attempts with short backoff in the notification worker before marking a delivery failed.
Log at least info.event, info.execution_id, info.agent_id, and your own processing result for observability.

Testing Your Webhooks

Use webhook.site for quick smoke tests, then validate with your real endpoint and signature verification enabled.

Test Integration Event Example

Using “Test integration” in Asteroid sends an EXECUTION_TEST payload:
{
  "type": "execution",
  "event_id": "2ec89fb9-c2b5-4f6a-9fe9-c8f4f9dd6f66",
  "timestamp": "2024-01-15T10:30:00Z",
  "info": {
    "event": "EXECUTION_TEST",
    "execution_id": "00000000-0000-0000-0000-000000000003",
    "execution_url": "",
    "agent_id": "00000000-0000-0000-0000-000000000001",
    "agent_name": "Test Agent",
    "payload": {
      "message": "This is a test notification from Asteroid. If you're seeing this, your integration is working correctly! 🎉"
    }
  }
}

Troubleshooting

  • Verify your endpoint is reachable from Asteroid and accepts POST
  • Ensure your notification rule configuration matches the events you expect
  • Confirm metadata filter values exactly match execution metadata values
  • Verify against raw request bytes, not parsed JSON
  • Ensure you use RSA PKCS#1 v1.5 with SHA-256
  • Confirm you’re using the correct environment public key
  • Handle at-least-once semantics in your endpoint logic
  • Use stable execution fields for idempotency (not only event_id)
  • Return 2xx once a duplicate is safely recognized