webhook-automation

Build and manage webhook-based integrations for real-time event processing and API connections

INSTALLATION
npx skills add https://github.com/claude-office-skills/skills --skill webhook-automation
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

Webhook Automation

Comprehensive skill for building webhook-based integrations and real-time event processing.

Core Concepts

Webhook Architecture

WEBHOOK FLOW:

┌─────────────┐     ┌─────────────┐     ┌─────────────┐

│   Source    │────▶│   Webhook   │────▶│   Handler   │

│   System    │     │   Endpoint  │     │   Logic     │

└─────────────┘     └─────────────┘     └──────┬──────┘

                                               │

                    ┌──────────────────────────┼───────┐

                    │                          │       │

                    ▼                          ▼       ▼

              ┌──────────┐              ┌──────────┐ ┌──────────┐

              │  Action  │              │  Action  │ │  Action  │

              │    A     │              │    B     │ │    C     │

              └──────────┘              └──────────┘ └──────────┘

Webhook Types

webhook_types:

  incoming:

    description: "Receive events from external services"

    use_cases:

      - Payment notifications (Stripe, PayPal)

      - Form submissions

      - CRM updates

      - CI/CD events

  outgoing:

    description: "Send events to external services"

    use_cases:

      - Notify external systems

      - Trigger workflows

      - Sync data

      - Alert integrations

Webhook Endpoint Setup

Basic Endpoint

webhook_endpoint:

  url: "https://api.example.com/webhooks/incoming"

  method: POST

  authentication:

    type: signature

    header: "X-Signature-256"

    algorithm: "HMAC-SHA256"

    secret: "${WEBHOOK_SECRET}"

  validation:

    required_headers:

      - "Content-Type"

      - "X-Request-ID"

    content_types:

      - "application/json"

      - "application/x-www-form-urlencoded"

  response:

    success:

      status: 200

      body: { "received": true }

    error:

      status: 400

      body: { "error": "Invalid payload" }

Signature Verification

// Verify webhook signature

function verifySignature(payload, signature, secret) {

  const hmac = crypto.createHmac('sha256', secret);

  const digest = 'sha256=' + hmac.update(payload).digest('hex');

  return crypto.timingSafeEqual(

    Buffer.from(digest),

    Buffer.from(signature)

  );

}

// Usage

app.post('/webhook', (req, res) => {

  const signature = req.headers['x-signature-256'];

  const payload = JSON.stringify(req.body);

  if (!verifySignature(payload, signature, process.env.WEBHOOK_SECRET)) {

    return res.status(401).json({ error: 'Invalid signature' });

  }

  // Process webhook...

  processWebhook(req.body);

  res.status(200).json({ received: true });

});

Event Processing

Event Router

event_router:

  routes:

    - event_type: "payment.succeeded"

      handler: processPayment

      actions:

        - update_order_status

        - send_confirmation_email

        - notify_fulfillment

    - event_type: "customer.created"

      handler: processNewCustomer

      actions:

        - create_crm_contact

        - send_welcome_email

        - assign_to_sales

    - event_type: "subscription.cancelled"

      handler: processChurn

      actions:

        - update_subscription_status

        - trigger_retention_flow

        - notify_customer_success

    - event_type: "*"

      handler: logUnhandled

      actions:

        - log_to_monitoring

Payload Transformation

