Skip to main content
workflows emit events as they run. An integration carries those events to somewhere you watch — an HTTP endpoint you own, or a Slack channel. Use integrations instead of polling when executions are long or volume is high. Use them when a person must know that a unattended execution failed.

How events reach you

Integrations work in two layers.
  1. The integration. You create it once for the organisation. It holds the connection — the webhook URL, or the authorised Slack workspace.
  2. The notification. You attach the integration to a workflow, and choose which events fire it.
One integration can serve many workflows. One workflow can carry several notifications with different rules.

Set up a webhook

1

Create the integration

Go to IntegrationsAdd IntegrationWebhook, then set:
  • URL — the endpoint that receives the events.
  • Headers — optional headers Asteroid adds to every request.
Asteroid always sends POST with a JSON body.
2

Attach it to a workflow

Open the workflow, go to the Notifications tab, and select Add Notification. Then configure:
  • Event rules — which event types fire the notification.
  • Field filters — match on fields inside the payload.
  • Metadata filter — fire only when the execution’s metadata matches.
  • Unwrap result — for EXECUTION_COMPLETED, send payload.result alone instead of the full envelope.
3

Verify the signature

Check X-Asteroid-Webhook-Signature against the raw request body before you parse or act on anything. See Verify the signature.

Payload structure

Every request body has the same shape, unless Unwrap result is set on an EXECUTION_COMPLETED rule. That delivery carries the result object on its own.
string
required
The category of the notification. execution for execution events. Batch events use execution_batch and a different info shape. See Batch notifications.
string
required
Identifier for this delivery.
string
required
ISO 8601 timestamp of the event.
object
required
The execution context and the event-specific payload.
info holds:
string
required
The event name. See Event types.
string
required
Execution UUID.
string
required
Link to the execution in the platform. For batch events it points at the workflow’s batch page.
string
required
workflow UUID.
string
required
workflow display name.
object
The metadata you attached when you started the execution.
object
required
Event-specific data. Its shape depends on info.event.

Event types

Match on info.event. The rule picker in the platform lists the same events by name.

Execution lifecycle

EXECUTION_CANCELLED carries the cancel reason. See Debug your workflows for what each reason means.

Actions and steps

Execution detail

Tests


Batch notifications

A batch is not an execution, so its events arrive with type: "execution_batch" and a batch info. Subscribe with the Batch Started and Batch Completed rules. Batch events carry no metadata, so a notification with a metadata filter never fires for them. Started and Completed can arrive out of order for a very small batch.
event_id is stable for a batch event. A redelivery repeats it, so you can deduplicate on it. See Batch executions.

Example: a failed action


Verify the signature

Asteroid signs every delivery. Check the signature against the raw request body before you parse or act on anything. Every request carries these headers: Each signature is the SHA-256 digest of the raw body bytes, signed with RSA PKCS#1 v1.5, then Base64 encoded. The key set names that algorithm RS256.
Verify against the raw request bytes, before you parse the JSON. Any reserialisation changes the bytes and breaks the check.

Fetch the public keys

Public keys are published as a JSON Web Key Set. The endpoint is public and needs no credentials.
Select the key whose kid matches X-Asteroid-Webhook-Key-Id. Cache the set and refetch when a delivery names a kid you do not hold. A new key appears in the set before we sign anything with it. A receiver that refetches on an unknown kid survives every rotation with no code change and no downtime.
Do not hardcode a single key. That is what the deprecated header forces, and it is why rotating it breaks receivers.

Example

The legacy header

X-Asteroid-Signature is deprecated. Move to X-Asteroid-Webhook-Signature.
X-Asteroid-Signature predates key ids. It names no key, so it is always signed with one fixed key. That key cannot be rotated without breaking every receiver that pinned it. Nothing breaks today. We still send the header on every delivery, and we will announce a removal date well before we stop. Until then, treat it as read-only history:
  • New integrations verify X-Asteroid-Webhook-Signature only.
  • Existing integrations migrate, then stop reading X-Asteroid-Signature.
The GET /integrations/webhook/public-key endpoint needs a platform session. Its top-level publicKeyPem and keyId describe this legacy key only. The same response also returns a keys array with every signing key in the ring. Prefer the unauthenticated JWKS endpoint.

Migrate off the legacy header

The payload, the algorithm, and the raw-bytes rule are unchanged. You are only changing which header you read and where the key comes from.
1

Read the key id

Read X-Asteroid-Webhook-Key-Id from the request.
2

Look the key up

