---
title: Relay Hook
description: Emit typed webhook events at every Dispatch lifecycle point using relay_hook.
---

The `relay_hook` package bridges Dispatch lifecycle events to [Relay](https://github.com/xraph/relay) for webhook delivery. When registered as a Dispatch extension, it emits a typed webhook event at every job, workflow, cron, and shutdown lifecycle point.

## Setup

```go
import (
    "github.com/xraph/relay"
    "github.com/xraph/dispatch/relay_hook"
    "github.com/xraph/relay/store/memory"
)

// Create a Relay instance.
r, _ := relay.New(relay.WithStore(memory.New()))

// Register the event types Dispatch will emit.
relay_hook.RegisterAll(ctx, r)

// Create the hook extension.
hook := relay_hook.New(r)

// Register with the engine.
eng := engine.Build(d,
    engine.WithExtension(hook),
)
```

## Emitted event types

| Event type | Lifecycle point |
|-----------|----------------|
| `dispatch.job.enqueued` | Job accepted into queue |
| `dispatch.job.started` | Worker begins execution |
| `dispatch.job.completed` | Job finishes successfully |
| `dispatch.job.failed` | Job fails terminally |
| `dispatch.job.retrying` | Job fails, scheduled for retry |
| `dispatch.job.dlq` | Job moved to DLQ |
| `dispatch.workflow.started` | Workflow run begins |
| `dispatch.workflow.step.completed` | Workflow step completes |
| `dispatch.workflow.step.failed` | Workflow step fails |
| `dispatch.workflow.completed` | Workflow run completes |
| `dispatch.workflow.failed` | Workflow run fails |
| `dispatch.cron.fired` | Cron entry fires |
| `dispatch.shutdown` | Dispatcher shuts down |

## Filtering events

Restrict which events are emitted:

```go
hook := relay_hook.New(r,
    relay_hook.WithEvents(
        relay_hook.EventJobCompleted,
        relay_hook.EventJobFailed,
        relay_hook.EventJobDLQ,
        relay_hook.EventWorkflowFailed,
    ),
)
```

## Event payload

Each webhook event carries a JSON payload with the full entity at the time of the lifecycle event. For example, `dispatch.job.completed` includes:

```json
{
  "job_id": "job_01h2xcejqtf2nbrexx3vqjhp41",
  "name": "send_email",
  "queue": "default",
  "elapsed_ms": 142,
  "completed_at": "2025-01-15T09:00:00Z"
}
```

## Tenant routing

Webhook events are routed to Relay endpoints matching the job's `ScopeOrgID` as the `TenantID`. If `ScopeOrgID` is empty, events are routed to a global tenant.
