Skip to main content

Delete Tracking

Permanently delete a tracking configuration and stop all data collection for the specified criteria.

Endpoint

HTTP Request

DELETE /tracking/{tracking_id}
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

Path Parameters

tracking_id

  • Type: String
  • Description: Unique identifier of the tracking configuration to delete
  • Example: tracking_1234567890

Response Format

Success Response (200 OK)

{
  "id": "tracking_1234567890",
  "status": "deleted",
  "message": "Tracking configuration deleted successfully",
  "deleted_at": "2024-01-15T10:30:00Z",
  "final_statistics": {
    "total_items_tracked": 15420,
    "daily_average": 1250,
    "success_rate": 99.8,
    "error_count": 3,
    "last_item_at": "2024-01-15T10:25:00Z",
    "tracking_duration": "45 days 12 hours"
  }
}

Error Response (404 Not Found)

{
  "error": "Tracking configuration not found",
  "code": 404,
  "details": {
    "tracking_id": "tracking_invalid_id"
  },
  "timestamp": "2024-01-15T10:30:00Z",
  "requestId": "req_1234567890"
}

Error Response (409 Conflict)

{
  "error": "Tracking cannot be deleted while processing data",
  "code": 409,
  "details": {
    "reason": "Tracking has active data collection in progress",
    "retry_after": 30
  },
  "timestamp": "2024-01-15T10:30:00Z",
  "requestId": "req_1234567890"
}

Implementation Examples

JavaScript (Node.js)

const axios = require("axios");

async function deleteTracking(apiKey, trackingId) {
  try {
    const response = await axios.delete(`https://scrape.st/tracking/${trackingId}`, {
      headers: {
        "x-api-key": apiKey,
        "Content-Type": "application/json",
      },
    });

    const result = response.data;
    console.log(`Tracking ${trackingId} deleted successfully`);

    // Log final statistics
    logTrackingStatistics(trackingId, result.final_statistics);

    return result;
  } catch (error) {
    console.error(`Failed to delete tracking ${trackingId}:`, error.response?.data || error.message);
    throw error;
  }
}

function logTrackingStatistics(trackingId, stats) {
  console.log(`\n=== Final Statistics for ${trackingId} ===`);
  console.log(`Total Items Tracked: ${stats.total_items_tracked.toLocaleString()}`);
  console.log(`Daily Average: ${stats.daily_average.toLocaleString()}`);
  console.log(`Success Rate: ${stats.success_rate.toFixed(2)}%`);
  console.log(`Error Count: ${stats.error_count}`);
  console.log(`Tracking Duration: ${stats.tracking_duration}`);
  console.log(`Last Item: ${new Date(stats.last_item_at).toLocaleString()}`);
}

// Usage
deleteTracking("your_api_key_here", "tracking_1234567890");

Python

import requests
from datetime import datetime

def delete_tracking(api_key, tracking_id):
    url = f"https://scrape.st/tracking/{tracking_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"Tracking {tracking_id} deleted successfully")

        # Log final statistics
        log_tracking_statistics(tracking_id, result["final_statistics"])

        return result
    except requests.exceptions.RequestException as error:
        print(f"Failed to delete tracking {tracking_id}: {error}")
        if error.response:
            print(f"Error details: {error.response.text}")
        raise

def log_tracking_statistics(tracking_id, stats):
    print(f"\n=== Final Statistics for {tracking_id} ===")
    print(f"Total Items Tracked: {stats['total_items_tracked']:,}")
    print(f"Daily Average: {stats['daily_average']:,}")
    print(f"Success Rate: {stats['success_rate']:.2f}%")
    print(f"Error Count: {stats['error_count']}")
    print(f"Tracking Duration: {stats['tracking_duration']}")
    print(f"Last Item: {datetime.fromisoformat(stats['last_item_at'].replace('Z', '+00:00')).strftime('%Y-%m-%d %H:%M:%S')}")

# Usage
delete_tracking("your_api_key_here", "tracking_1234567890")

cURL

curl -X DELETE https://scrape.st/tracking/tracking_1234567890 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Bulk Deletion

