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

# Creating a subscription

> Connect an email address, webhook, or queue to a topic and select which messages it receives.

Create subscriptions from their topic. A subscription fixes the protocol and
endpoint; changing either requires a new subscription so the new destination
can be authorized or confirmed.

## Choose the destination

| Protocol | Endpoint | When delivery starts |
| - | - | - |
| `email` | An email address | After the recipient opens the confirmation link. |
| `https` | A public HTTPS URL | After the webhook owner confirms the signed handshake. |
| `http` | A public HTTP URL | After the webhook owner confirms the signed handshake. |
| `queue` | A queue name, UUID, or CRN | Immediately after the queue is authorized. |

Prefer HTTPS for webhooks. The URL scheme must match the protocol. Loopback,
private, and link-local destinations are refused. Redirects are not followed.
Queue endpoints must be in the same account and region and require
`queue:SendMessage` on the destination in addition to
`notifications:Subscribe` on the topic.

## Create the subscription

<Tabs>
  <Tab title="Console">
    1. Open **Notifications**, choose the topic, and open **Subscriptions**.
    2. Select **Subscribe** to open the creation page.
    3. Choose **Protocol** and enter **Endpoint**.
    4. Optionally enter a **Filter policy** and a **Dead-letter queue**.
    5. For a webhook, enable **Raw message delivery** only if your endpoint
       expects the published payload instead of a notification envelope.
    6. Select **Create subscription**.

    For a new webhook subscription, save the displayed signing secret for
    the endpoint operator. After closing that dialog, the console opens the
    subscription page. Email and queue subscriptions open that page directly.
  </Tab>

  <Tab title="API">
    ```http theme={null}
    POST /v1/topics/{topic_id}/subscriptions
    Content-Type: application/json
    ```

    ```json theme={null}
    {
      "protocol": "queue",
      "endpoint": "order-workers",
      "filter_policy": {
        "event": ["order.created", "order.paid"]
      },
      "redrive_policy": {
        "dead_letter_queue": "notification-failures"
      }
    }
    ```

    The response is HTTP `201` with a `subscription` object. Queue endpoints
    are resolved and returned as CRNs. The topic is supplied in the URL and
    is not repeated in the request or subscription response.

    For a webhook, set `protocol` to `https` and `endpoint` to a public URL.
    The first creation also returns `signing_secret`. Repeating a subscription
    to the same topic, protocol, and endpoint returns the existing subscription
    without issuing a new secret; use PATCH to change its settings.
  </Tab>

  <Tab title="CLI">
    Save the JSON request from the API tab as `request-1.json`. Set `TOPIC_ID` to the resource UUID. Use your configured account and region.

    ```bash theme={null}
    basaltic notifications subscription subscribe "$TOPIC_ID" --from-file request-1.json
    ```
  </Tab>

  <Tab title="Go">
    Save the JSON request from the API tab as `request-1.json`. Set `TOPIC_ID` to the resource UUID. Configure credentials, account, and region through the SDK environment variables.

    ```go theme={null}
    package main

    import (
    	"context"
    	"encoding/json"
    	"fmt"
    	"os"

    	basaltic "github.com/basaltic-sh/sdk-go"
    	"github.com/basaltic-sh/sdk-go/notifications"
    )

    func readJSON(path string, value any) error {
    	data, err := os.ReadFile(path)
    	if err != nil {
    		return err
    	}
    	return json.Unmarshal(data, value)
    }

    func run() error {
    	ctx := context.Background()
    	cfg, err := basaltic.NewConfig(ctx)
    	if err != nil {
    		return err
    	}
    	client := notifications.New(cfg)
    	var request1 notifications.SubscribeRequest
    	if err := readJSON("request-1.json", &request1); err != nil {
    		return err
    	}
    	result1, err := client.Subscribe(ctx, os.Getenv("TOPIC_ID"), &request1)
    	if err != nil {
    		return err
    	}
    	fmt.Printf("%+v\n", result1)
    	return nil
    }

    func main() {
    	if err := run(); err != nil {
    		fmt.Fprintln(os.Stderr, err)
    		os.Exit(1)
    	}
    }
    ```
  </Tab>
</Tabs>

## Confirmation

Email and webhook subscriptions start in `pending_confirmation`. Confirmation
links expire after 72 hours by default. Use the subscription's resend action
if a link expires. The endpoint owner follows the received confirmation link;
returning HTTP `200` to the webhook handshake alone does not confirm it.

These recipient links are separate from authenticated API management, so they
are not SDK or CLI operations. A recipient can also use the unsubscribe link
included with a notification. Administrators remove a subscription through
its authenticated DELETE operation.

## Filtering and delivery options

An omitted or empty filter receives every publication. A nonempty policy
matches only [message attributes](/notifications/filter-policies), not fields
inside a JSON message body. Policies apply equally to all protocols.

`raw_message_delivery` is supported only for HTTP and HTTPS. Queue delivery
always uses the notification envelope. `delivery_policy` can override the
topic's retry settings field by field through the API.

A subscription's dead-letter queue receives failed notification delivery
envelopes. This is different from a queue's own redrive policy, which handles
messages a queue consumer repeatedly leases without acknowledging. See
[delivery failures](/notifications/delivery#dead-letter-queues).

## Change or delete a subscription

The API updates mutable settings at
`PATCH /v1/topics/{topic_id}/subscriptions/{subscription_id}`. Omitting
`filter_policy` preserves it; an empty object removes filtering. Protocol and
endpoint remain immutable. Delete the same resource path to stop future
subscription delivery. Read or rotate webhook secrets through the separate
signing-secret actions, each of which has its own permission.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.