# Data deletion service (gRPC)

Data Deletion Service manages deletion of stored data.

## Endpoints

### Delete channel with tags

gRPC `/nominal.storage.v1.DataDeletionService/DeleteChannelWithTags`

Deletes channels with tags within a data source. Requires DATASOURCE__DELETE_DATA permission on the data source. Deletions are soft — deleted channels with tags are marked for deletion and will eventually be hard deleted. The request will be rejected if there are too many pending deletions for the data source. Throws if the request matches too many channels with tags.

Request: `DeleteChannelWithTagsRequest`

`data_source_rid` string required
:   ​

`channel` string
:   If channel is provided, only channels with tags matching that channel will be deleted.

`tags` map of string to string
:   At least one tag must be specified in the request. Deletes all data containing the specified tags. At least 1 entrie.

`apply` boolean
:   When false, the request does not apply the deletions and instead returns the list of channels with tags that would be deleted. When true, the deletions are applied.

Response: `DeleteChannelWithTagsResponse`

`channel_with_tags` array of [`ChannelWithTags`](https://dev.nominal.io/api/grpc/data-deletion-service.md#channelwithtags)
:   The list of ChannelWithTags that were deleted or would be deleted (when apply is false).

    Fields of `ChannelWithTags`

    `channel` string
    :   ​

    `tags` map of string to string
    :   ​

Request

**Python**

```python
import grpc
from nominal.protos.storage.v1 import data_deletion_pb2, data_deletion_pb2_grpc

channel = grpc.secure_channel("api.gov.nominal.io:443", grpc.ssl_channel_credentials())
data_deletion_service = data_deletion_pb2_grpc.DataDeletionServiceStub(channel)
auth = [("authorization", "Bearer <api key>")]

request = data_deletion_pb2.DeleteChannelWithTagsRequest(
    data_source_rid="<data source rid>",
)
response = data_deletion_service.DeleteChannelWithTags(request, metadata=auth)
print(response)
```

**Go**

```go
package main

import (
	"context"
	"crypto/tls"
	"fmt"
	"log"

	storagev1 "github.com/nominal-io/nominal-api-protos-go/nominal/protos/storage/v1"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/metadata"
)

func main() {
	conn, err := grpc.NewClient("api.gov.nominal.io:443",
		grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})))
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
	dataDeletionService := storagev1.NewDataDeletionServiceClient(conn)
	ctx := metadata.AppendToOutgoingContext(context.Background(), "authorization", "Bearer <api key>")

	request := &storagev1.DeleteChannelWithTagsRequest{
		DataSourceRid: "<data source rid>",
	}
	response, err := dataDeletionService.DeleteChannelWithTags(ctx, request)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(response)
}
```

Response

```json
{
  "channel_with_tags": [
    {
      "channel": "<channel>",
      "tags": {
        "<key>": "<value>"
      }
    }
  ]
}
```

### Delete data

gRPC `/nominal.storage.v1.DataDeletionService/DeleteData`

Do not use it for new integrations.

Deletes stored data. This is an irreversible operation so be careful about specified time range, channel names, and tag scope. requires the user to be an admin for the organization.

Request: `DeleteDataRequest`

`data_source_rid` string
:   ​

`time_range` [`Range`](https://dev.nominal.io/api/grpc/data-deletion-service.md#range)
:   If specified, will only delete data within the given time range. If not specified, will delete data across all time.

    Fields of `Range`

    `start` [`Timestamp`](https://dev.nominal.io/api/grpc/data-deletion-service.md#timestamp)
    :   ​

        Fields of `Timestamp`

        `seconds` integer (int64)
        :   ​

        `nanos` integer (int64)
        :   ​

    `end` [`Timestamp`](https://dev.nominal.io/api/grpc/data-deletion-service.md#timestamp)
    :   ​

`tags` map of string to string
:   If specified, will only delete data that fully matches the given tags. If not specified, will delete data across all tags.

`channel_names` array of string
:   If specified, will only delete data that has an exact channel name match with the given names. If not specified, will delete data across all channels.

`delete_metadata` boolean
:   If true and tags, channelNames, and timeRange are empty, will also delete associated channel metadata. Otherwise, will only delete raw data. This is to guarantee that you are not orphaning data unintentionally by deleting the metadata.

Response: `DeleteDataResponse`

A message with no fields.

Request

**Python**

```python
import grpc
from nominal.protos.storage.v1 import data_deletion_pb2, data_deletion_pb2_grpc

channel = grpc.secure_channel("api.gov.nominal.io:443", grpc.ssl_channel_credentials())
data_deletion_service = data_deletion_pb2_grpc.DataDeletionServiceStub(channel)
auth = [("authorization", "Bearer <api key>")]

request = data_deletion_pb2.DeleteDataRequest(
    data_source_rid="<data source rid>",
    time_range={"start": {"seconds": 1, "nanos": 1}, "end": {"seconds": 1, "nanos": 1}},
    tags={"<key>": "<value>"},
    channel_names=["<channel names>"],
    delete_metadata=True,
)
response = data_deletion_service.DeleteData(request, metadata=auth)
print(response)
```

**Go**

```go
package main

import (
	"context"
	"crypto/tls"
	"fmt"
	"log"

	storagev1 "github.com/nominal-io/nominal-api-protos-go/nominal/protos/storage/v1"
	typestime "github.com/nominal-io/nominal-api-protos-go/nominal/protos/types/time"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/metadata"
	"google.golang.org/protobuf/proto"
)

func main() {
	conn, err := grpc.NewClient("api.gov.nominal.io:443",
		grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})))
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
	dataDeletionService := storagev1.NewDataDeletionServiceClient(conn)
	ctx := metadata.AppendToOutgoingContext(context.Background(), "authorization", "Bearer <api key>")

	request := &storagev1.DeleteDataRequest{
		DataSourceRid: "<data source rid>",
		TimeRange: &typestime.Range{
			Start: &typestime.Timestamp{
				Seconds: proto.Int64(1),
				Nanos:   proto.Int64(1),
			},
			End: &typestime.Timestamp{
				Seconds: proto.Int64(1),
				Nanos:   proto.Int64(1),
			},
		},
		Tags: map[string]string{
			"<key>": "<value>",
		},
		ChannelNames: []string{
			"<channel names>",
		},
		DeleteMetadata: true,
	}
	response, err := dataDeletionService.DeleteData(ctx, request)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(response)
}
```

Response

```json
{}
```

### Undelete channel with tags

gRPC `/nominal.storage.v1.DataDeletionService/UndeleteChannelWithTags`

Best effort to undelete channels with tags within a data source. Requires DATASOURCE__DELETE_DATA permission on the data source. The batch size of channels with tags in the request must be <= 1000.

Request: `UndeleteChannelWithTagsRequest`

`data_source_rid` string required
:   ​

`channel_with_tags` array of [`ChannelWithTags`](https://dev.nominal.io/api/grpc/data-deletion-service.md#channelwithtags)
:   1 to 1,000 items.

    Fields of `ChannelWithTags`

    `channel` string
    :   ​

    `tags` map of string to string
    :   ​

Response: `UndeleteChannelWithTagsResponse`

A message with no fields.

Request

**Python**

```python
import grpc
from nominal.protos.storage.v1 import data_deletion_pb2, data_deletion_pb2_grpc

channel = grpc.secure_channel("api.gov.nominal.io:443", grpc.ssl_channel_credentials())
data_deletion_service = data_deletion_pb2_grpc.DataDeletionServiceStub(channel)
auth = [("authorization", "Bearer <api key>")]

request = data_deletion_pb2.UndeleteChannelWithTagsRequest(
    data_source_rid="<data source rid>",
)
response = data_deletion_service.UndeleteChannelWithTags(request, metadata=auth)
print(response)
```

**Go**

```go
package main

import (
	"context"
	"crypto/tls"
	"fmt"
	"log"

	storagev1 "github.com/nominal-io/nominal-api-protos-go/nominal/protos/storage/v1"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/metadata"
)

func main() {
	conn, err := grpc.NewClient("api.gov.nominal.io:443",
		grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})))
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
	dataDeletionService := storagev1.NewDataDeletionServiceClient(conn)
	ctx := metadata.AppendToOutgoingContext(context.Background(), "authorization", "Bearer <api key>")

	request := &storagev1.UndeleteChannelWithTagsRequest{
		DataSourceRid: "<data source rid>",
	}
	response, err := dataDeletionService.UndeleteChannelWithTags(ctx, request)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(response)
}
```

Response

```json
{}
```

## Types

### ChannelWithTags

Identifies a channel with its associated tags.

`channel` string
:   ​

`tags` map of string to string
:   ​

### Range

Deprecated for new APIs. Define an API-owned range with the endpoint semantics it needs instead.

`start` [`Timestamp`](https://dev.nominal.io/api/grpc/data-deletion-service.md#timestamp)
:   ​

`end` [`Timestamp`](https://dev.nominal.io/api/grpc/data-deletion-service.md#timestamp)
:   ​

### Timestamp

Deprecated for new APIs. Use google.protobuf.Timestamp for absolute instants.

This legacy nanosecond-precision timestamp is represented by an epoch time in seconds and a nanosecond offset. The nanosecond offset is from the start of the epoch second, so must be less than 1 billion.

`seconds` integer (int64)
:   ​

`nanos` integer (int64)
:   ​

Page design based on [Scalar](https://scalar.com), MIT License.
