---
title: "Create a webhook subscription"
method: POST
path: "/subscriptions"
tags: ["Subscriptions"]
---

# Create a webhook subscription

`POST /subscriptions`

## Request

- Base URL: `https://api.textla.com/v1`
- URL: `https://api.textla.com/v1/subscriptions`
- Auth: HTTP bearer

Creates a webhook subscription for the authenticated account and mints its signing secret. The secret is returned once, in this response, and is never retrievable again — store it now.

## Request body

- CreateSubscriptionBody
  - `$schema` string, uri: A URL to the JSON Schema for this object.
  - `custom_headers` object: Optional additive request headers applied to each delivery (at most 20; each name is non-empty and at most 256 bytes, each value at most 2048 bytes). Advisory: the delivery sink drops any that would shadow a reserved header or carry an unsafe value. Values are NOT secret — stored in plaintext and returned on read, so do not put credentials here.
  - `target_url` string, uri, required: Absolute https webhook destination.
  - `types` string[], nullable, required: Event types to subscribe to (must be registered types).

## Response `201`

Created

- CreatedSubscription
  - `$schema` string, uri: A URL to the JSON Schema for this object.
  - `account_id` string, required: Account that owns the subscription.
  - `action` string, required: What a matched event does: deliver a signed webhook, or send a notification to a user.
  - `custom_headers` object, nullable, required: Additive request headers applied to each delivery. Advisory: the delivery sink drops any that would shadow a reserved header or carry an unsafe value. Values are NOT secret — stored in plaintext and returned on read, so do not put credentials here.
  - `disabled` boolean, required: A disabled subscription matches nothing.
  - `id` string, required: Service-minted subscription id.
  - `notification` NotificationActionOutput, required
    - `cadence` string
    - `channels` string[], nullable, required: Delivery channels for the notification: at least one of email, in_app.
    - `filters` FilterOutput[], nullable, required: Optional payload predicates; dispatch drops a subscription whose filter does not match the event.
      - `op` string, required: Comparison operator: eq, ne, in, nin, matches or not_matches.
      - `path` string, required: Dotted path into the event payload.
      - `value` unknown, required
    - `recipient_user_id` string, nullable, required: The notified user, resolved to a channel-scoped address at send time.
    - `send_at` string
  - `secret` string, nullable, required: The webhook signing secret (the HMAC-SHA256 key). Shown once, at creation, and never retrievable again — store it now. Null when no signing key is configured for the environment, and always null for a notification subscription.
  - `target_url` string, required: Absolute https webhook destination. Empty for a notification subscription.
  - `types` string[], nullable, required: Event types this subscription wants.

## Other responses

- `400`: Bad Request
- `401`: Unauthorized
- `403`: Forbidden
- `412`: Precondition Failed
- `422`: Unprocessable Entity
- `500`: Internal Server Error
- `502`: Bad Gateway
- `503`: Service Unavailable
- `504`: Gateway Timeout

---

[API](https://skmtc.dev/textla/apis/textla-api.md) - [All operations](https://skmtc.dev/textla/apis/textla-api/llms.txt) - [OpenAPI document](https://skmtc.dev/textla/apis/textla-api/revisions/473f03350bc1?raw)
