Source: https://dinakar-pageloop-knowledge-base.docs-staging.pageloop.ai/guides/sending-your-first-event

# Sending your first event

# Sending your first event

This guide goes further than the [Quickstart](/quickstart): you will create a real
subscription, publish to it, and read the delivery log.

1. **Create a subscription**

   A subscription binds an event-type pattern to a URL.
   ```bash
   curl https://api.kestrel.dev/v1/subscriptions \
     -H "Authorization: Bearer $KESTREL_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{
       "url": "https://example.com/webhooks/kestrel",
       "eventTypes": ["invoice.*"],
       "description": "Billing service"
     }'
   ```
   The response includes `signingSecret`. It is shown once — store it now.
2. **Publish an event**
   ```bash
   curl https://api.kestrel.dev/v1/events \
     -H "Authorization: Bearer $KESTREL_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{ "type": "invoice.paid", "payload": { "invoiceId": "in_1024" } }'
   ```
3. **Check the delivery**
   ```bash
   curl "https://api.kestrel.dev/v1/deliveries?eventId=evt_01HZX9K2QW" \
     -H "Authorization: Bearer $KESTREL_API_KEY"
   ```
   A successful delivery looks like this:
   ```json
   {
     "data": [
       {
         "id": "dlv_01HZX9M4TT",
         "eventId": "evt_01HZX9K2QW",
         "subscriptionId": "sub_8213",
         "status": "succeeded",
         "attempts": 1,
         "responseStatus": 200,
         "durationMs": 143
       }
     ]
   }
   ```

## Wildcards

`eventTypes` accepts a `*` in the last segment only.

| Pattern          | Matches                          | Does not match       |
| ---------------- | -------------------------------- | -------------------- |
| `invoice.*`      | `invoice.paid`, `invoice.voided` | `invoice.line.added` |
| `invoice.line.*` | `invoice.line.added`             | `invoice.paid`       |
| `*`              | every event type                 | —                    |

> [!INFO]
>
> A subscription may list up to 25 patterns. Beyond that, create a second subscription
> pointing at the same URL.

## Local development

Kestrel cannot reach `localhost`, so use a tunnel and point the subscription at the public
URL it gives you. Delete the subscription when you are done — disabled subscriptions still
count against your plan's subscription limit.

Next: [Handling failures](/guides/handling-failures).