Delete Multiple Tracking Configurations

async function deleteMultipleTracking(apiKey, trackingIds) {
  const results = [];

  for (const trackingId of trackingIds) {
    try {
      const result = await deleteTracking(apiKey, trackingId);
      results.push({ trackingId, status: "success", result });
    } catch (error) {
      results.push({ trackingId, status: "error", error: error.message });
    }
  }

  return results;
}

// Usage
const trackingIds = ["tracking_123", "tracking_456", "tracking_789"];
const deletionResults = await deleteMultipleTracking("your_api_key_here", trackingIds);

console.log("Deletion Results:");
deletionResults.forEach((result) => {
  const status = result.status === "success" ? "success" : "failed";
  console.log(`${status}: ${result.trackingId}`);
});

Conditional Deletion

async function deleteInactiveTracking(apiKey, inactiveDays = 30) {
  // First, list all tracking configurations
  const tracking = await listTracking(apiKey);
  const cutoffDate = new Date(Date.now() - inactiveDays * 24 * 60 * 60 * 1000);

  const inactiveTracking = tracking.data.filter((config) => {
    const lastItem = new Date(config.statistics.last_item_at);
    return !config.active || lastItem < cutoffDate;
  });

  console.log(`Found ${inactiveTracking.length} inactive tracking configurations`);

  // Delete inactive tracking
  const results = await deleteMultipleTracking(
    apiKey,
    inactiveTracking.map((t) => t.id),
  );

  return results;
}

// Usage
deleteInactiveTracking("your_api_key_here", 30); // Delete tracking inactive for 30+ days

Safety Measures

Confirmation Before Deletion

async function deleteTrackingWithConfirmation(apiKey, trackingId) {
  // Get tracking details first
  const tracking = await listTracking(apiKey);
  const config = tracking.data.find((t) => t.id === trackingId);

  if (!config) {
    throw new Error(`Tracking ${trackingId} not found`);
  }

  // Show tracking details for confirmation
  console.log(`\n=== Tracking Details ===`);
  console.log(`ID: ${config.id}`);
  console.log(`Name: ${config.name}`);
  console.log(`Type: ${config.type}`);
  console.log(`Status: ${config.status}`);
  console.log(`Items Tracked: ${config.statistics.items_tracked.toLocaleString()}`);
  console.log(`Daily Average: ${config.statistics.daily_average.toLocaleString()}`);
  console.log(`Success Rate: ${config.statistics.success_rate.toFixed(2)}%`);

  // 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 tracking configuration? (y/N): `, async (answer) => {
      rl.close();

      if (answer.toLowerCase() === "y" || answer.toLowerCase() === "yes") {
        try {
          const result = await deleteTracking(apiKey, trackingId);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      } else {
        console.log("Deletion cancelled");
        resolve({ cancelled: true });
      }
    });
  });
}

Backup Before Deletion

async function deleteTrackingWithBackup(apiKey, trackingId) {
  // Get tracking details before deletion
  const tracking = await listTracking(apiKey);
  const config = tracking.data.find((t) => t.id === trackingId);

  if (!config) {
    throw new Error(`Tracking ${trackingId} not found`);
  }

  // Create backup
  const backup = {
    tracking: config,
    deleted_at: new Date().toISOString(),
    deleted_by: "api_call",
  };

  // Store backup (implement your storage logic)
  await storeTrackingBackup(trackingId, backup);

  console.log(`Backup created for tracking ${trackingId}`);

  // Delete tracking
  return await deleteTracking(apiKey, trackingId);
}

async function storeTrackingBackup(trackingId, backup) {
  // Implement your backup storage logic here
  // Could be database, file system, cloud storage, etc.
  console.log(`Storing backup for ${trackingId}...`);
  // Example: await db.collection('tracking_backups').insertOne(backup);
}

Error Handling

Conflict Resolution

