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

# Delete Webhook

> Remove webhook endpoints from your Devdraft application

The Delete Webhook endpoint allows you to permanently remove webhook endpoints from your application. Once deleted, the webhook will no longer receive events and cannot be recovered. This operation is irreversible, so use it carefully.

## Endpoint Details

* **URL**: `/api/v0/webhooks/{webhook_id}`
* **Method**: `DELETE`
* **Authentication**: Required (API Key Authentication with Scopes)
* **Content-Type**: `application/json`
* **Required Scope**: `webhook:delete`

## Authentication

This endpoint requires API key authentication with specific scopes:

### Required Headers

```json theme={null}
x-client-key: your-client-key
x-client-secret: your-client-secret
```

### Required Scope

Your API key must have the `webhook:delete` scope to access this endpoint.

## Path Parameters

| Parameter   | Type   | Description                   | Required |
| ----------- | ------ | ----------------------------- | -------- |
| webhook\_id | string | Unique identifier for webhook | Yes      |

## Response

### Success Response (204 No Content)

When a webhook is successfully deleted, the API returns a `204 No Content` status with an empty response body. This indicates that the webhook has been permanently removed.

### Confirmation Response (200 OK)

Some implementations may return a confirmation response:

<CodeGroup>
  ```json Confirmation Response theme={null}
  {
    "message": "Webhook successfully deleted",
    "webhook_id": "wh_550e8400e29b41d4a716446655440000",
    "deleted_at": "2024-03-20T15:30:00.000Z"
  }
  ```
</CodeGroup>

## Example Requests

