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

# How to Delete Comparisons in Draftable API

> Learn the different methods for deleting comparisons and managing document storage in Draftable API, including manual deletion, automatic expiry, and understanding URL expiry.

# How to Delete Comparisons in Draftable API

When using the Draftable API, comparisons and their associated documents are stored on the server until they are deleted. Over time, this can result in significant storage usage, particularly in self-hosted deployments where documents accumulate in the `/var` directory.

This guide explains the three approaches to managing comparison lifecycle and deletion:

1. **Manual Deletion** - Explicitly delete comparisons via API calls
2. **Comparison Expiry** - Automatically delete comparisons after a specified time
3. **URL Expiry** - Control viewer URL validity (does **not** delete documents)

<Warning>
  **URL Expiry vs Comparison Expiry**: A common misconception is that setting a URL expiry will delete the comparison and its documents. This is **not** the case. URL expiry only controls how long the viewer link remains valid—the comparison and documents remain on disk until explicitly deleted or until the comparison expires.
</Warning>

***

## Method 1: Manual Deletion

You can permanently delete a comparison at any time using the delete method. This immediately removes the comparison and all associated documents from storage.

<Tabs>
  <Tab title="C# (.NET)">
    ```csharp theme={null}
    using Draftable.CompareAPI.Client;

    // Initialize the client
    var client = new Comparisons(accountId, authToken);

    // Delete a specific comparison by identifier
    client.Delete("your-comparison-identifier");

    // Async version
    await client.DeleteAsync("your-comparison-identifier");
    ```

    After deletion, the comparison identifier becomes available for reuse.
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import draftable

    # Initialize the client
    client = draftable.Client(account_id, auth_token)
    comparisons = client.comparisons

    # Delete a specific comparison by identifier
    comparisons.delete("your-comparison-identifier")
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    const draftable = require('@draftable/compare-api');

    // Initialize the client
    const client = draftable.client(accountId, authToken);
    const comparisons = client.comparisons;

    // Delete a specific comparison by identifier
    comparisons.destroy("your-comparison-identifier").then(() => {
        console.log("Comparison deleted successfully");
    });
    ```

    Note: In the Node.js client, the delete method is called `destroy()`.
  </Tab>
</Tabs>

### Bulk Deletion Example

To delete multiple or all comparisons (e.g., for cleanup), you can retrieve and iterate through your comparisons:

<Tabs>
  <Tab title="C# (.NET)">
    ```csharp theme={null}
    // Get all comparisons and delete the oldest 10
    var allComparisons = client.GetAll();
    var oldestComparisons = allComparisons
        .OrderBy(c => c.CreationTime)
        .Take(10);

    foreach (var comparison in oldestComparisons)
    {
        client.Delete(comparison.Identifier);
        Console.WriteLine($"Deleted comparison: {comparison.Identifier}");
    }
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    # Get all comparisons and delete them
    all_comparisons = comparisons.all()

    for comparison in all_comparisons:
        comparisons.delete(comparison.identifier)
        print(f"Deleted comparison: {comparison.identifier}")
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    // Get all comparisons and delete the oldest 10
    comparisons.getAll().then((allComparisons) => {
        const deleteStartIndex = Math.max(0, allComparisons.length - 10);
        
        for (let i = deleteStartIndex; i < allComparisons.length; i++) {
            const identifier = allComparisons[i].identifier;
            comparisons.destroy(identifier).then(() => {
                console.log(`Deleted comparison: ${identifier}`);
            });
        }
    });
    ```
  </Tab>
</Tabs>

***

## Method 2: Comparison Expiry (Automatic Deletion)

The recommended approach for managing storage is to set an expiry time when creating comparisons. When a comparison expires, the system automatically deletes the comparison **and all associated documents** from storage.

<Tabs>
  <Tab title="C# (.NET)">
    ```csharp theme={null}
    using Draftable.CompareAPI.Client;

    // Create a comparison that expires in 24 hours
    var comparison = client.Create(
        left: Comparisons.Side.FromFile("left.docx"),
        right: Comparisons.Side.FromFile("right.docx"),
        expires: TimeSpan.FromHours(24)
    );

    // Or set expiry to 30 minutes
    var shortLivedComparison = client.Create(
        left: Comparisons.Side.FromFile("left.pdf"),
        right: Comparisons.Side.FromFile("right.pdf"),
        expires: TimeSpan.FromMinutes(30)
    );

    Console.WriteLine($"Comparison will expire at: {comparison.ExpiryTime}");
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from datetime import timedelta, datetime

    # Create a comparison that expires in 24 hours
    comparison = comparisons.create(
        left="left.docx",
        right="right.docx",
        expires=timedelta(hours=24)
    )

    # Or set a specific expiry datetime
    comparison = comparisons.create(
        left="left.pdf",
        right="right.pdf",
        expires=datetime.utcnow() + timedelta(days=7)
    )

    print(f"Comparison will expire at: {comparison.expiry_time}")
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    // Create a comparison that expires in 2 hours
    comparisons.create({
        left: {
            source: 'https://example.com/left.pdf',
            fileType: 'pdf',
        },
        right: {
            source: 'https://example.com/right.docx',
            fileType: 'docx',
        },
        // Expire in 2 hours (milliseconds)
        expires: new Date(Date.now() + 1000 * 60 * 60 * 2),
    }).then((comparison) => {
        console.log(`Comparison will expire at: ${comparison.expiryTime}`);
    });

    // Or set expiry to a specific date
    comparisons.create({
        left: { source: buffer, fileType: 'pdf' },
        right: { source: buffer, fileType: 'docx' },
        expires: new Date('2025-12-31T23:59:59Z'),
    });
    ```
  </Tab>
</Tabs>

### When Does a Comparison Become "Expired"?

A comparison receives the "expired" status when the current time passes the `expiry_time` that was set during creation. Once expired:

1. The comparison becomes inaccessible via the API
2. The system automatically deletes the comparison data
3. All associated documents are removed from storage (e.g., the `/var` directory in self-hosted deployments)

<Tip>
  **Best Practice**: Always set an appropriate `expires` value when creating comparisons. This ensures automatic cleanup and prevents storage from growing indefinitely. Common expiry periods include:

  * **30 minutes to 2 hours** for temporary/preview comparisons
  * **24 hours to 7 days** for standard document reviews
  * **30 days** for long-term reference comparisons
</Tip>

***

## Method 3: URL Expiry (Does NOT Delete Documents)

When generating signed viewer URLs for private comparisons, you can set how long the URL remains valid. **This is not the same as comparison expiry.**

<Warning>
  **Important**: URL expiry only controls the validity of the viewer link. When a URL expires:

  * Users see an "expired link" error message
  * The comparison and documents **remain on disk**
  * Storage is **not** freed

  To delete documents and free storage, you must use **comparison expiry** or **manual deletion**.
</Warning>

<Tabs>
  <Tab title="C# (.NET)">
    ```csharp theme={null}
    // Generate a signed URL valid for 30 minutes (default)
    var viewerUrl = client.SignedViewerURL("comparison-identifier");

    // Generate a signed URL valid for 1 hour
    var viewerUrl = client.SignedViewerURL(
        "comparison-identifier", 
        TimeSpan.FromHours(1)
    );

    // Generate a signed URL valid until a specific time
    var viewerUrl = client.SignedViewerURL(
        "comparison-identifier",
        DateTime.UtcNow.AddDays(1)
    );
    ```

    After the URL expires, users cannot access the viewer via that link, but the comparison still exists and can be accessed with a new signed URL.
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from datetime import timedelta

    # Generate a signed URL valid for 30 minutes (default)
    viewer_url = comparisons.signed_viewer_url("comparison-identifier")

    # Generate a signed URL valid for 1 hour
    viewer_url = comparisons.signed_viewer_url(
        "comparison-identifier",
        valid_until=timedelta(hours=1)
    )

    print(f"Viewer URL: {viewer_url}")
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    // Generate a signed URL valid for 30 minutes (default)
    const viewerUrl = comparisons.signedViewerURL("comparison-identifier");

    // Generate a signed URL valid for 1 hour
    const validUntil = new Date(Date.now() + 1000 * 60 * 60);
    const viewerUrl = comparisons.signedViewerURL(
        "comparison-identifier",
        validUntil
    );

    console.log(`Viewer URL: ${viewerUrl}`);
    ```
  </Tab>