async function deleteTrackingWithRetry(apiKey, trackingId, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await deleteTracking(apiKey, trackingId);
    } catch (error) {
      if (error.response?.status === 409) {
        const retryAfter = error.response.data?.details?.retry_after || 30;
        console.log(`Tracking has active data collection, waiting ${retryAfter} seconds...`);
        await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
        continue;
      }

      if (error.response?.status === 404) {
        throw new Error(`Tracking ${trackingId} 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 safeDeleteTracking(apiKey, trackingId) {
  try {
    const result = await deleteTracking(apiKey, trackingId);
    console.log(`Tracking ${trackingId} deleted successfully`);
    return result;
  } catch (error) {
    if (error.response?.status === 404) {
      console.log(`Tracking ${trackingId} not found (may already be deleted)`);
      return { notFound: true };
    }

    if (error.response?.status === 409) {
      console.log(`Tracking ${trackingId} cannot be deleted right now`);
      return { conflict: true, error: error.message };
    }

    console.error(`Failed to delete tracking ${trackingId}:`, error.message);
    throw error;
  }
}

Monitoring and Auditing

Deletion Audit Log

class TrackingAuditLogger {
  constructor() {
    this.deletionLog = [];
  }

  logDeletion(trackingId, result, deletedBy = "api") {
    const logEntry = {
      trackingId,
      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: Tracking ${trackingId} deletion logged`);
  }

  async storeAuditLog(logEntry) {
    // Implement your audit storage logic
    // Could be database, logging service, etc.
    console.log("Storing audit log entry:", logEntry);
  }

  getDeletionHistory(trackingId = null) {
    if (trackingId) {
      return this.deletionLog.filter((entry) => entry.trackingId === trackingId);
    }
    return this.deletionLog;
  }
}

// Usage
const auditLogger = new TrackingAuditLogger();

async function deleteTrackingWithAudit(apiKey, trackingId) {
  try {
    const result = await deleteTracking(apiKey, trackingId);
    auditLogger.logDeletion(trackingId, result);
    return result;
  } catch (error) {
    auditLogger.logDeletion(trackingId, { error: error.message, status: "failed" });
    throw error;
  }
}

Data Export Before Deletion

Export Tracking Data

async function exportTrackingDataBeforeDeletion(apiKey, trackingId) {
  // Get tracking details
  const tracking = await listTracking(apiKey);
  const config = tracking.data.find((t) => t.id === trackingId);

  if (!config) {
    throw new Error(`Tracking ${trackingId} not found`);
  }

  // Export tracking data (implement your export logic)
  const exportData = {
    tracking_config: config,
    export_timestamp: new Date().toISOString(),
    statistics: config.statistics,
    data_summary: {
      total_items: config.statistics.items_tracked,
      tracking_period: {
        start: config.created_at,
        end: config.statistics.last_item_at,
      },
    },
  };

  // Store export data
  await storeTrackingExport(trackingId, exportData);

  console.log(`Data exported for tracking ${trackingId}`);

  // Delete tracking
  return await deleteTracking(apiKey, trackingId);
}

async function storeTrackingExport(trackingId, exportData) {
  // Implement your export storage logic
  console.log(`Storing export data for ${trackingId}...`);
  // Could be file export, database backup, cloud storage, etc.
}

Best Practices

Before Deletion

  • Verify Configuration: Confirm tracking ID and current status
  • Check Dependencies: Ensure no processes depend on the tracking data
  • Export Data: Export important tracking data before deletion
  • Backup Configuration: Create backup of tracking configuration and statistics
  • Notify Teams: Inform relevant teams about planned deletion

During Deletion

  • Handle Conflicts: Implement retry logic for active data collection
  • Log Operations: Maintain audit trail of all deletions
  • Monitor Impact: Watch for any system impact from deletion
  • Grace Period: Consider pausing before permanent deletion

After Deletion

  • Verify Cleanup: Confirm all tracking data is removed
  • Update Documentation: Update documentation referencing the tracking
  • Monitor Systems: Watch for unexpected behavior after deletion
  • Review Patterns: Analyze deletion patterns for optimization

For Data Management

  • Data Retention: Follow data retention policies and compliance requirements
  • Export Formats: Use standard export formats for data portability
  • Storage Planning: Plan appropriate storage for exported data
  • Security Measures: Secure exported data according to your security policies
Next: X Queries Introduction