---
title: Webhooks
description: Push observed events to external HTTP endpoints as they're appended.
---

import { Tabs, TabItem } from '@astrojs/starlight/components';


A webhook forwards events Chronicle observes to an external HTTP endpoint — use it to notify another system without that system needing to connect to Chronicle itself. Webhooks are configured server-side (the Kernel makes the HTTP calls), so registering one is a one-time setup step, not something you do per request.

## Register a webhook

<Tabs syncKey="chronicle-client">
<TabItem label="C#">

```csharp
using Cratis.Chronicle;
using Cratis.Chronicle.Events;
using Cratis.Chronicle.Webhooks;

[EventType]
public record WebhooksIndexAccountOpened(string OwnerName);

public class WebhooksIndexRegister(IEventStore eventStore)
{
    public async Task RegisterWebhook() =>
        await eventStore.Webhooks.Register(
            "account-events",
            "https://example.com/chronicle/webhooks",
            builder => builder
                .WithEventType<WebhooksIndexAccountOpened>()
                .WithHeader("x-source", "my-app")
                .WithBearerToken(Environment.GetEnvironmentVariable("WEBHOOK_TOKEN")!));
}
```

</TabItem>
<TabItem label="Kotlin">

```text
Kotlin does not support this workflow yet.
```

</TabItem>
<TabItem label="Java">

```text
Java does not support this workflow yet.
```

</TabItem>
<TabItem label="Elixir">

```elixir
defmodule MyApp.Events.WebhooksIndexAccountOpened do
  use Chronicle.Events.EventType, id: "webhooks-index-account-opened"

  defstruct [:owner_name]
end

defmodule MyApp.WebhooksIndexRegister do
  alias MyApp.Events.WebhooksIndexAccountOpened

  def register_webhook do
    Chronicle.WebHooks.register(
      "account-events",
      "https://example.com/chronicle/webhooks",
      fn builder ->
        builder
        |> Chronicle.WebHooks.DefinitionBuilder.with_event_type(WebhooksIndexAccountOpened)
        |> Chronicle.WebHooks.DefinitionBuilder.with_header("x-source", "my-app")
        |> Chronicle.WebHooks.DefinitionBuilder.with_bearer_token(System.fetch_env!("WEBHOOK_TOKEN"))
      end
    )
  end
end
```

</TabItem>
<TabItem label="TypeScript">

```typescript
import { eventType, IEventStore } from '@cratis/chronicle';

@eventType()
class WebhooksIndexAccountOpened {
    constructor(readonly ownerName: string) {}
}

class WebhooksIndexRegister {
    constructor(
        private readonly store: IEventStore,
        private readonly webhookToken: string
    ) {}

    async registerWebhook(): Promise<void> {
        await this.store.webhooks.register(
            'account-events',
            'https://example.com/chronicle/webhooks',
            builder => {
                builder
                    .withEventType(WebhooksIndexAccountOpened)
                    .withHeader('x-source', 'my-app')
                    .withBearerToken(this.webhookToken);
            }
        );
    }
}
```

</TabItem>
</Tabs>

If no event types are configured, the webhook forwards every event type registered for the client.

## Query registered webhooks

<Tabs syncKey="chronicle-client">
<TabItem label="C#">

```csharp
using Cratis.Chronicle;
using Cratis.Chronicle.Webhooks;

public class WebhooksIndexQuery(IEventStore eventStore)
{
    public async Task<IEnumerable<WebhookDefinition>> GetAllWebhooks() => await eventStore.Webhooks.GetAll();
}
```

</TabItem>
<TabItem label="Kotlin">

```text
Kotlin does not support this workflow yet.
```

</TabItem>
<TabItem label="Java">

```text
Java does not support this workflow yet.
```

</TabItem>
<TabItem label="Elixir">

```elixir
defmodule MyApp.WebhooksIndexQuery do
  def get_all_webhooks do
    Chronicle.WebHooks.all()
  end
end
```

</TabItem>
<TabItem label="TypeScript">

```typescript
import { IEventStore } from '@cratis/chronicle';
import { WebhookDefinition } from '@cratis/chronicle.contracts';

class WebhooksIndexQuery {
    constructor(private readonly store: IEventStore) {}

    async getAllWebhooks(): Promise<WebhookDefinition[]> {
        return this.store.webhooks.getWebhooks();
    }
}
```

</TabItem>
</Tabs>

Kotlin and Java don't currently have a webhooks API — there's no equivalent anywhere in the Kotlin client SDK yet.

## Related topics

- [Jobs](/chronicle/jobs/) — inspecting and controlling long-running Kernel operations, the other kernel-managed background concern.
- [Subscriptions](/chronicle/subscriptions/) — forwarding events between event stores rather than to an external HTTP endpoint.
