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

> ## Agent Instructions
> AhaSend stores all message data in the EU. See /facts.
> The API base URL is https://api.ahasend.com. Send the API key in the Authorization: Bearer header. See /api-reference/authentication.
> Use send.ahasend.com for SMTP in the EU, or send-us.ahasend.com as a US connection point forwarding to the EU. Ports 25, 587 and 2525 use STARTTLS. Port 465 is not supported. See /smtp.
> For send-only integrations, create an API Key v2 under Credentials → Add and scope it to messages:send:{your-domain}. See /send-api/credentials and /api-reference/scopes.

# CLI Examples: Scripts and CI/CD Automation

> Copy-paste AhaSend CLI scripts for order confirmations, password resets, alerts, GitHub Actions deploy notifications, webhook event processing, and load tests.

These AhaSend CLI examples show common email sending and management tasks, including sandbox tests and automation.

Before running the examples, [log in with a full API key](/docs/cli/authentication), use your verified sender domain, and replace `YOUR_RESOURCE_ID` with a resource UUID from your test account. Create any named template, recipient, attachment, or JSON files first. Shell examples use Bash and Python 3 for portable future dates; examples that read JSON with `jq` need jq installed. Sends use sandbox mode.

## Transactional Emails

### Order Confirmation

```bash theme={null}
# Single order confirmation
ahasend messages send --sandbox \
  --from orders@shop.com \
  --to customer@example.com \
  --subject "Order #12345 Confirmed" \
  --html-template order-confirmation.html \
  --global-substitutions order-data.json \
  --attach invoice.pdf \
  --idempotency-key "order-12345"
```

**order-data.json:**

```json theme={null}
{
  "order_id": "12345",
  "customer_name": "John Doe",
  "total": "$149.99",
  "items": [
    {"name": "Product A", "quantity": 2, "price": "$49.99"},
    {"name": "Product B", "quantity": 1, "price": "$50.01"}
  ],
  "delivery_date": "<delivery date>"
}
```

### Password Reset

```bash theme={null}
# Secure password reset email
ahasend messages send --sandbox \
  --from security@app.com \
  --to user@example.com \
  --subject "Password Reset Request" \
  --html-template password-reset.html \
  --global-substitutions reset-data.json \
  --header "X-Priority: high" \
  --track-clicks=false \
  --idempotency-key "reset-user123-$(date +%s)"
```

### Account Verification

```bash theme={null}
# Save global substitutions in a file (the flag takes a path).
cat > verification-data.json <<'JSON'
{"verify_url":"https://example.com/verify?token=TEST_TOKEN"}
JSON
# New user verification
ahasend messages send --sandbox \
  --from noreply@app.com \
  --to newuser@example.com \
  --subject "Verify Your Email Address" \
  --html "<h2>Welcome!</h2><p>Please verify your email by clicking <a href='{{verify_url}}'>here</a></p>" \
  --text "Welcome! Please verify your email by visiting: {{verify_url}}" \
  --global-substitutions verification-data.json \
  --tags signup,verification
```

## Lifecycle Notifications

### Account Activity Digest

```bash theme={null}
#!/bin/bash
# send-newsletter.sh

# Prepare data
TEMPLATE="account-digest.html"
RECIPIENTS="account-users.csv"
SUBJECT="Your Account Activity Digest"

# Send newsletter with tracking
ahasend messages send --sandbox \
  --from newsletter@company.com \
  --recipients "$RECIPIENTS" \
  --subject "$SUBJECT" \
  --html-template "$TEMPLATE" \
  --track-opens=true \
  --track-clicks=true \
  --tags account-digest,transactional \
  --max-concurrency 5 \
  --progress \
  --show-metrics

# Check delivery stats after 1 hour
# Check recent statistics after the sandbox send.
ahasend stats deliverability \
  --from-time 7d \
  --group-by hour
```

### Account Feature Notifications

```bash theme={null}
# Notify account users about an enabled feature
for segment in vip regular trial; do
  echo "Sending to $segment segment..."

  ahasend messages send --sandbox \
    --from notifications@yourdomain.com \
    --recipients "${segment}-users.csv" \
    --subject "{{first_name}}, Your Account Feature Is Ready" \
    --html-template "launch-${segment}.html" \
    --global-substitutions launch-data.json \
    --tags "account-feature,${segment}" \
    --max-concurrency 3 \
    --progress

  sleep 60  # Stagger sends
done
```

### Pending Order Reminder