<CodeGroup>
  ```bash Basic Delete theme={null}
  curl -X DELETE "https://api.devdraft.ai/api/v0/webhooks/wh_550e8400e29b41d4a716446655440000" \
    -H "Content-Type: application/json" \
    -H "x-client-key: your-client-key" \
    -H "x-client-secret: your-client-secret"
  ```

  ```javascript JavaScript/Node.js theme={null}
  const deleteWebhook = async (webhookId) => {
    try {
      const response = await fetch(`https://api.devdraft.ai/api/v0/webhooks/${webhookId}`, {
        method: 'DELETE',
        headers: {
          'Content-Type': 'application/json',
          'x-client-key': process.env.DEVDRAFT_CLIENT_KEY,
          'x-client-secret': process.env.DEVDRAFT_CLIENT_SECRET
        }
      });

      if (!response.ok) {
        throw new Error(`Failed to delete webhook: ${response.statusText}`);
      }

      console.log(`Webhook ${webhookId} successfully deleted`);
      return true;
    } catch (error) {
      console.error('Error deleting webhook:', error);
      throw error;
    }
  };

  // Safe deletion with confirmation
  const safeDeleteWebhook = async (webhookId) => {
    try {
      // First, get webhook details for confirmation
      const webhook = await getWebhook(webhookId);
      console.log(`About to delete webhook: ${webhook.name} (${webhook.url})`);
      
      // Confirm deletion (you might want to add user confirmation here)
      const confirmed = true; // Replace with actual confirmation logic
      
      if (confirmed) {
        await deleteWebhook(webhookId);
        console.log('Webhook deleted successfully');
      } else {
        console.log('Deletion cancelled');
      }
    } catch (error) {
      console.error('Error in safe deletion:', error);
      throw error;
    }
  };

  // Usage
  await deleteWebhook('wh_550e8400e29b41d4a716446655440000');
  ```

  ```python Python theme={null}
  import requests
  from typing import Optional

  class WebhookManager:
      def __init__(self, client_key: str, client_secret: str, base_url: str = 'https://api.devdraft.ai'):
          self.client_key = client_key
          self.client_secret = client_secret
          self.base_url = base_url
          
      def delete_webhook(self, webhook_id: str) -> bool:
          headers = {
              'Content-Type': 'application/json',
              'x-client-key': self.client_key,
              'x-client-secret': self.client_secret
          }
          
          response = requests.delete(
              f"{self.base_url}/api/v0/webhooks/{webhook_id}",
              headers=headers
          )
          
          if response.status_code == 204:
              return True
          elif response.status_code == 200:
              return True
          else:
              response.raise_for_status()
              return False
      
      def safe_delete_webhook(self, webhook_id: str, confirm: bool = False) -> bool:
          """Safely delete webhook with confirmation"""
          if not confirm:
              # Get webhook details first
              webhook = self.get_webhook(webhook_id)
              print(f"WARNING: About to delete webhook '{webhook['name']}' ({webhook['url']})")
              print("This action cannot be undone!")
              
              # In a real application, you would prompt for user confirmation
              response = input("Are you sure you want to delete this webhook? (yes/no): ")
              if response.lower() != 'yes':
                  print("Deletion cancelled")
                  return False
          
          return self.delete_webhook(webhook_id)
      
      def cleanup_inactive_webhooks(self, dry_run: bool = True) -> list:
          """Clean up inactive webhooks"""
          webhooks = self.list_webhooks(active=False)
          inactive_webhooks = webhooks['data']
          
          if dry_run:
              print(f"Found {len(inactive_webhooks)} inactive webhooks that could be deleted:")
              for webhook in inactive_webhooks:
                  print(f"- {webhook['name']} ({webhook['id']})")
              return inactive_webhooks
          
          deleted_webhooks = []
          for webhook in inactive_webhooks:
              try {
                  if self.delete_webhook(webhook['id']):
                      deleted_webhooks.append(webhook)
                      print(f"Deleted inactive webhook: {webhook['name']}")
              except Exception as e:
                  print(f"Failed to delete webhook {webhook['name']}: {e}")
          
          return deleted_webhooks

  # Usage
  webhook_manager = WebhookManager(
      client_key='your-client-key',
      client_secret='your-client-secret'
  )

  # Delete a specific webhook
  webhook_manager.delete_webhook('wh_550e8400e29b41d4a716446655440000')

  # Safe deletion with confirmation
  webhook_manager.safe_delete_webhook('wh_550e8400e29b41d4a716446655440000')

  # Clean up inactive webhooks (dry run first)
  inactive = webhook_manager.cleanup_inactive_webhooks(dry_run=True)
  print(f"Found {len(inactive)} inactive webhooks")
  ```
</CodeGroup>

## Error Responses

<CodeGroup>
  ```json 404 Not Found theme={null}
  {
    "statusCode": 404,
    "message": "Webhook not found",
    "error": "Not Found",
    "details": "No webhook found with ID: wh_550e8400e29b41d4a716446655440000"
  }
  ```

  ```json 401 Unauthorized theme={null}
  {
    "statusCode": 401,
    "message": "Client key or secret missing",
    "error": "Unauthorized",
    "details": "Please provide both x-client-key and x-client-secret headers"
  }
  ```

  ```json 403 Forbidden theme={null}
  {
    "statusCode": 403,
    "message": "Missing required scope",
    "error": "Forbidden",
    "details": "API key does not have the required webhook:delete scope"
  }
  ```

  ```json 409 Conflict theme={null}
  {
    "statusCode": 409,
    "message": "Cannot delete webhook with pending deliveries",
    "error": "Conflict",
    "details": "Wait for pending deliveries to complete before deleting"
  }
  ```
</CodeGroup>

## Safety Considerations

<Warning>
  **Irreversible Action**: Once a webhook is deleted, it cannot be recovered. All configuration and delivery history will be permanently lost.
</Warning>

<Warning>
  **Active Deliveries**: Deleting a webhook may interrupt pending event deliveries. Consider disabling the webhook first and waiting for pending deliveries to complete.
</Warning>

### Pre-Deletion Checklist

<Steps>
  <Step title="Verify Webhook ID">
    Double-check the webhook ID to ensure you're deleting the correct webhook.
  </Step>

  <Step title="Check Dependencies">
    Verify that no critical processes depend on this webhook for functionality.
  </Step>

  <Step title="Review Recent Activity">
    Check recent delivery events to ensure no important events are in progress.
  </Step>

  <Step title="Backup Configuration">
    Note down webhook configuration (URL, settings) in case you need to recreate it.
  </Step>

  <Step title="Inform Team">
    Notify relevant team members about the webhook deletion, especially if it's shared.
  </Step>
</Steps>

## Alternative Actions

Before deleting a webhook, consider these alternatives:

<AccordionGroup>
  <Accordion title="Disable Instead of Delete" icon="toggle-off">
    **Temporary Solution**: Disable the webhook by setting `isActive: false` instead of deleting it.

    ```javascript theme={null}
    // Disable webhook instead of deleting
    await updateWebhook(webhookId, { isActive: false });
    ```

    **Benefits**:

    * Preserves configuration and history
    * Can be easily re-enabled later
    * Safer than permanent deletion
  </Accordion>

  <Accordion title="Update URL" icon="link">
    **Redirect to New Endpoint**: Update the webhook URL to point to a new endpoint.

    ```javascript theme={null}
    // Update webhook URL
    await updateWebhook(webhookId, { 
      url: 'https://new-endpoint.example.com/webhooks' 
    });
    ```

    **Use Cases**:

    * Moving to a new server
    * Changing webhook implementation
    * Temporary redirects
  </Accordion>

  <Accordion title="Archive Configuration" icon="archive">
    **Export Settings**: Save webhook configuration before deletion for future reference.

    ```javascript theme={null}
    // Export webhook configuration
    const webhook = await getWebhook(webhookId);
    const config = {
      name: webhook.name,
      url: webhook.url,
      encrypted: webhook.encrypted,
      // Save other important settings
    };
    console.log('Webhook config:', JSON.stringify(config, null, 2));
    ```
  </Accordion>
</AccordionGroup>

## Batch Operations

### Delete Multiple Webhooks

<CodeGroup>
  ```javascript Batch Deletion theme={null}
  const deleteMultipleWebhooks = async (webhookIds) => {
    const results = [];
    
    for (const webhookId of webhookIds) {
      try {
        await deleteWebhook(webhookId);
        results.push({ 
          webhookId, 
          status: 'deleted', 
          error: null 
        });
      } catch (error) {
        results.push({ 
          webhookId, 
          status: 'failed', 
          error: error.message 
        });
      }
    }
    
    return results;
  };

  // Usage
  const webhooksToDelete = [
    'wh_550e8400e29b41d4a716446655440000',
    'wh_660f9500f30c52e5b827557766551111'
  ];

  const results = await deleteMultipleWebhooks(webhooksToDelete);
  console.log('Deletion results:', results);
  ```
</CodeGroup>

### Cleanup Unused Webhooks

<CodeGroup>
  ```javascript Cleanup Script theme={null}
  const cleanupUnusedWebhooks = async (criteria = {}) => {
    const {
      inactiveDays = 30,
      zeroDeliveries = true,
      confirmBeforeDelete = true
    } = criteria;
    
    // Get all webhooks
    const webhooks = await listWebhooks();
    
    // Filter based on criteria
    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() - inactiveDays);
    
    const candidatesForDeletion = webhooks.data.filter(webhook => {
      const lastDelivery = new Date(webhook.delivery_stats.last_delivery || 0);
      const hasNoDeliveries = webhook.delivery_stats.total_events === 0;
      const isOldAndInactive = lastDelivery < cutoffDate;
      
      return (zeroDeliveries && hasNoDeliveries) || isOldAndInactive;
    });
    
    console.log(`Found ${candidatesForDeletion.length} webhooks for cleanup:`);
    candidatesForDeletion.forEach(webhook => {
      console.log(`- ${webhook.name} (${webhook.id}) - Last delivery: ${webhook.delivery_stats.last_delivery || 'Never'}`);
    });
    
    if (confirmBeforeDelete) {
      const confirm = prompt('Delete these webhooks? (yes/no): ');
      if (confirm !== 'yes') {
        console.log('Cleanup cancelled');
        return [];
      }
    }
    
    // Delete webhooks
    return await deleteMultipleWebhooks(candidatesForDeletion.map(w => w.id));
  };

  // Run cleanup
  await cleanupUnusedWebhooks({
    inactiveDays: 60,
    zeroDeliveries: true,
    confirmBeforeDelete: true
  });
  ```
</CodeGroup>

## Best Practices

<AccordionGroup>
  <Accordion title="Confirmation Process" icon="clipboard-check">
    * Always implement a confirmation step for deletion operations
    * Display webhook details before deletion to prevent mistakes
    * Consider requiring additional authentication for bulk deletions
  </Accordion>

  <Accordion title="Audit Logging" icon="file-text">
    * Log all webhook deletions for audit purposes
    * Include user information, timestamp, and reason for deletion
    * Maintain deletion logs for compliance and troubleshooting
  </Accordion>

  <Accordion title="Graceful Handling" icon="hand-peace">
    * Check for pending deliveries before deletion
    * Consider disabling webhook first, then deleting after grace period
    * Implement proper error handling for deletion failures
  </Accordion>

  <Accordion title="Backup Strategy" icon="database">
    * Export webhook configurations before deletion
    * Store critical webhook settings in version control
    * Document webhook purposes and dependencies
  </Accordion>
</AccordionGroup>

## Use Cases

### Development Environment Cleanup

<CodeGroup>
  ```javascript Development Cleanup theme={null}
  const cleanupDevelopmentWebhooks = async () => {
    const webhooks = await listWebhooks();
    
    // Find development/test webhooks
    const devWebhooks = webhooks.data.filter(webhook => 
      webhook.name.toLowerCase().includes('test') ||
      webhook.name.toLowerCase().includes('dev') ||
      webhook.url.includes('localhost') ||
      webhook.url.includes('webhook.site')
    );
    
    console.log(`Found ${devWebhooks.length} development webhooks`);
    
    // Delete development webhooks
    for (const webhook of devWebhooks) {
      try {
        await deleteWebhook(webhook.id);
        console.log(`Deleted development webhook: ${webhook.name}`);
      } catch (error) {
        console.error(`Failed to delete ${webhook.name}: ${error.message}`);
      }
    }
  };
  ```
</CodeGroup>

### Migration Cleanup

<CodeGroup>
  ```javascript Migration Cleanup theme={null}
  const cleanupAfterMigration = async (oldUrlPattern) => {
    const webhooks = await listWebhooks();
    
    // Find webhooks pointing to old infrastructure
    const oldWebhooks = webhooks.data.filter(webhook => 
      webhook.url.includes(oldUrlPattern)
    );
    
    console.log(`Found ${oldWebhooks.length} webhooks using old URLs`);
    
    // Confirm each deletion individually for migration cleanup
    for (const webhook of oldWebhooks) {
      console.log(`\nWebhook: ${webhook.name}`);
      console.log(`URL: ${webhook.url}`);
      console.log(`Last delivery: ${webhook.delivery_stats.last_delivery || 'Never'}`);
      
      const action = prompt('Action (delete/skip/update): ');
      
      if (action === 'delete') {
        await deleteWebhook(webhook.id);
        console.log('Deleted');
      } else if (action === 'update') {
        const newUrl = prompt('New URL: ');
        if (newUrl) {
          await updateWebhook(webhook.id, { url: newUrl });
          console.log('Updated');
        }
      } else {
        console.log('Skipped');
      }
    }
  };
  ```
</CodeGroup>

## Related Endpoints

* `POST /api/v0/webhooks` - Create a new webhook
* `GET /api/v0/webhooks` - List all webhooks
* `GET /api/v0/webhooks/{id}` - Fetch specific webhook details
* `PATCH /api/v0/webhooks/{id}` - Update webhook configuration