Fetch https://odyssey.asteroid.ai/.well-known/jwks.json and select the key with that kid. Cache the set, and refetch on a kid you do not hold.
3

Verify the new header

Verify X-Asteroid-Webhook-Signature against the raw body with that key. Your existing verification call stays the same, because the algorithm has not changed.
4

Drop the old header

Stop reading X-Asteroid-Signature and delete the pinned public key from your configuration.
Test the change with Test integration in the platform. It sends a real signed delivery. See Test the integration.

Filter what you receive

Most teams want the failures, not the running commentary.

Subscription modes

Field filters

Add one or more field filters to an event type. Filters on one event type combine with OR: the notification fires when any of them match. Two filters — outcome equals failure and outcome equals cancelled — mean “tell me when the outcome is either one”.

Metadata filters

A metadata filter matches the key-value pairs you attached when you started the execution. All pairs must match, so the filter combines with AND. Leave the metadata filter empty and the notification fires for every execution. Metadata filtering runs after event-type filtering. An execution must match the event rules first, then the metadata filter.
Attach metadata on every execute call and one workflow can feed several channels. Send production failures to your on-call channel, and staging failures nowhere. See Call a workflow from your code.

A worked example

One workflow, two environments, two webhooks. A production failure fires the first. A staging failure fires the second. A staging run that completes fires neither.

Slack

The Slack integration posts the same events into a channel, formatted for people to read.

Install it

You need a Slack workspace where you can install apps.
1

Add the integration

In the platform, go to IntegrationsAdd IntegrationSlack. Slack asks you to authorise the app. Review the permissions, pick the workspace, and select Allow.
2

Set the default channel

Find the new Slack integration in the list and open its Edit dialog. Pick a Default Channel and save. The Asteroid bot joins the channel you pick.
The dropdown lists public channels. To use a private channel, invite the Asteroid bot to it in Slack first. The channel then appears in the dropdown, after you refresh the page.
3

Attach it to a workflow

Open the workflow, go to the Notifications tab, and select Add Notification. Pick the Slack integration, set the event rules, and save.

What a Slack message contains

  • Status — a colour and an icon for the event type.
  • Context — the workflow name, and a link to the execution in the platform.
  • Detail — depends on the event:
    • EXECUTION_COMPLETED — a snippet of the result and the workflow’s reasoning.
    • EXECUTION_FAILED — the error and the reason.
    • EXECUTION_PAUSED — the reason, such as the question the workflow asked.
Some messages carry a button. A human-in-the-loop request lets you open the execution straight from Slack.

Test the integration

Select Test integration in the platform. Asteroid sends an EXECUTION_TEST payload.
Point a new webhook at webhook.site for the first smoke test. Then move to your real endpoint with signature verification switched on.

Build a reliable endpoint

Return 2xx as soon as you have the body. Do the work afterwards, in your own queue. A slow endpoint turns into a failed delivery.
Delivery is at-least-once. Build your handler so a repeat is harmless.Dedupe on your own business identifiers. event_id is generated per delivery and changes across retries, so it cannot carry the whole job.
Asteroid makes up to three send attempts, with a short backoff, before it marks a delivery failed.
Run a periodic sweep with GET /executions alongside your webhook handler. It catches anything that arrived while your endpoint was down. See Executions and statuses.
Log info.event, info.execution_id, info.agent_id, and your own outcome. That is enough to reconstruct any delivery later.

Troubleshooting

  • Check the endpoint is reachable from the internet and accepts POST.
  • Check the notification’s event rules cover the events you expect.
  • Check the metadata filter values match the execution’s metadata exactly.
  • Verify against the raw request bytes, not parsed JSON.
  • Use RSA PKCS#1 v1.5 with SHA-256.
  • Check you picked the key whose kid matches X-Asteroid-Webhook-Key-Id.
  • Refetch the key set. A delivery naming a kid you do not hold means your cache is stale.
  • If you still verify the deprecated X-Asteroid-Signature, see Migrate off the legacy header.
  • Handle at-least-once delivery in your own logic.
  • Dedupe on stable execution fields, not on event_id alone.
  • Return 2xx once you recognise a duplicate.
  • Check the integration has a default channel.
  • For a private channel, invite the Asteroid bot in Slack first.
  • Check the integration is attached to the workflow on its Notifications tab.

Next

Call a workflow from your code

Attach the metadata your filters match on

Batch executions

Batch events and why webhooks beat polling

Executions and statuses

The statuses behind each event

Debug your workflows

What to do when an event says the execution failed