Manage Connections with the Hookdeck CLI

View as Markdown

The Hookdeck CLI (v1.2.0+) provides powerful commands for programmatic Connection management, enabling Infrastructure as Code (IaC), CI/CD integration, and production automation workflows. This guide explains how to use the CLI to create, update, pause, and manage connections efficiently.

Requirements: Hookdeck CLI v1.2.0 or later

  npm install hookdeck-cli -g
  
  
  yarn global add hookdeck-cli
  
  
    brew install hookdeck/hookdeck/hookdeck
    
    
  1.     scoop bucket add hookdeck https://github.com/hookdeck/scoop-hookdeck-cli.git
        
        
  2.   scoop install hookdeck
      
      
  1. Download the latest release's tar.gz file.

  2.     tar -xvf hookdeck_X.X.X_linux_x86_64.tar.gz
        
        
  3.   ./hookdeck
      
      

Key Concepts

Before diving into workflows, it's important to understand connection states and their implications.

Connection States

StateDescriptionEvent BehaviorUse Case
ActiveConnection is operationalEvents are delivered immediatelyNormal operation
PausedConnection temporarily haltedEvents are queued for later deliveryMaintenance windows, debugging
DisabledConnection is turned offNew events are rejected, pending events cancelledPermanent deactivation

Event Queue Behavior

When a Connection is paused, Events are queued rather than delivered. Understanding retention periods is critical:

PlanRetention PeriodWhat Happens After
Free3 daysEvents removed from queue
Team7 daysEvents removed from queue
Growth30 daysEvents removed from queue

Important: Events that exceed the retention period while queued will be removed from the queue and will not be delivered.

State Transition Consequences

Understanding what happens when transitioning between states helps prevent data loss:

From StateTo StateEvent Impact
ActivePausedNew events queued, existing deliveries continue
PausedActiveAll queued events process immediately
ActiveDisabledPending events cancelled (non-recoverable)
DisabledActiveNo queued events to process
AnyDeletedAll pending events cancelled (permanent)

Practical Workflows

Infrastructure as Code with Dry-Run

Infrastructure as Code (IaC) is the practice of managing and provisioning infrastructure through code rather than manual processes, enabling version control, repeatability, and automation. The upsert command with --dry-run enables safe, idempotent deployments. This is the recommended approach for production environments.

Important: Production environments should always configure source authentication (webhook signature verification) and destination authentication.

# Step 1: Preview changes without applying them
# Configure Stripe webhook signature verification and destination auth
hookdeck connection upsert production-webhooks \
  --source-name stripe --source-type STRIPE \
  --source-config '{"verification":{"type":"STRIPE","configs":{"webhook_secret_key":"whsec_..."}}}' \
  --destination-name my-api --destination-type HTTP \
  --destination-url https://api.example.com/webhooks \
  --destination-auth-method bearer \
  --destination-bearer-token "$API_BEARER_TOKEN" \
  --dry-run

# Review the output to verify changes

# Step 2: Apply the changes (remove --dry-run)
hookdeck connection upsert production-webhooks \
  --source-name stripe --source-type STRIPE \
  --source-config '{"verification":{"type":"STRIPE","configs":{"webhook_secret_key":"'"$STRIPE_WEBHOOK_SECRET"'"}}}' \
  --destination-name my-api --destination-type HTTP \
  --destination-url https://api.example.com/webhooks \
  --destination-auth-method bearer \
  --destination-bearer-token "$API_BEARER_TOKEN"

Note: The Stripe webhook secret (starts with whsec_) is obtained from your Stripe dashboard when creating a webhook event destination.

Output example:

$ hookdeck connection upsert production-webhooks --dry-run
=== DRY RUN MODE ===

Operation: UPDATE
Connection: production-webhooks (ID: web_abc123)

Changes to be applied:
  • Source: stripe (by name)
  • Destination: my-api → my-api (inline creation)

