---
title: "Create a webhook subscription for recording-ready events; the signing secret is returned exactly once. Requires the webhooks:manage scope (PATs carry it implicitly) and paid-feature access. Also accepts an app session token (the settings UI)."
method: POST
path: "/v1/webhooks"
---

# Create a webhook subscription for recording-ready events; the signing secret is returned exactly once. Requires the webhooks:manage scope (PATs carry it implicitly) and paid-feature access. Also accepts an app session token (the settings UI).

`POST /v1/webhooks`

## Request

- Base URL: `https://api.usebubbles.com`
- URL: `https://api.usebubbles.com/v1/webhooks`
- Auth: HTTP bearer

## Request body

- CreateWebhookRequest: POST /v1/webhooks request body.
  - `url` string, required: The https receiver URL to POST deliveries to.
  - `events` string[], required: Event types to subscribe to (at least one).
  - `team_id` string: Restrict to one team.
  - `space_id` string: Restrict to one channel.
  - `filters` WebhookSubscriptionFilters: Optional post-match filters on a webhook subscription.
    - `bubble_types` string[]: Only deliver for these bubble types.
    - `only_my_bubbles` boolean: Only deliver for bubbles the subscriber created.

## Response `201`

Created.

- WebhookSubscriptionCreated: POST /v1/webhooks 201 response — the same shape plus the signing secret, shown exactly once.
  - `id` string, required: The subscription id (wh_…).
  - `url` string, required: The receiver URL deliveries are POSTed to.
  - `events` string[], required: Subscribed event types.
  - `team_id` string, nullable, required: Team scope, or null.
  - `space_id` string, nullable, required: Channel scope, or null.
  - `filters` WebhookSubscriptionFilters, required: Optional post-match filters on a webhook subscription.
    - `bubble_types` string[]: Only deliver for these bubble types.
    - `only_my_bubbles` boolean: Only deliver for bubbles the subscriber created.
  - `status` 'active' | 'disabled', required: Delivery status.
  - `created_at` string, required: Creation instant (ISO-8601 UTC).
  - `last_success_at` string, nullable, required: Last successful delivery instant, or null.
  - `last_failure_at` string, nullable, required: Last failed delivery instant, or null.
  - `disabled_at` string, nullable, required: When disabled, or null.
  - `disabled_reason` string, nullable, required: Why disabled, or null.
  - `secret` string, required: The signing secret (whsec_…) for HMAC verification — returned ONCE.

## Other responses

- `400`: A query parameter or request body was malformed (invalid_request).
- `401`: Missing, malformed, or wrong-kind credential (unauthorized / token_revoked / account_deleted).
- `403`: The credential lacks the required scope, or the workspace cannot access paid features (forbidden / pro_plan_required).
- `429`: Rate limit exceeded (rate_limited); see the Retry-After header.
- `500`: An unexpected server error occurred (internal_error).

---

[API](https://skmtc.dev/usebubbles/apis/bubbles-public-api.md) - [All operations](https://skmtc.dev/usebubbles/apis/bubbles-public-api/llms.txt) - [OpenAPI document](https://skmtc.dev/usebubbles/apis/bubbles-public-api/revisions/31570f5d4b05?raw)