```bash theme={null}
#!/bin/bash
# pending-order-reminder.sh

# Query pending orders from database
# ... database query logic ...

# Create recipients file
cat > pending-orders.json << 'EOF'
[
  {
    "email": "shopper@example.com",
    "name": "Jane Shopper",
    "substitution_data": {
      "first_name": "Jane",
      "cart_value": "$234.99",
      "items_count": 3,
      "cart_url": "https://shop.com/cart/restore/abc123",
      "discount_code": "COMEBACK10"
    }
  }
]
EOF

# Send recovery emails
ahasend messages send --sandbox \
  --from shop@store.com \
  --recipients pending-orders.json \
  --subject "{{first_name}}, your order is waiting for confirmation" \
  --html-template pending-order.html \
  --schedule "$(python3 -c 'from datetime import datetime,timedelta,timezone; print((datetime.now(timezone.utc)+timedelta(hours=2)).isoformat())')" \
  --tags "pending-order,recovery,automated"
```

## Notification Systems

### Real-Time Alerts

```bash theme={null}
#!/bin/bash
# send-alert.sh

ALERT_TYPE=${1:-info}
ALERT_MESSAGE=${2:-"Docs alert test"}
RECIPIENTS=${3:-test@example.com}

case $ALERT_TYPE in
  critical)
    SUBJECT="🚨 CRITICAL ALERT"
    PRIORITY="high"
    ;;
  warning)
    SUBJECT="⚠️ Warning"
    PRIORITY="normal"
    ;;
  info)
    SUBJECT="ℹ️ Information"
    PRIORITY="low"
    ;;
  *) echo "Use critical, warning, or info"; exit 1 ;;
esac

ahasend messages send --sandbox \
  --from alerts@monitoring.com \
  --to "$RECIPIENTS" \
  --subject "$SUBJECT: $ALERT_MESSAGE" \
  --text "$(printf '%s\n\nTime: %s\nSystem: Test' "$ALERT_MESSAGE" "$(date)")" \
  --header "X-Priority: $PRIORITY" \
  --tags "alert,${ALERT_TYPE},automated"
```

### Daily Reports

```bash theme={null}
#!/bin/bash
# daily-report.sh

# Generate report data
generate_report() {
  echo "{"
  echo "  \"date\": \"$(date +%Y-%m-%d)\","
  echo "  \"total_users\": 15234,"
  echo "  \"new_signups\": 87,"
  echo "  \"revenue\": \"\$12,456.78\","
  echo "  \"top_products\": ["
  echo "    {\"name\": \"Product A\", \"sales\": 234},"
  echo "    {\"name\": \"Product B\", \"sales\": 189}"
  echo "  ]"
  echo "}"
}

# Generate and save report data
generate_report > report-data.json

# Send daily report
ahasend messages send --sandbox \
  --from reports@analytics.com \
  --recipients executives.csv \
  --subject "Daily Report - $(date +%Y-%m-%d)" \
  --html-template daily-report.html \
  --global-substitutions report-data.json \
  --attach "reports/detailed-$(date +%Y%m%d).pdf" \
  --schedule "$(python3 -c 'from datetime import datetime,timedelta,timezone; print((datetime.now(timezone.utc)+timedelta(hours=1)).isoformat())')" \
  --tags "report,daily,automated"
```

## Webhook Integration

### Process Webhook Events

```bash theme={null}
# Run your local, signature-verifying receiver first; see the webhook guide.
ahasend webhooks listen \
  --forward-to http://localhost:8080/webhook \
  --events message.bounced,message.failed
```

