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

# Webhook subscriptions

> Create, list, update, and delete webhook subscriptions.

Send an agent's events to your HTTPS endpoint in three steps: create a subscription, store its signing secret, and check the delivery path.

## Before you start

* An [Agent Token](/live/authentication) for the agent.
* An HTTPS receiver you control.
* Event names from the [event catalog](/events).

## Create a subscription

Send the receiver's public HTTPS URL and the event names you want. Relay delivers each event to every active subscription that includes its type, so one subscription per receiver is enough:

<CodeGroup>
  ```bash cURL theme={null}
  curl -sS -A "relay-docs/1.0" -X POST https://api.relayapp.im/v1/webhook-subscriptions \
    -H "Authorization: Bearer $RELAY_AGENT_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "target_url":"https://agent.example/webhooks/relay",
      "subscribed_events":["message.received"]
    }'
  ```

  ```typescript TypeScript SDK theme={null}
  const subscription = await relay.webhookSubscriptions.create({
    target_url: "https://agent.example/webhooks/relay",
    subscribed_events: ["message.received"],
  });
  ```
</CodeGroup>

## Store the signing secret

The create response is the only place Relay ever shows `signing_secret`. Write it to your secret store before anything else and load it as `RELAY_WEBHOOK_SECRET` where your receiver runs. You use it to [verify every incoming request](/webhooks/verify-signatures):

```http theme={null}
HTTP/1.1 201 Created
Content-Type: application/json
```

| Response field      | Meaning                                                    |
| ------------------- | ---------------------------------------------------------- |
| `id`                | Subscription ID for retrieve, update, and delete           |
| `target_url`        | The receiver URL you sent                                  |
| `signing_secret`    | Secret for signature verification, returned only on create |
| `subscribed_events` | Event names this subscription receives                     |
| `is_active`         | Whether matching events are delivered                      |

## Update or delete a subscription

Every later operation takes the subscription ID. An update accepts the same fields as create plus `is_active`, which pauses delivery without losing the secret. Delete the subscription when the receiver goes away, or to switch the agent to WebSocket delivery:

<CodeGroup>
  ```bash cURL theme={null}
  curl -sS -A "relay-docs/1.0" -X DELETE \
    "https://api.relayapp.im/v1/webhook-subscriptions/$SUBSCRIPTION_ID" \
    -H "Authorization: Bearer $RELAY_AGENT_TOKEN"
  ```

  ```typescript TypeScript SDK theme={null}
  await relay.webhookSubscriptions.delete(subscriptionId);
  ```
</CodeGroup>

| Operation | TypeScript SDK                                            | HTTPS                                               |
| --------- | --------------------------------------------------------- | --------------------------------------------------- |
| List      | `relay.webhookSubscriptions.list()`                       | `GET /v1/webhook-subscriptions`                     |
| Retrieve  | `relay.webhookSubscriptions.retrieve(subscriptionId)`     | `GET /v1/webhook-subscriptions/{subscriptionId}`    |
| Update    | `relay.webhookSubscriptions.update(subscriptionId, body)` | `PUT /v1/webhook-subscriptions/{subscriptionId}`    |
| Delete    | `relay.webhookSubscriptions.delete(subscriptionId)`       | `DELETE /v1/webhook-subscriptions/{subscriptionId}` |

## Choose the delivery path

The saved subscriptions decide how the agent receives events; any saved subscription, active or not, puts the agent in webhook mode. The first subscription closes any connected WebSocket. Deleting the last subscription moves pending events back to WebSocket, where they wait for your backend with their `event_id` and body unchanged.

## What you get back

Create answers `201`, delete answers `204` with no body, and the other operations return the subscription:

```http theme={null}
HTTP/1.1 204 No Content
```

## When it fails

A `401` means the Agent Token is missing or revoked, and a `404` means the subscription ID is not one of this agent's. A body that fails validation, such as a URL that is not HTTPS or an event name outside the catalog, is rejected with code `1005`. A lost signing secret cannot be read back; delete the subscription and create a new one.

## Next steps

* [Receive events](/webhooks)
* [Verify signatures](/webhooks/verify-signatures)
* [Handle delivery and retries](/webhooks/delivery)
* [Connect with WebSocket](/websocket)
