> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Quick start

> Create a webhook subscription, activate it, receive the hub.destination.verified lifecycle event, and confirm delivery.

This path needs four hub calls. It subscribes to the hub's own `hub.destination.verified` lifecycle fact, so you do not need a separate product producer for the first end-to-end check.

Every `/v1` call sends the `Authorization: Bearer TOKEN` header and `Content-Type: application/json`. The hub reads the tenant only from the token.

## Before you start

***

You need:

* A running hub and a token. The catalog read also needs `catalog` `get`.
* A public `https://` endpoint you control. The hub rejects private, loopback, and cloud-metadata addresses.

## The four calls

***

```
1. GET  /v1/catalog                    → find hub.destination.verified
2. POST /v1/subscriptions              → id + signingSecret
3. POST /v1/subscriptions/{id}/ping    → activate and emit the lifecycle fact
4. GET  /v1/subscriptions/{id}/health  → confirm one successful delivery
```

## 1. Find the matching key and origin

***

`GET /v1/catalog`

Find the hub-owned `hub.destination.verified` entry. The matching key is `<resource>.<event>`. The producing application is `streaming-hub`.

Each catalog entry exposes `resourceType`, the bare event verb as `eventType`, and the producer's application `topic`. Build the source-free matching key directly as `<resourceType>.<eventType>`. A v3 topic has the form `lerian.streaming.<source>` and repeats across that producer's events.

## 2. Create the subscription

***

`POST /v1/subscriptions`

Send `X-Idempotency` with a unique value.

```json theme={null}
{
  "name": "quick-start",
  "sink_kind": "webhook",
  "endpoint": "https://hooks.example.com/lerian",
  "event_types": ["hub.destination.verified"],
  "origin": "streaming-hub"
}
```

`event_types` contains source-free matching keys, not full CloudEvents types. `origin` pins the subscription to one `ce-source`. Omit it only when you intentionally want the same key from any producer. Both fields are immutable after creation. `schema_major` is optional. `plan_tier` defaults to `standard`.

The `201` response carries the subscription `id` and plaintext `signingSecret`. Save the secret now. No read path returns it.

## 3. Activate the destination and emit the test fact

***

`POST /v1/subscriptions/{id}/ping`

A new webhook starts in `pending_verification`. The ping sends a signed probe through the production delivery path. Your endpoint must answer with `2xx`.

```json theme={null}
{ "outcome": "ok", "statusCode": 200, "errorClass": "" }
```

`outcome: "ok"` moves the subscription to `active`. After that state change commits, the hub attempts to emit `hub.destination.verified` with `ce-source: streaming-hub`. If that best-effort emission succeeds, the subscription you just created matches the fact and receives it. Repeating the ping for an already-active subscription probes the endpoint again but does not re-emit the lifecycle event.

## 4. Confirm the delivery

***

Your endpoint receives a signed `POST` with `X-Lerian-Event-Id`, `X-Lerian-Event-Type`, and `X-Lerian-Delivery-Id`. Verify the HMAC before trusting the body and deduplicate on `X-Lerian-Event-Id`.

Then call `GET /v1/subscriptions/{id}/health`. A fresh `last_success_at` and one success in `delivery_outcomes` confirm the path works end to end.

A `pull` subscription needs no endpoint or ping. Create it with `sink_kind: "pull"`, then read `GET /v1/events?subscription_id=<id>`.

See [Managing subscriptions](/en/platform/streaming-hub/managing-subscriptions) and [Consuming events](/en/platform/streaming-hub/consuming-events) for lifecycle, signatures, retries, and cursors.