The receiver processes `payload.type` and `payload.data.recipient`. CLI listener output is for people, not a line-delimited JSON stream. See [webhook verification and processing](/docs/integrations/webhooks). AhaSend already creates cause-dependent automatic suppressions; see [suppression durations](/docs/bounces#suppression-duration).

### Webhook Testing Pipeline

```bash theme={null}
#!/bin/bash
# test-webhook-integration.sh
set -euo pipefail

# 1. Create test webhook
WEBHOOK_ID=$(ahasend webhooks create --scope global --non-interactive --disabled \
  --url https://example.com/test-webhook \
  --all-events \
  --name "Integration test webhook" \
  --output json | jq -er '.id')

cleanup() {
  ahasend webhooks update "$WEBHOOK_ID" --disable || true
  if [ -n "${LISTENER_PID:-}" ]; then kill "$LISTENER_PID" 2>/dev/null || true; fi
  ahasend webhooks delete "$WEBHOOK_ID" --force
}
trap cleanup EXIT

echo "Created webhook: $WEBHOOK_ID"

# 2. Start listener with forwarding (a local handler must already be running)
ahasend webhooks listen \
  --webhook-id "$WEBHOOK_ID" \
  --forward-to http://localhost:3000/test-webhook \
  --verbose &
LISTENER_PID=$!

# 3. Trigger test events
sleep 2
# Enable only after the listener connects; disabled webhooks emit no events.
ahasend webhooks update "$WEBHOOK_ID" --enable
ahasend webhooks trigger "$WEBHOOK_ID" --all-events

# 4. Send test email
ahasend messages send \
  --from test@example.com \
  --to test@example.com \
  --subject "Webhook Test" \
  --text "Testing webhook integration" \
  --sandbox

# 5. Wait and cleanup
sleep 5
echo "Integration test complete"
```

## Automation Scripts

### CI/CD Email Notifications

```yaml theme={null}
# .github/workflows/deploy-notification.yml
name: Deployment Notification

on:
  deployment_status:

jobs:
  notify:
    if: github.event.deployment_status.state == 'success'
    runs-on: ubuntu-latest
    steps:
      - name: Install AhaSend CLI
        run: |
          wget https://github.com/AhaSend/ahasend-cli/releases/latest/download/ahasend-linux-amd64
          chmod +x ahasend-linux-amd64
          sudo mv ahasend-linux-amd64 /usr/local/bin/ahasend

      - name: Send deployment notification
        env:
          AHASEND_API_KEY: ${{ secrets.AHASEND_API_KEY }}
          AHASEND_ACCOUNT_ID: ${{ secrets.AHASEND_ACCOUNT_ID }}
        run: |
          ahasend --api-key "$AHASEND_API_KEY" --account-id "$AHASEND_ACCOUNT_ID" messages send --sandbox \
            --from ci@company.com \
            --to team@company.com \
            --subject "✅ Deployment Successful: ${{ github.event.deployment.environment }}" \
            --html "<h2>Deployment Complete</h2>
                    <p>Environment: ${{ github.event.deployment.environment }}</p>
                    <p>Commit: ${{ github.sha }}</p>
                    <p>Deployed by: ${{ github.actor }}</p>
                    <p>Time: $(date)</p>" \
            --tags "deployment,ci,notification"
```

### Database Backup Notifications

```bash theme={null}
#!/bin/bash
# backup-notification.sh

# Set BACKUP_SOURCE to your database dump. This small fixture makes the test runnable.
printf '%s
' 'SELECT 1;' > docs-backup-source.sql
BACKUP_SOURCE=docs-backup-source.sql
BACKUP_FILE="backup-$(date +%Y%m%d-%H%M%S).sql.gz"
gzip -c "$BACKUP_SOURCE" > "$BACKUP_FILE"
BACKUP_STATUS=$?
BACKUP_SIZE=$(wc -c < "$BACKUP_FILE")

if [ $BACKUP_STATUS -eq 0 ]; then
  SUBJECT="✅ Backup Successful"
  MESSAGE=$(printf 'Backup completed.\nFile: %s\nBytes: %s' "$BACKUP_FILE" "$BACKUP_SIZE")
  TAGS="backup,success"
else
  SUBJECT="❌ Backup Failed"
  MESSAGE="Database backup failed with error code: $BACKUP_STATUS"
  TAGS="backup,failure,alert"
fi

# Send notification
ahasend messages send --sandbox \
  --from backup@database.com \
  --to admin@company.com \
  --subject "$SUBJECT - $(date +%Y-%m-%d)" \
  --text "$MESSAGE" \
  --tags "$TAGS"
```

### User Onboarding Sequence

```bash theme={null}
#!/bin/bash
# onboarding-sequence.sh

USER_EMAIL=${1:-test@example.com}
USER_NAME=${2:-"Test User"}
# jq safely escapes the name and writes the file expected by the CLI.
jq -n --arg name "$USER_NAME" '{name:$name}' > onboarding-data.json

# Welcome email (immediate)
ahasend messages send --sandbox \
  --from welcome@app.com \
  --to "$USER_EMAIL" \
  --subject "Welcome to Our App, $USER_NAME!" \
  --html-template templates/welcome.html \
  --global-substitutions onboarding-data.json \
  --tags "onboarding,day0,welcome"

# Day 1: Getting started guide
ahasend messages send --sandbox \
  --from tips@app.com \
  --to "$USER_EMAIL" \
  --subject "Getting Started with Our App" \
  --html-template templates/getting-started.html \
  --global-substitutions onboarding-data.json \
  --schedule "$(python3 -c 'from datetime import datetime,timedelta,timezone; print((datetime.now(timezone.utc)+timedelta(days=1)).isoformat())')" \
  --tags "onboarding,day1,guide"

# Day 3: Feature highlights
ahasend messages send --sandbox \
  --from tips@app.com \
  --to "$USER_EMAIL" \
  --subject "Discover Our Best Features" \
  --html-template templates/features.html \
  --global-substitutions onboarding-data.json \
  --schedule "$(python3 -c 'from datetime import datetime,timedelta,timezone; print((datetime.now(timezone.utc)+timedelta(days=3)).isoformat())')" \
  --tags "onboarding,day3,features"

# Day 6: Check-in
ahasend messages send --sandbox \
  --from support@app.com \
  --to "$USER_EMAIL" \
  --subject "How's Everything Going?" \
  --html-template templates/checkin.html \
  --global-substitutions onboarding-data.json \
  --schedule "$(python3 -c 'from datetime import datetime,timedelta,timezone; print((datetime.now(timezone.utc)+timedelta(days=6)).isoformat())')" \
  --tags "onboarding,day6,checkin"

echo "Onboarding sequence scheduled for $USER_EMAIL"
```

## Performance Testing

### Load Testing Script

```bash theme={null}
#!/bin/bash
# load-test.sh

# Configuration
TOTAL_EMAILS=${TOTAL_EMAILS:-10}
CONCURRENCY=10

echo "Starting load test: $TOTAL_EMAILS emails"

# Generate test recipients
echo "email,name,test_id" > test-recipients.csv
for i in $(seq 1 $TOTAL_EMAILS); do
  echo "test${i}@example.com,Test User ${i},TEST-${i}" >> test-recipients.csv
done

# Run load test
START_TIME=$(date +%s)

ahasend messages send \
  --from loadtest@example.com \
  --recipients test-recipients.csv \
  --subject "Load Test {{test_id}}" \
  --text "This is a load test message for {{name}}" \
  --sandbox \
  --max-concurrency $CONCURRENCY \
  --progress \
  --show-metrics \
  --output json > load-test-results.json

END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))

# The CLI does not expose successful_jobs, failed_jobs, or emails_per_sec.
# Inspect the returned JSON and elapsed time without assuming those fields.
cat load-test-results.json
echo "Elapsed: ${DURATION}s; requested recipients: $TOTAL_EMAILS"

# Cleanup
rm test-recipients.csv
```

## Multi-Environment Management

### Environment-Specific Sending

```bash theme={null}
#!/bin/bash
# deploy-emails.sh

ENVIRONMENT=$1

case $ENVIRONMENT in
  production)
    PROFILE="production"
    FROM="noreply@company.com"
    RECIPIENTS="all-users.csv"
    ;;
  staging)
    PROFILE="staging"
    FROM="test@staging.company.com"
    RECIPIENTS="test-users.csv"
    ;;
  development)
    PROFILE="development"
    FROM="dev@dev.company.com"
    RECIPIENTS="dev-team.csv"
    ;;
  *)
    echo "Unknown environment: $ENVIRONMENT"
    exit 1
    ;;
esac

# Send with environment-specific profile
ahasend messages send --sandbox \
  --profile "$PROFILE" \
  --from "$FROM" \
  --recipients "$RECIPIENTS" \
  --subject "[$ENVIRONMENT] System Update" \
  --html-template update-notification.html \
  --tags "update,${ENVIRONMENT}"

echo "Emails sent to $ENVIRONMENT environment"
```

## Next Steps

* [Learn about batch processing](/docs/cli/batch-processing)
* [Configure webhooks](/docs/cli/commands/webhooks)
* [Explore the API](/docs/api-reference)

## Related Guides

* [Install the CLI](/docs/cli/installation), [CLI authentication](/docs/cli/authentication), [REST sending guide](/docs/send-api/send-email).
* [SMTP settings](/docs/smtp), [Node.js SDK](/docs/guides/nodejs-sdk), [Go SDK](/docs/guides/go-sdk).
* [CLI configuration and output](/docs/cli/configuration), [API authentication](/docs/api-reference/authentication), [Permission scopes](/docs/api-reference/scopes).
* [Domain setup](/docs/domains), [Sandbox behavior](/docs/send-api/sandbox), [Tracking setup](/docs/tracking/open-tracking).
* [Suppression durations](/docs/bounces#suppression-duration).


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