=== DRY RUN COMPLETE ===
No changes were made. Remove --dry-run to apply these changes.

Blue-Green Deployment Pattern

Blue-green deployment is a release strategy that maintains two identical production environments (blue and green), allowing you to switch traffic between them for zero-downtime deployments and easy rollbacks. This script demonstrates a zero-downtime deployment strategy using connection management:

#!/bin/bash
# blue-green-deployment.sh
# Switch traffic between blue and green environments

set -e

BLUE_CONNECTION="production-blue"
GREEN_CONNECTION="production-green"
SOURCE="stripe"
BLUE_URL="https://blue.api.example.com/webhooks"
GREEN_URL="https://green.api.example.com/webhooks"

echo "🚀 Starting blue-green deployment..."

# Step 1: Ensure green environment is ready
echo "Deploying to green environment..."
hookdeck connection upsert $GREEN_CONNECTION \
  --source-name $SOURCE --source-type WEBHOOK \
  --destination-name green-api --destination-type HTTP \
  --destination-url $GREEN_URL

# Step 2: Health check (implement your own health check logic)
echo "Running health checks on green environment..."
# curl -f $GREEN_URL/health || exit 1

# Step 3: Pause blue to queue new events
echo "Pausing blue environment..."
hookdeck connection pause $BLUE_CONNECTION

# Step 4: Activate green
echo "Activating green environment..."
hookdeck connection unpause $GREEN_CONNECTION

# Step 5: Wait for blue to finish processing
echo "Waiting for blue to finish processing..."
sleep 10

# Step 6: Disable blue completely
echo "Disabling blue environment..."
hookdeck connection disable $BLUE_CONNECTION

echo "✅ Deployment complete. Green is now active."

Maintenance Window Management

A maintenance window is a scheduled period during which you perform updates or repairs on your systems. By pausing connections during maintenance, you can queue incoming events safely and process them once your systems are back online. Manage planned maintenance by pausing connections:

#!/bin/bash
# maintenance-window.sh
# Pause connections during maintenance, then resume

CONNECTION_ID="conn_abc123"  # Use the connection ID

echo "🔧 Starting maintenance window..."

# Pause the connection
hookdeck connection pause $CONNECTION_ID
echo "✓ Connection paused - events will be queued"

# Perform maintenance tasks
echo "Performing maintenance tasks..."
# Your maintenance commands here
sleep 60  # Simulated maintenance

# Resume the connection
hookdeck connection unpause $CONNECTION_ID
echo "✅ Maintenance complete. Connection resumed."
echo "ℹ️ Queued events will now be processed"

Note: Monitor your queue via the Hookdeck dashboard to track queued events during the maintenance window.

Multi-Environment Setup

Managing multiple environments (development, staging, production) with consistent configurations is essential for reliable deployments. In Hookdeck, environments are represented by separate Projects , each with its own API key and isolated configuration.

Best Practice: Create separate projects for each environment (e.g., "My App - Development", "My App - Staging", "My App - Production").

This script demonstrates configuring connections across multiple projects:

#!/bin/bash
# multi-environment-setup.sh
# Configure connections across multiple Hookdeck projects

# Each environment uses its own project and API key
declare -A ENV_KEYS=(
  ["dev"]="$DEV_API_KEY"
  ["staging"]="$STAGING_API_KEY"
  ["production"]="$PRODUCTION_API_KEY"
)

SOURCE="github"

