# Deleting Data

You need to have write permission on the collection to be able to delete datapoints.

Check out the examples below for common scenarios of deleting data from a collection.

## Deleting data by datapoint IDs

To delete data from a collection, use the [delete](/docs/api-reference/python/tilebox.datasets/Collection.delete) method. This method accepts a list of datapoint IDs to delete.

**Python**

```python title="Python"
from tilebox.datasets import Client

client = Client()
datasets = client.datasets()
collections = datasets.my_custom_dataset.collections()
collection = collections["Sensor-1"]

n_deleted = collection.delete([
  "0195c87a-49f6-5ffa-e3cb-92215d057ea6",
  "0195c87b-bd0e-3998-05cf-af6538f34957",
])

print(f"Deleted {n_deleted} data points.")
```

**Go**

```go title="Go"
package main

import (
	"context"
	"log"
	"log/slog"

	"github.com/google/uuid"
	"github.com/tilebox/tilebox-go/datasets/v1"
)

func main() {
	ctx := context.Background()

	client := datasets.NewClient()

	dataset, err := client.Datasets.Get(ctx, "my_custom_dataset")
	if err != nil {
		log.Fatalf("Failed to get dataset: %v", err)
	}

	collection, err := client.Collections.Get(ctx, dataset.ID, "Sensor-1")
	if err != nil {
		log.Fatalf("Failed to create collection: %v", err)
	}

	datapointIDs := []uuid.UUID{
		uuid.MustParse("0195c87a-49f6-5ffa-e3cb-92215d057ea6"),
		uuid.MustParse("0195c87b-bd0e-3998-05cf-af6538f34957"),
	}
	numDeleted, err := client.Datapoints.DeleteIDs(ctx, collection.ID, datapointIDs)
	if err != nil {
		log.Fatalf("Failed to delete datapoints: %v", err)
	}
	slog.Info("Deleted data points", slog.Int64("deleted", numDeleted))
}
```

**Output**

```plaintext title="Output"
Deleted 2 data points.
```

In python, `delete` not only takes a list of datapoint IDs as string, but supports a wide range of other useful input types as well.
See the [delete](/docs/api-reference/python/tilebox.datasets/Collection.delete) API documentation for more details.

### Possible errors

* `NotFoundError`: raised if one of the data points is not found in the collection. If any of the data points are not found,
  nothing will be deleted
* `ValueError`: raised if one of the specified ids is not a valid UUID

## Deleting a time interval

One common way to delete all datapoints in a time interval is to first query it from a collection and then deleting those
found datapoints. For this use case it often is a good idea to query the datapoints with `skip_data=True` to avoid actually
loading the data fields, since only the datapoint IDs are required. See [skipping data fields](/docs/datasets/query#skipping-data-fields) for more details.

**Python**

```python title="Python"
to_delete = collection.query(temporal_extent=("2023-05-01", "2023-06-01"), skip_data=True)

n_deleted = collection.delete(to_delete)
print(f"Deleted {n_deleted} data points.")
```

**Go**

```go title="Go"
datasetID := uuid.MustParse("25a6f262-f6eb-4de5-be4f-b021f4f7dd13")
collectionID := uuid.MustParse("c5145c99-1843-4816-9221-970f9ce3ac93")
startDate := time.Date(2023, time.May, 1, 0, 0, 0, 0, time.UTC)
endDate := time.Date(2023, time.June, 1, 0, 0, 0, 0, time.UTC)
mai2023 := query.NewTimeInterval(startDate, endDate)

var toDelete []*v1.Sentinel2Msi
err := client.Datapoints.QueryInto(ctx,
  datasetID,
  &toDelete,
  datasets.WithCollectionIDs(collectionID),
  datasets.WithTemporalExtent(mai2023),
  datasets.WithSkipData(),
)
if err != nil {
  log.Fatalf("Failed to query datapoints: %v", err)
}

numDeleted, err := client.Datapoints.Delete(ctx, collectionID, toDelete)
if err != nil {
  log.Fatalf("Failed to delete datapoints: %v", err)
}
slog.Info("Deleted data points", slog.Int64("deleted", numDeleted))
```

**Output**

```plaintext title="Output"
Deleted 104 data points.
```

## Automatic batching

Tilebox automatically batches the delete requests for you, so you don't have to worry about the maximum request size.