transformations:

  - name: stripe_to_internal

    source: stripe_webhook

    target: internal_order

    mapping:

      id: "data.object.id"

      amount: "data.object.amount / 100"  # Cents to dollars

      currency: "data.object.currency | uppercase"

      customer_email: "data.object.receipt_email"

      created_at: "data.object.created | timestamp"

      metadata: "data.object.metadata"

  - name: github_to_slack

    source: github_webhook

    target: slack_message

    mapping:

      text: |

        *{{action | capitalize}} {{repository.name}}*

        {{#if pull_request}}

        PR: {{pull_request.title}}

        By: {{pull_request.user.login}}

        {{/if}}

      channel: "{{repository.name}}-notifications"

Common Integrations

Stripe Webhooks

stripe_webhooks:

  endpoint_secret: "${STRIPE_WEBHOOK_SECRET}"

  events:

    - type: "checkout.session.completed"

      handler: |

        async function(event) {

          const session = event.data.object;

          await fulfillOrder(session);

          await sendReceipt(session.customer_email);

        }

    - type: "invoice.payment_failed"

      handler: |

        async function(event) {

          const invoice = event.data.object;

          await notifyCustomer(invoice);

          await createDunningTask(invoice);

        }

    - type: "customer.subscription.updated"

      handler: |

        async function(event) {

          const subscription = event.data.object;

          await syncSubscriptionStatus(subscription);

        }

GitHub Webhooks

github_webhooks:

  secret: "${GITHUB_WEBHOOK_SECRET}"

  events:

    - type: "push"

      branches: ["main", "develop"]

      handler: |

        async function(event) {

          await triggerCI(event.repository, event.ref);

          await notifyTeam(event.commits);

        }

    - type: "pull_request"

      actions: ["opened", "synchronize"]

      handler: |

        async function(event) {

          await runTests(event.pull_request);

          await requestReview(event.pull_request);

        }

    - type: "issues"

      actions: ["opened"]

      handler: |

        async function(event) {

          await triageIssue(event.issue);

          await assignOwner(event.issue);

        }

Slack Webhooks

slack_webhooks:

  incoming:

    # Receive slash commands and interactions

    signing_secret: "${SLACK_SIGNING_SECRET}"

    events:

      - type: "slash_command"

        command: "/deploy"

        handler: handleDeployCommand

      - type: "interactive_message"

        callback_id: "approval_*"

        handler: handleApproval

  outgoing:

    # Send messages to Slack

    webhook_url: "${SLACK_WEBHOOK_URL}"

    templates:

      alert:

        blocks:

          - type: section

            text: "🚨 *Alert:* {{message}}"

          - type: context

            elements:

              - type: mrkdwn

                text: "Source: {{source}} | Time: {{timestamp}}"

Error Handling

Retry Strategy

retry_config:

  enabled: true

  policy:

    max_attempts: 5

    initial_delay: 1000  # ms

    max_delay: 60000  # ms

    backoff_multiplier: 2

  retry_on:

    status_codes: [408, 429, 500, 502, 503, 504]

    exceptions: ["ECONNRESET", "ETIMEDOUT"]

  dead_letter:

    enabled: true

    destination: "failed_webhooks_queue"

    retention_days: 7

Error Logging

error_handling:

  logging:

    level: error

    include:

      - request_id

      - event_type

      - payload_hash

      - error_message

      - stack_trace

      - retry_count

  alerting:

    on_failure:

      - type: slack

        channel: "#webhook-alerts"

        threshold: 5  # failures per minute

    on_dead_letter:

      - type: pagerduty

        severity: warning

Webhook Testing

Test Payload Generator

test_payloads:

  stripe_payment:

    type: "checkout.session.completed"

    data:

      object:

        id: "cs_test_123"

        amount_total: 2000

        currency: "usd"

        customer_email: "test@example.com"

        payment_status: "paid"

  github_push:

    ref: "refs/heads/main"

    repository:

      name: "my-repo"

      full_name: "org/my-repo"

    commits:

      - id: "abc123"

        message: "Test commit"

        author:

          name: "Test User"

Webhook Debugging

debugging:

  tools:

    - name: "Request Bin"

      url: "https://requestbin.com"

      use: "Capture and inspect payloads"

    - name: "ngrok"

      command: "ngrok http 3000"

      use: "Expose local server"

    - name: "Webhook.site"

      url: "https://webhook.site"

      use: "Quick webhook testing"

  logging:

    enabled: true

    log_payloads: true

    log_headers: true

    mask_secrets: true

Security Best Practices

Security Checklist

security:

  authentication:

    - Verify webhook signatures

    - Use HTTPS only

    - Rotate secrets regularly

  validation:

    - Validate payload schema

    - Check timestamp freshness

    - Verify source IP if possible

  processing:

    - Idempotent handlers

    - Rate limiting

    - Timeout protection

  storage:

    - Encrypt secrets at rest

    - Audit logging

    - No sensitive data in URLs

IP Allowlisting

ip_allowlist:

  stripe:

    - "3.18.12.63"

    - "3.130.192.231"

    # ... more IPs

  github:

    - "192.30.252.0/22"

    - "185.199.108.0/22"

    # ... more ranges

  slack:

    - "54.159.240.0/22"

    # ... more ranges

Monitoring

Metrics Dashboard

WEBHOOK METRICS - LAST 24 HOURS

═══════════════════════════════════════

Received:      12,456

Processed:     12,398 (99.5%)

Failed:           58 (0.5%)

Retried:         123

BY SOURCE:

Stripe     ████████████░░░░ 5,230

GitHub     ██████████░░░░░░ 4,120

Slack      ████░░░░░░░░░░░░ 1,850

Other      ███░░░░░░░░░░░░░ 1,256

LATENCY (p99):

Processing: 245ms

Response:   52ms

ERROR BREAKDOWN:

Timeout:       25

Invalid Sig:   18

Parse Error:   10

Rate Limited:   5

Best Practices

  • Respond Quickly: Return 200 immediately, process async
  • Idempotency: Handle duplicate events gracefully
  • Verify Signatures: Always validate webhook authenticity
  • Log Everything: Maintain audit trail
  • Retry Logic: Implement exponential backoff
  • Dead Letters: Don't lose failed events
  • Rate Limiting: Protect against flood attacks
  • Monitoring: Alert on failures and latency
BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card