for ENV in "${!ENV_KEYS[@]}"; do
  echo "Configuring $ENV environment..."
  
  # Authenticate with environment-specific project using CI command
  hookdeck ci --api-key "${ENV_KEYS[$ENV]}"
  
  # Construct environment-specific destination URL
  DEST_URL="https://$ENV.api.example.com/webhooks"
  
  # Production environments should have destination authentication
  # Use source types with built-in verification (STRIPE, GITHUB, etc.)
  if [ "$ENV" = "production" ]; then
    # Preview with authentication
    hookdeck connection upsert "$ENV-webhooks" \
      --source-name $SOURCE --source-type GITHUB \
      --destination-name "$ENV-api" --destination-type HTTP \
      --destination-url $DEST_URL \
      --destination-auth-method bearer \
      --destination-bearer-token "$PRODUCTION_BEARER_TOKEN" \
      --dry-run
    
    # Apply if approved
    read -p "Apply changes to $ENV? (y/n) " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
      hookdeck connection upsert "$ENV-webhooks" \
        --source-name $SOURCE --source-type GITHUB \
        --destination-name "$ENV-api" --destination-type HTTP \
        --destination-url $DEST_URL \
        --destination-auth-method bearer \
        --destination-bearer-token "$PRODUCTION_BEARER_TOKEN"
      echo "✓ $ENV environment configured with source verification and destination authentication"
    fi
  else
    # Non-production can be configured without auth (for local dev)
    hookdeck connection upsert "$ENV-webhooks" \
      --source-name $SOURCE --source-type WEBHOOK \
      --destination-name "$ENV-api" --destination-type HTTP \
      --destination-url $DEST_URL \
      --dry-run
    
    read -p "Apply changes to $ENV? (y/n) " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
      hookdeck connection upsert "$ENV-webhooks" \
        --source-name $SOURCE --source-type WEBHOOK \
        --destination-name "$ENV-api" --destination-type HTTP \
        --destination-url $DEST_URL
      echo "✓ $ENV environment configured"
    fi
  fi
done

Projects Documentation ->

Learn about using projects to manage environments and access control.

GitHub Actions CI/CD Integration

Continuous Integration and Continuous Deployment (CI/CD) automates your deployment process, ensuring changes are tested and deployed consistently. Integrating Hookdeck CLI into your CI/CD pipeline enables automatic connection updates when you push code changes. Complete workflow for deploying connection configurations via GitHub Actions:

# .github/workflows/deploy-connections.yml
name: Deploy Hookdeck Connections

on:
  push:
    branches:
      - main
    paths:
      - 'hookdeck/connections/**'

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Install Hookdeck CLI
        run: |
          curl -fsSL https://cli.hookdeck.com/install.sh | sh
          echo "$HOME/.hookdeck/bin" >> $GITHUB_PATH

      - name: Authenticate with Hookdeck
        env:
          HOOKDECK_API_KEY: ${{ secrets.HOOKDECK_API_KEY }}
        run: |
          hookdeck ci --api-key $HOOKDECK_API_KEY

      - name: Validate configuration (dry-run)
        run: |
          hookdeck connection upsert production-webhooks \
            --source-name stripe --source-type STRIPE \
            --source-webhook-secret ${{ secrets.STRIPE_WEBHOOK_SECRET }} \
            --destination-name production-api --destination-type HTTP \
            --destination-url ${{ vars.WEBHOOK_URL }} \
            --destination-auth-method bearer \
            --destination-bearer-token ${{ secrets.API_BEARER_TOKEN }} \
            --dry-run

      - name: Deploy to production
        if: github.ref == 'refs/heads/main'
        run: |
          hookdeck connection upsert production-webhooks \
            --source-name stripe --source-type STRIPE \
            --source-webhook-secret ${{ secrets.STRIPE_WEBHOOK_SECRET }} \
            --destination-name production-api --destination-type HTTP \
            --destination-url ${{ vars.WEBHOOK_URL }} \
            --destination-auth-method bearer \
            --destination-bearer-token ${{ secrets.API_BEARER_TOKEN }}

      - name: Verify deployment
        run: |
          hookdeck connection list --name production-webhooks

GitLab CI/CD Integration

GitLab CI/CD provides similar automation capabilities to GitHub Actions, with native integration into GitLab repositories. This example demonstrates how to deploy Hookdeck connection configurations using GitLab's pipeline syntax. Similar workflow for GitLab CI/CD pipelines:

