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

# Destinations and deliveries

> Configure where events are sent, track delivery status, and handle retries.

## Event destinations

A destination defines where events are delivered. Deck supports multiple destination types so you can receive events wherever your infrastructure already lives.

### Supported destination types

| Type                  | Identifier         | Description                                                                                                        |
| --------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------ |
| **Webhook**           | `webhook`          | HTTP endpoint that receives `POST` requests with [Standard Webhooks](https://www.standardwebhooks.com/) signatures |
| **AWS SQS**           | `aws_sqs`          | Amazon Simple Queue Service queue                                                                                  |
| **AWS Kinesis**       | `aws_kinesis`      | Amazon Kinesis Data Stream                                                                                         |
| **AWS S3**            | `aws_s3`           | Amazon S3 bucket (events stored as JSON objects)                                                                   |
| **GCP Pub/Sub**       | `gcp_pubsub`       | Google Cloud Pub/Sub topic                                                                                         |
| **Azure Service Bus** | `azure_servicebus` | Azure Service Bus queue or topic                                                                                   |
| **RabbitMQ**          | `rabbitmq`         | AMQP-compatible message broker exchange                                                                            |
| **Hookdeck**          | `hookdeck`         | Hookdeck Event Gateway for routing, filtering, and transforming events                                             |

### Creating a destination

To create a destination, send a `POST` to `/v2/event-destinations` with the destination `type`, a type-specific object (keyed by the type name) containing both config fields and credentials, and the events you want to receive.

```json theme={null}
POST /v2/event-destinations

{
  "name": "Production Webhook",
  "type": "webhook",
  "webhook": {
    "url": "https://your-app.com/webhooks/deck"
  },
  "events": ["credential.verified", "task_run.completed", "task_run.failed"]
}
```

Use `"events": ["*"]` to subscribe to everything.

Credential fields go inside the type-keyed object alongside config fields. There is no separate top-level `credentials` block.

***

## Destination configuration reference

Each destination type requires specific configuration fields and credentials.

<Tabs>
  <Tab title="Webhook">
    Delivers events as HTTP `POST` requests to a URL endpoint. Signed using the [Standard Webhooks](https://www.standardwebhooks.com/) specification.

    | Field                    | Type   | Required | Description                                                           |
    | ------------------------ | ------ | -------- | --------------------------------------------------------------------- |
    | `webhook.url`            | string | Yes      | Absolute endpoint URL. HTTP is accepted; use HTTPS for production.    |
    | `webhook.custom_headers` | string | No       | JSON-encoded object of additional headers to include on every request |
    | `webhook.secret`         | string | No       | Signing secret (`whsec_` prefix). Auto-generated if not provided.     |

    ```json theme={null}
    {
      "type": "webhook",
      "webhook": {
        "url": "https://your-app.com/webhooks/deck"
      },
      "events": ["*"]
    }
    ```
  </Tab>

  <Tab title="AWS SQS">
    Delivers events as messages to an Amazon SQS queue. Event metadata is included as message attributes.

    | Field               | Type   | Required | Description                             |
    | ------------------- | ------ | -------- | --------------------------------------- |
    | `aws_sqs.queue_url` | string | Yes      | Full SQS queue URL                      |
    | `aws_sqs.key`       | string | Yes      | AWS Access Key ID                       |
    | `aws_sqs.secret`    | string | Yes      | AWS Secret Access Key                   |
    | `aws_sqs.session`   | string | No       | Session token for temporary credentials |

    **Required IAM permission:** `sqs:SendMessage` on the queue resource.

    ```json theme={null}
    {
      "type": "aws_sqs",
      "aws_sqs": {
        "queue_url": "https://sqs.us-east-1.amazonaws.com/123456789012/deck-events",
        "key": "AKIAIOSFODNN7EXAMPLE",
        "secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
      },
      "events": ["*"]
    }
    ```
  </Tab>

  <Tab title="AWS Kinesis">
    Streams events to an Amazon Kinesis Data Stream. The event ID is used as the partition key.

    | Field                     | Type   | Required | Description                             |
    | ------------------------- | ------ | -------- | --------------------------------------- |
    | `aws_kinesis.stream_name` | string | Yes      | Kinesis stream name                     |
    | `aws_kinesis.region`      | string | Yes      | AWS region (e.g., `us-east-1`)          |
    | `aws_kinesis.key`         | string | Yes      | AWS Access Key ID                       |
    | `aws_kinesis.secret`      | string | Yes      | AWS Secret Access Key                   |
    | `aws_kinesis.session`     | string | No       | Session token for temporary credentials |

    **Required IAM permission:** `kinesis:PutRecord` on the stream resource.

    ```json theme={null}
    {
      "type": "aws_kinesis",
      "aws_kinesis": {
        "stream_name": "deck-events",
        "region": "us-east-1",
        "key": "AKIAIOSFODNN7EXAMPLE",
        "secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
      },
      "events": ["*"]
    }
    ```
  </Tab>

  <Tab title="AWS S3">
    Stores events as JSON objects in an Amazon S3 bucket. Each event becomes a separate object keyed by `{rfc3339_nano_timestamp}_{event_id}.json`.

    | Field                  | Type   | Required | Description                                                                                                                                                                                                                       |
    | ---------------------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `aws_s3.bucket`        | string | Yes      | S3 bucket name                                                                                                                                                                                                                    |
    | `aws_s3.region`        | string | Yes      | AWS region (e.g., `us-east-1`)                                                                                                                                                                                                    |
    | `aws_s3.storage_class` | string | No       | Any [S3 storage class](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-class-intro.html) (e.g., `STANDARD`, `STANDARD_IA`, `INTELLIGENT_TIERING`, `GLACIER_IR`, `GLACIER`, `DEEP_ARCHIVE`). Defaults to `STANDARD`. |
    | `aws_s3.key`           | string | Yes      | AWS Access Key ID                                                                                                                                                                                                                 |
    | `aws_s3.secret`        | string | Yes      | AWS Secret Access Key                                                                                                                                                                                                             |
    | `aws_s3.session`       | string | No       | Session token for temporary credentials                                                                                                                                                                                           |

    **Required IAM permission:** `s3:PutObject` on the bucket resource.

    ```json theme={null}
    {
      "type": "aws_s3",
      "aws_s3": {
        "bucket": "deck-events",
        "region": "us-east-1",
        "key": "AKIAIOSFODNN7EXAMPLE",
        "secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
      },
      "events": ["*"]
    }
    ```
  </Tab>

  <Tab title="GCP Pub/Sub">
    Publishes events to a Google Cloud Pub/Sub topic. Event metadata is included as message attributes.

    | Field                             | Type   | Required | Description                            |
    | --------------------------------- | ------ | -------- | -------------------------------------- |
    | `gcp_pubsub.project_id`           | string | Yes      | GCP project ID                         |
    | `gcp_pubsub.topic`                | string | Yes      | Pub/Sub topic name                     |
    | `gcp_pubsub.service_account_json` | string | Yes      | Service account JSON key (stringified) |

    **Required IAM role:** `roles/pubsub.publisher` on the topic.

    ```json theme={null}
    {
      "type": "gcp_pubsub",
      "gcp_pubsub": {
        "project_id": "my-gcp-project",
        "topic": "deck-events",
        "service_account_json": "{\"type\": \"service_account\", ...}"
      },
      "events": ["*"]
    }
    ```
  </Tab>

  <Tab title="Azure Service Bus">
    Sends events to an Azure Service Bus queue or topic. Event metadata is included as application properties.

    | Field                                | Type   | Required | Description                                          |
    | ------------------------------------ | ------ | -------- | ---------------------------------------------------- |
    | `azure_servicebus.name`              | string | Yes      | Queue or topic name                                  |
    | `azure_servicebus.connection_string` | string | Yes      | Service Bus connection string with `Send` permission |

    ```json theme={null}
    {
      "type": "azure_servicebus",
      "azure_servicebus": {
        "name": "deck-events",
        "connection_string": "Endpoint=sb://my-namespace.servicebus.windows.net/;SharedAccessKeyName=sender;SharedAccessKey=..."
      },
      "events": ["*"]
    }
    ```
  </Tab>

  <Tab title="RabbitMQ">
    Publishes events to a RabbitMQ exchange via AMQP. The event type is used as the routing key. Event metadata is included as message headers.

    | Field                 | Type   | Required | Description                                                                                                                                                       |
    | --------------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `rabbitmq.server_url` | string | Yes      | RabbitMQ host and port (e.g., `rabbitmq.example.com:5672`). A full `amqp://user:pass@host:port` URL is also accepted; credentials and host are extracted from it. |
    | `rabbitmq.exchange`   | string | Yes      | Exchange name                                                                                                                                                     |
    | `rabbitmq.tls`        | string | No       | Enable TLS. Accepts `"true"`, `"on"`, or `"false"`. Defaults to `"false"`.                                                                                        |
    | `rabbitmq.username`   | string | Yes¹     | RabbitMQ username                                                                                                                                                 |
    | `rabbitmq.password`   | string | Yes¹     | RabbitMQ password                                                                                                                                                 |

    ¹ Required unless embedded in `server_url`.

    The exchange must already exist. Deck publishes messages with the event type as the routing key, so you can bind queues using topic patterns.

    ```json theme={null}
    {
      "type": "rabbitmq",
      "rabbitmq": {
        "server_url": "rabbitmq.example.com:5672",
        "exchange": "deck-events",
        "username": "deck",
        "password": "..."
      },
      "events": ["*"]
    }
    ```
  </Tab>

  <Tab title="Hookdeck">
    Routes events through the Hookdeck Event Gateway for advanced routing, filtering, and transformation before delivery. Routing and delivery settings are managed in the Hookdeck dashboard.

    | Field            | Type   | Required | Description           |
    | ---------------- | ------ | -------- | --------------------- |
    | `hookdeck.token` | string | Yes      | Hookdeck source token |

    ```json theme={null}
    {
      "type": "hookdeck",
      "hookdeck": {
        "token": "<HOOKDECK_SOURCE_TOKEN>"
      },
      "events": ["*"]
    }
    ```
  </Tab>
</Tabs>

### Verifying webhook signatures

Deck uses the [Standard Webhooks](https://www.standardwebhooks.com/) specification for webhook signatures. Every delivery includes headers for verification, and a `whsec_` signing secret is generated automatically when you create a webhook destination. You can retrieve it from the Console.

#### Headers sent with each delivery

| Header              | Description                                                     |
| ------------------- | --------------------------------------------------------------- |
| `webhook-id`        | Unique event identifier                                         |
| `webhook-timestamp` | Unix timestamp of when the delivery was sent                    |
| `webhook-signature` | Base64-encoded HMAC-SHA256 signature in `v1,<signature>` format |

#### Verification

Use the official [Standard Webhooks SDK](https://github.com/standard-webhooks/standard-webhooks/tree/main/libraries) to verify signatures. SDKs are available for JavaScript, Python, Go, Ruby, Java, Rust, and more.

<CodeGroup>
  ```javascript Node.js theme={null}
  import { Webhook } from "standardwebhooks";

  const wh = new Webhook(process.env.DECK_WEBHOOK_SECRET);

  app.post("/webhooks/deck", (req, res) => {
    try {
      const payload = wh.verify(req.rawBody, req.headers);
      await processEvent(payload);
      res.status(200).json({ received: true });
    } catch (err) {
      res.status(401).json({ error: "Invalid signature" });
    }
  });
  ```

  ```python Python theme={null}
  from standardwebhooks.webhooks import Webhook

  wh = Webhook(os.environ["DECK_WEBHOOK_SECRET"])

  def handle_webhook(request):
      try:
          payload = wh.verify(request.body, request.headers)
          process_event(payload)
          return {"received": True}, 200
      except Exception:
          return {"error": "Invalid signature"}, 401
  ```

  ```go Go theme={null}
  import svix "github.com/standard-webhooks/standard-webhooks/libraries/go"

  func handleWebhook(w http.ResponseWriter, r *http.Request) {
  	wh, _ := svix.NewWebhook(os.Getenv("DECK_WEBHOOK_SECRET"))

  	body, _ := io.ReadAll(r.Body)
  	err := wh.Verify(body, r.Header)
  	if err != nil {
  		http.Error(w, "Invalid signature", http.StatusUnauthorized)
  		return
  	}

  	processEvent(body)
  	w.WriteHeader(http.StatusOK)
  }
  ```
</CodeGroup>

#### Secret rotation

When you rotate your signing secret, Deck keeps the previous secret valid for 24 hours. During this window, verify against both secrets so you can roll over without downtime.

### Destination statuses

| Status                 | Meaning                                                                                             |
| ---------------------- | --------------------------------------------------------------------------------------------------- |
| `pending_verification` | Deck is waiting for a successful response from your endpoint                                        |
| `active`               | Receiving deliveries                                                                                |
| `inactive`             | Disabled. Set via `PATCH /v2/event-destinations/{id}` with `status: "active"` to resume deliveries. |

## Deliveries

Each delivery is tracked independently. For webhooks, a delivery fails when the destination does not return a `2xx` response within **5 seconds**.

Failed deliveries are retried up to **10 times** with exponential backoff (base 2, starting at 30 seconds).

Persistent failures don't auto-disable a destination. List failed deliveries with `GET /v2/event-destinations/{id}/event-deliveries?status=failure` to inspect them.

### Delivery statuses

| Status    | Meaning                      |
| --------- | ---------------------------- |
| `success` | Delivered and acknowledged   |
| `failure` | All retry attempts exhausted |
