Delete Webhook
Permanently delete a webhook subscription and stop all event deliveries to the specified endpoint.Endpoint
HTTP Request
DELETE /webhooks/{webhook_id}
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Path Parameters
webhook_id
- Type: String
- Description: Unique identifier of the webhook to delete
- Example:
webhook_1234567890
Response Format
Success Response (200 OK)
{
"id": "webhook_1234567890",
"status": "deleted",
"message": "Webhook deleted successfully",
"deleted_at": "2024-01-15T10:30:00Z",
"final_statistics": {
"total_deliveries": 1250,
"total_failures": 3,
"success_rate": 99.76,
"last_delivery_at": "2024-01-15T10:25:00Z"
}
}
Error Response (404 Not Found)
{
"error": "Webhook not found",
"code": 404,
"details": {
"webhook_id": "webhook_invalid_id"
},
"timestamp": "2024-01-15T10:30:00Z",
"requestId": "req_1234567890"
}
Error Response (409 Conflict)
{
"error": "Webhook cannot be deleted while processing events",
"code": 409,
"details": {
"reason": "Webhook has pending events",
"retry_after": 30
},
"timestamp": "2024-01-15T10:30:00Z",
"requestId": "req_1234567890"
}
Implementation Examples
JavaScript (Node.js)
const axios = require("axios");
async function deleteWebhook(apiKey, webhookId) {
try {
const response = await axios.delete(`https://scrape.st/webhooks/${webhookId}`, {
headers: {
"x-api-key": apiKey,
"Content-Type": "application/json",
},
});
const result = response.data;
console.log(`Webhook ${webhookId} deleted successfully`);
// Log final statistics
logWebhookStatistics(webhookId, result.final_statistics);
return result;
} catch (error) {
console.error(`Failed to delete webhook ${webhookId}:`, error.response?.data || error.message);
throw error;
}
}
function logWebhookStatistics(webhookId, stats) {
console.log(`\n=== Final Statistics for ${webhookId} ===`);
console.log(`Total Deliveries: ${stats.total_deliveries}`);
console.log(`Total Failures: ${stats.total_failures}`);
console.log(`Success Rate: ${stats.success_rate.toFixed(2)}%`);
console.log(`Last Delivery: ${new Date(stats.last_delivery_at).toLocaleString()}`);
}
// Usage
deleteWebhook("your_api_key_here", "webhook_1234567890");
Python
import requests
from datetime import datetime
def delete_webhook(api_key, webhook_id):
url = f"https://scrape.st/webhooks/{webhook_id}"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
try:
response = requests.delete(url, headers=headers)
response.raise_for_status()
result = response.json()
print(f"Webhook {webhook_id} deleted successfully")
# Log final statistics
log_webhook_statistics(webhook_id, result["final_statistics"])
return result
except requests.exceptions.RequestException as error:
print(f"Failed to delete webhook {webhook_id}: {error}")
if error.response:
print(f"Error details: {error.response.text}")
raise
def log_webhook_statistics(webhook_id, stats):
print(f"\n=== Final Statistics for {webhook_id} ===")
print(f"Total Deliveries: {stats['total_deliveries']}")
print(f"Total Failures: {stats['total_failures']}")
print(f"Success Rate: {stats['success_rate']:.2f}%")
print(f"Last Delivery: {datetime.fromisoformat(stats['last_delivery_at'].replace('Z', '+00:00')).strftime('%Y-%m-%d %H:%M:%S')}")
# Usage
delete_webhook("your_api_key_here", "webhook_1234567890")
cURL
curl -X DELETE https://scrape.st/webhooks/webhook_1234567890 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json"
Bulk Deletion
Delete Multiple Webhooks
async function deleteMultipleWebhooks(apiKey, webhookIds) {
const results = [];
for (const webhookId of webhookIds) {
try {
const result = await deleteWebhook(apiKey, webhookId);
results.push({ webhookId, status: "success", result });
} catch (error) {
results.push({ webhookId, status: "error", error: error.message });
}
}
return results;
}
// Usage
const webhookIds = ["webhook_123", "webhook_456", "webhook_789"];
const deletionResults = await deleteMultipleWebhooks("your_api_key_here", webhookIds);
console.log("Deletion Results:");
deletionResults.forEach((result) => {
const status = result.status === "success" ? "✅" : "❌";
console.log(`${status} ${result.webhookId}: ${result.status}`);
});
Conditional Deletion
async function deleteInactiveWebhooks(apiKey, inactiveDays = 30) {
// First, list all webhooks
const webhooks = await listWebhooks(apiKey);
const cutoffDate = new Date(Date.now() - inactiveDays * 24 * 60 * 60 * 1000);
const inactiveWebhooks = webhooks.data.filter((webhook) => {
const lastDelivery = new Date(webhook.last_delivery_at);
return !webhook.active || lastDelivery < cutoffDate;
});
console.log(`Found ${inactiveWebhooks.length} inactive webhooks`);
// Delete inactive webhooks
const results = await deleteMultipleWebhooks(
apiKey,
inactiveWebhooks.map((w) => w.id),
);
return results;
}
// Usage
deleteInactiveWebhooks("your_api_key_here", 30); // Delete webhooks inactive for 30+ days
Safety Measures
Confirmation Before Deletion
async function deleteWebhookWithConfirmation(apiKey, webhookId) {
// Get webhook details first
const webhooks = await listWebhooks(apiKey);
const webhook = webhooks.data.find((w) => w.id === webhookId);
if (!webhook) {
throw new Error(`Webhook ${webhookId} not found`);
}
// Show webhook details for confirmation
console.log(`\n=== Webhook Details ===`);
console.log(`ID: ${webhook.id}`);
console.log(`URL: ${webhook.url}`);
console.log(`Events: ${webhook.events.join(", ")}`);
console.log(`Status: ${webhook.status}`);
console.log(`Deliveries: ${webhook.delivery_count}`);
console.log(`Failures: ${webhook.failure_count}`);
// Ask for confirmation (in interactive environments)
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
return new Promise((resolve, reject) => {
rl.question(`\nAre you sure you want to delete this webhook? (y/N): `, async (answer) => {
rl.close();
if (answer.toLowerCase() === "y" || answer.toLowerCase() === "yes") {
try {
const result = await deleteWebhook(apiKey, webhookId);
resolve(result);
} catch (error) {
reject(error);
}
} else {
console.log("Deletion cancelled");
resolve({ cancelled: true });
}
});
});
}
Backup Before Deletion
async function deleteWebhookWithBackup(apiKey, webhookId) {
// Get webhook details before deletion
const webhooks = await listWebhooks(apiKey);
const webhook = webhooks.data.find((w) => w.id === webhookId);
if (!webhook) {
throw new Error(`Webhook ${webhookId} not found`);
}
// Create backup
const backup = {
webhook: webhook,
deleted_at: new Date().toISOString(),
deleted_by: "api_call",
};
// Store backup (implement your storage logic)
await storeWebhookBackup(webhookId, backup);
console.log(`Backup created for webhook ${webhookId}`);
// Delete webhook
return await deleteWebhook(apiKey, webhookId);
}
async function storeWebhookBackup(webhookId, backup) {
// Implement your backup storage logic here
// Could be database, file system, cloud storage, etc.
console.log(`Storing backup for ${webhookId}...`);
// Example: await db.collection('webhook_backups').insertOne(backup);
}
Error Handling
Conflict Resolution
async function deleteWebhookWithRetry(apiKey, webhookId, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await deleteWebhook(apiKey, webhookId);
} catch (error) {
if (error.response?.status === 409) {
const retryAfter = error.response.data?.details?.retry_after || 30;
console.log(`Webhook has pending events, waiting ${retryAfter} seconds...`);
await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
continue;
}
if (error.response?.status === 404) {
throw new Error(`Webhook ${webhookId} not found`);
}
if (attempt === maxRetries) {
throw error;
}
const delay = Math.pow(2, attempt) * 1000;
console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`);
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
}
Graceful Error Handling
async function safeDeleteWebhook(apiKey, webhookId) {
try {
const result = await deleteWebhook(apiKey, webhookId);
console.log(`✅ Webhook ${webhookId} deleted successfully`);
return result;
} catch (error) {
if (error.response?.status === 404) {
console.log(`ℹ️ Webhook ${webhookId} not found (may already be deleted)`);
return { notFound: true };
}
if (error.response?.status === 409) {
console.log(`⚠️ Webhook ${webhookId} cannot be deleted right now`);
return { conflict: true, error: error.message };
}
console.error(`❌ Failed to delete webhook ${webhookId}:`, error.message);
throw error;
}
}
Monitoring and Auditing
Deletion Audit Log
class WebhookAuditLogger {
constructor() {
this.deletionLog = [];
}
logDeletion(webhookId, result, deletedBy = "api") {
const logEntry = {
webhookId,
deletedAt: new Date().toISOString(),
deletedBy,
success: result.status === "deleted",
finalStatistics: result.final_statistics,
error: result.error || null,
};
this.deletionLog.push(logEntry);
// Store in persistent storage
this.storeAuditLog(logEntry);
console.log(`Audit log: Webhook ${webhookId} deletion logged`);
}
async storeAuditLog(logEntry) {
// Implement your audit storage logic
// Could be database, logging service, etc.
console.log("Storing audit log entry:", logEntry);
}
getDeletionHistory(webhookId = null) {
if (webhookId) {
return this.deletionLog.filter((entry) => entry.webhookId === webhookId);
}
return this.deletionLog;
}
}
// Usage
const auditLogger = new WebhookAuditLogger();
async function deleteWebhookWithAudit(apiKey, webhookId) {
try {
const result = await deleteWebhook(apiKey, webhookId);
auditLogger.logDeletion(webhookId, result);
return result;
} catch (error) {
auditLogger.logDeletion(webhookId, { error: error.message, status: "failed" });
throw error;
}
}
Best Practices
Before Deletion
- Verify Webhook: Confirm webhook ID and current status
- Check Dependencies: Ensure no processes depend on the webhook
- Backup Data: Create backup of webhook configuration and statistics
- Notify Teams: Inform relevant teams about planned deletion
During Deletion
- Handle Conflicts: Implement retry logic for temporary conflicts
- Log Operations: Maintain audit trail of all deletions
- Monitor Impact: Watch for any system impact from deletion
- Grace Period: Consider soft deletion before permanent removal
After Deletion
- Verify Cleanup: Confirm all webhook data is removed
- Update Documentation: Update any documentation referencing the webhook
- Monitor Systems: Watch for unexpected behavior after deletion
- Review Patterns: Analyze deletion patterns for optimization