# .gitlab-ci.yml
stages:
  - validate
  - deploy

variables:
  CONNECTION_NAME: "production-webhooks"
  SOURCE_NAME: "stripe"

validate:
  stage: validate
  image: ubuntu:latest
  before_script:
    - apt-get update && apt-get install -y curl jq npm
    - npm install hookdeck-cli -g
    - hookdeck ci --api-key $HOOKDECK_API_KEY
  script:
    - |
      hookdeck connection upsert $CONNECTION_NAME \
        --source-name $SOURCE_NAME --source-type STRIPE \
        --source-webhook-secret $STRIPE_WEBHOOK_SECRET \
        --destination-name production-api --destination-type HTTP \
        --destination-url $WEBHOOK_URL \
        --destination-auth-method bearer \
        --destination-bearer-token $API_BEARER_TOKEN \
        --dry-run

deploy_production:
  stage: deploy
  image: ubuntu:latest
  only:
    - main
  before_script:
    - apt-get update && apt-get install -y curl npm
    - npm install hookdeck-cli -g
    - hookdeck ci --api-key $HOOKDECK_API_KEY
  script:
    - |
      hookdeck connection upsert $CONNECTION_NAME \
        --source-name $SOURCE_NAME --source-type STRIPE \
        --source-webhook-secret $STRIPE_WEBHOOK_SECRET \
        --destination-name production-api --destination-type HTTP \
        --destination-url $WEBHOOK_URL \
        --destination-auth-method bearer \
        --destination-bearer-token $API_BEARER_TOKEN
    - hookdeck connection list --name $CONNECTION_NAME

Edge Cases & Gotchas

Connection vs Source Operations

Understanding the difference between connection-level and source-level operations is crucial:

# Disable a SINGLE connection (affects only this connection)
hookdeck connection disable my-connection

# Disable an ENTIRE source (affects ALL connections using this source)
hookdeck source disable my-source

Impact example:

  • Source "stripe" has 3 connections: production, staging, dev
  • Disabling the source disables all 3 connections
  • Disabling production connection only affects that one connection

CLI Destination Limitations

CLI destinations (created by hookdeck listen) have certain limitations:

# This works with HTTP destinations
hookdeck connection pause production-webhooks

# This may have limitations with CLI destinations
hookdeck connection pause cli-12345
# ⚠️ CLI destinations are designed for local development
# For production use, use HTTP destinations

Workaround: For local development control, use hookdeck listen with connection name parameter:

hookdeck listen 3000 stripe --connection-name my-local-dev

Connection Deletion is Permanent

# Delete a connection (PERMANENT - cannot be undone)
hookdeck connection delete my-connection

# Best practice: Disable instead of delete if you might need it later
hookdeck connection disable my-connection

Recovery: If you accidentally delete a connection, you must recreate it from scratch. There is no undo operation.

Queue Time Limits

Events queued beyond retention periods will be removed from the queue and will not be delivered:

Tip: Check queue status via the Hookdeck dashboard before resuming a paused connection. Events that exceed the retention period for your plan (see Event Queue Behavior) will be removed from the queue.

Best Practices

Always Use --dry-run in Production

# ✅ Good: Preview changes first
hookdeck connection upsert production \
  --source-name stripe --source-type STRIPE \
  --destination-name api --destination-type HTTP \
  --destination-url $API_URL \
  --dry-run

# Then apply after review (remove --dry-run)
hookdeck connection upsert production \
  --source-name stripe --source-type STRIPE \
  --destination-name api --destination-type HTTP \
  --destination-url $API_URL

# ❌ Bad: Direct changes without preview
hookdeck connection upsert production \
  --source-name stripe --source-type STRIPE \
  --destination-name api --destination-type HTTP \
  --destination-url $API_URL

Monitor Paused Connections

