# Webhooks

## Overview

Euno can send real-time event notifications to your own HTTP endpoints whenever something significant happens in your account — for example, when a workflow rule triggers. Webhook delivery is powered by [Svix](https://www.svix.com/), which handles queueing, retries, delivery logs, and signature signing on your behalf.

Every Euno account gets its own isolated Svix application, so webhook endpoints and events are never shared across accounts.

***

## Prerequisites

* You must have the **Manage Webhooks** permission on your account.
* You need an HTTPS endpoint that can receive `POST` requests and return a `2xx` response.

{% hint style="info" %}
If you don't have a live endpoint yet, you can use [Svix Play](https://play.svix.com/) in the App Portal to generate a temporary test URL.
{% endhint %}

***

## Configure a Webhook Endpoint

### Step 1: Open the Webhooks page

Navigate to **Account Settings → Webhooks** (`/account?tab=webhooks`).

### Step 2: Open the Svix App Portal

Click **Open Webhook Portal**. Euno generates a short-lived magic link and opens the [Svix Consumer App Portal](https://docs.svix.com/app-portal) in a new tab. No separate Svix account is needed.

### Step 3: Add an endpoint

Inside the App Portal, click **Add Endpoint** and enter your HTTPS endpoint URL. See [Adding Endpoints in the App Portal](https://docs.svix.com/receiving/using-app-portal/adding-endpoints) for details.

You can optionally:

* **Filter by event type** — select which event types the endpoint should receive. If you leave this blank, the endpoint receives all event types.
* **Filter by channel** — subscribe to a specific channel to receive only events tagged with it (see [Event Filtering with Channels](#event-filtering-with-channels) below).

### Step 4: Verify delivery

After Euno sends the next matching event, use the **Delivery Logs** tab in the App Portal to inspect the request, response, and full payload. You can also manually send a test event from there.

***

## Available Event Types

| Event type           | When it fires                                          |
| -------------------- | ------------------------------------------------------ |
| `workflow.triggered` | A workflow rule evaluated and its conditions were met. |

{% hint style="info" %}
See [Euno Workflows](/using-euno/metadata-activation/workflows.md) for details on creating and managing workflow rules.
{% endhint %}

***

## `workflow.triggered` Payload

Every webhook request body is a JSON object. Below is a full example for `workflow.triggered`:

```json
{
  "type": "workflow.triggered",
  "workflow_rule_id": "550e8400-e29b-41d4-a716-446655440000",
  "workflow_rule_name": "Undocumented dbt models",
  "account_id": 42,
  "trigger_type": "threshold",
  "results_count": 17,
  "triggered_at": "2026-05-12T08:30:00+00:00",
  "result_uris": [
    "euno://dbt_model/my_project/my_schema/model_a",
    "euno://dbt_model/my_project/my_schema/model_b"
  ],
  "result_uris_truncated": false
}
```

> `result_uris` is capped at 1,000 entries. When the actual match count exceeds this, `result_uris_truncated` is `true` and the full list of matched resources can be found via the Euno UI.

| Field                   | Type              | Description                                                        |
| ----------------------- | ----------------- | ------------------------------------------------------------------ |
| `type`                  | string            | Always `"workflow.triggered"`.                                     |
| `workflow_rule_id`      | string (UUID)     | Unique identifier for the workflow rule.                           |
| `workflow_rule_name`    | string            | Display name of the workflow rule.                                 |
| `account_id`            | integer           | Euno account ID.                                                   |
| `trigger_type`          | string            | Trigger type: `"threshold"`, `"result_diff"`, or `"result_added"`. |
| `results_count`         | integer           | Number of matching resources at trigger time.                      |
| `triggered_at`          | string (ISO 8601) | UTC timestamp when the workflow triggered.                         |
| `result_uris`           | array of strings  | Euno URIs of the matching resources (capped at 1,000).             |
| `result_uris_truncated` | boolean           | `true` when there were more than 1,000 matching resources.         |

***

## Event Filtering with Channels

Every `workflow.triggered` event is tagged with two [Svix channels](https://docs.svix.com/channels):

| Channel                       | Meaning                                         |
| ----------------------------- | ----------------------------------------------- |
| `workflows`                   | All workflow-triggered events for this account. |
| `workflow:<workflow_rule_id>` | Events from one specific workflow rule.         |

Channels are **optional** — by default an endpoint with no channel filter receives all events. You add a channel filter in the App Portal when adding or editing an endpoint.

### Practical example: subscribe to a single workflow

1. Open the workflow in Euno. The URL looks like:

   ```
   /workflows/550e8400-e29b-41d4-a716-446655440000?accountId=42
   ```
2. Copy the UUID from the URL (`550e8400-e29b-41d4-a716-446655440000`). This is the `workflow_rule_id`.
3. In the App Portal, add or edit your endpoint and set the **Channel** filter to:

   ```
   workflow:550e8400-e29b-41d4-a716-446655440000
   ```
4. The endpoint will now receive events only when that specific workflow triggers.

The `workflow_rule_id` is also present in every `workflow.triggered` payload, so you can also filter on the receiving side if you prefer a single catch-all endpoint.

{% hint style="info" %}
Channel strings are case-sensitive. Always use lowercase.
{% endhint %}

***

## Delivery, Retries, and Troubleshooting

Svix delivers each webhook to your endpoint and retries automatically on failure using exponential back-off:

| Attempt | Delay after previous attempt |
| ------- | ---------------------------- |
| 1       | Immediately                  |
| 2       | 5 seconds                    |
| 3       | 5 minutes                    |
| 4       | 30 minutes                   |
| 5       | 2 hours                      |
| 6       | 5 hours                      |
| 7       | 10 hours                     |
| 8       | 10 hours                     |

After all attempts fail the message is marked as **Failed**. You can recover failed messages or replay any past message from the **Delivery Logs** tab in the App Portal. See [Svix Retry Schedule](https://docs.svix.com/retries) for full details.

{% hint style="warning" %}
Your endpoint must respond with a `2xx` HTTP status code within the timeout window. If it returns any other code or times out, Svix treats the delivery as failed and will retry.
{% endhint %}

***

## Security

Svix signs every outgoing webhook request using an HMAC-SHA256 signature. The signature is sent in the `svix-signature` request header alongside `svix-id` and `svix-timestamp`. You can verify these headers in your receiving code to confirm the request genuinely came from Euno.

The signing secret for your endpoint is shown in the App Portal under the endpoint's **Signing Secret** section.

See the [Svix signature verification guide](https://docs.svix.com/receiving/verifying-payloads/how) for code examples in Python, Node.js, Go, and other languages.

***

## References

* [Svix Consumer App Portal](https://docs.svix.com/app-portal)
* [Adding Endpoints in the App Portal](https://docs.svix.com/receiving/using-app-portal/adding-endpoints)
* [Svix Event Types](https://docs.svix.com/event-types)
* [Svix Channels](https://docs.svix.com/channels)
* [Svix Retry Schedule](https://docs.svix.com/retries)
* [Verifying Webhook Signatures](https://docs.svix.com/receiving/verifying-payloads/how)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.euno.ai/setup-configuration/account-settings/webhooks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