</Tabs>

***

## Comparison: Expiry Methods

| Feature                   | Comparison Expiry               | URL Expiry                     |
| ------------------------- | ------------------------------- | ------------------------------ |
| **Set when**              | Creating comparison             | Generating viewer URL          |
| **Parameter**             | `expires`                       | `valid_until` / `validFor`     |
| **Deletes documents**     | ✅ Yes                           | ❌ No                           |
| **Frees storage**         | ✅ Yes                           | ❌ No                           |
| **Affects access**        | Comparison becomes inaccessible | Only that specific URL expires |
| **Can generate new URLs** | ❌ No (comparison deleted)       | ✅ Yes                          |

***

## Recommended Approach

For most use cases, we recommend combining **comparison expiry** with **URL expiry**:

<Tabs>
  <Tab title="C# (.NET)">
    ```csharp theme={null}
    // Create comparison with 7-day expiry (auto-deletes after 7 days)
    var comparison = client.Create(
        left: Comparisons.Side.FromURL("https://example.com/left.pdf", "pdf"),
        right: Comparisons.Side.FromURL("https://example.com/right.pdf", "pdf"),
        expires: TimeSpan.FromDays(7)
    );

    // Generate URL valid for 1 hour (can regenerate as needed)
    var viewerUrl = client.SignedViewerURL(
        comparison.Identifier,
        TimeSpan.FromHours(1)
    );
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from datetime import timedelta

    # Create comparison with 7-day expiry (auto-deletes after 7 days)
    comparison = comparisons.create(
        left=draftable.make_side("https://example.com/left.pdf", "pdf"),
        right=draftable.make_side("https://example.com/right.pdf", "pdf"),
        expires=timedelta(days=7)
    )

    # Generate URL valid for 1 hour (can regenerate as needed)
    viewer_url = comparisons.signed_viewer_url(
        comparison.identifier,
        valid_until=timedelta(hours=1)
    )
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    // Create comparison with 7-day expiry (auto-deletes after 7 days)
    comparisons.create({
        left: { source: 'https://example.com/left.pdf', fileType: 'pdf' },
        right: { source: 'https://example.com/right.pdf', fileType: 'pdf' },
        expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7), // 7 days
    }).then((comparison) => {
        // Generate URL valid for 1 hour (can regenerate as needed)
        const viewerUrl = comparisons.signedViewerURL(
            comparison.identifier,
            new Date(Date.now() + 1000 * 60 * 60) // 1 hour
        );
        console.log(`Viewer URL: ${viewerUrl}`);
    });
    ```
  </Tab>
</Tabs>

This approach ensures:

* Documents are automatically cleaned up after a reasonable period
* URLs can be regenerated as needed while the comparison exists
* Storage usage remains under control

***

## Need Help?

If you have questions about managing comparisons or storage in your Draftable deployment, please contact us at [support@draftable.com](mailto:support@draftable.com).