Monitor paused connections via the Hookdeck dashboard:

  • Check the Connections page for paused connection indicators
  • View queued event counts in the dashboard
  • Set up alerts for long-running paused states

Note: Queue monitoring is not available via the CLI. Use the dashboard or API for detailed queue metrics.

Use Descriptive Connection Names

# ✅ Good: Descriptive, environment-specific names
hookdeck connection create production-stripe-webhooks
hookdeck connection create staging-github-events
hookdeck connection create dev-payment-notifications

# ❌ Bad: Generic, unclear names
hookdeck connection create conn1
hookdeck connection create test
hookdeck connection create webhook

Version Control Configuration Files

# Store connection configurations as scripts in version control
# deploy-production.sh
hookdeck connection upsert production-stripe \
  --source-name stripe --source-type STRIPE \
  --destination-name api --destination-type HTTP \
  --destination-url $API_URL \
  --destination-rate-limit 100 \
  --destination-rate-limit-period second

# Version control the deployment script
git add deploy-production.sh
git commit -m "Update production connection config"

Set Up Monitoring for Connection States

Monitor connection states through the Hookdeck dashboard:

  • Set up issue triggers to alert on connection failures
  • Use the Connections page to view paused/disabled status
  • Integrate with your monitoring tools via the Hookdeck API

For programmatic monitoring, use the Hookdeck API to query connection states and integrate with your alerting systems.

Troubleshooting

Common Error: Connection Not Found

$ hookdeck connection pause my-connection
Error: Connection 'my-connection' not found

Solution:

# List all connections to verify the name
hookdeck connection list

# Use the exact connection ID or name
hookdeck connection pause conn_abc123

Common Error: Unable to Delete Active Connection

$ hookdeck connection delete my-connection
Error: Cannot delete connection with pending events

Solution:

# First, disable the connection to stop new events
hookdeck connection disable my-connection

# Wait for pending events to process or fail
# Then delete
hookdeck connection delete my-connection

Recovering from Accidental Deletion

If you accidentally delete a connection, you must recreate it:

# Retrieve configuration from version control or backup
# Recreate the connection
hookdeck connection create \
  --name my-connection \
  --source-name stripe --source-type STRIPE \
  --destination-name api --destination-type HTTP \
  --destination-url https://api.example.com/webhooks

Prevention: Always use --disable instead of --delete unless you're certain.

Debugging Connection State Issues

# Get detailed connection information
# Use connection ID (not name for 'get' command)
hookdeck connection get conn_abc123 --output json

# List connections to find the ID
hookdeck connection list --name my-connection

# View connection details in the output

API Rate Limit Considerations

When performing bulk operations:

# ❌ Bad: May hit rate limits
for CONN in $(cat connections.txt); do
  hookdeck connection upsert $CONN \
    --source-name stripe --source-type STRIPE \
    --destination-name api --destination-type HTTP \
    --destination-url https://api.example.com
done

# ✅ Good: Add delays between operations
for CONN in $(cat connections.txt); do
  hookdeck connection upsert $CONN \
    --source-name stripe --source-type STRIPE \
    --destination-name api --destination-type HTTP \
    --destination-url https://api.example.com
  sleep 1  # Prevent rate limiting
done

Production Deployment Checklist

Before deploying connection changes to production:

  • [ ] Run with --dry-run first
  • [ ] Check for pending events before disable/delete operations
  • [ ] Document connection names in team wiki or runbook
  • [ ] Set up monitoring for connection states
  • [ ] Test in staging environment first
  • [ ] Have rollback plan ready
  • [ ] Verify queue sizes after resuming paused connections
  • [ ] Confirm retention period compliance for long pauses
  • [ ] Review logs for any errors or warnings
  • [ ] Notify team of planned changes

To learn more about connection management and related concepts:

Connections Documentation ->

Detailed information on managing your connections via the dashboard.

Pause & Resume Connections ->

Learn about pausing and resuming connections via the dashboard.