# Data deletion service

Data Deletion Service manages deletion of stored data.

OpenAPI file: [`nominal.storage.v1.json`](https://dev.nominal.io/api/_downloads/0a40cc8d3bf020a876f5cc95b98c387b/nominal.storage.v1.json)

## Endpoints

### Delete channel with tags

POST `/storage/data-deletion/v1/delete-channel-with-tags`

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.

Body

`dataSourceRid` 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

`channelWithTags` array of [`ChannelWithTags`](https://dev.nominal.io/api/rest/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

**curl**

```shell
curl -X POST "https://api.gov.nominal.io/api/storage/data-deletion/v1/delete-channel-with-tags" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "dataSourceRid": "<data source rid>"
}'
```

**requests**

```python
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/storage/data-deletion/v1/delete-channel-with-tags",
    headers={"Authorization": "Bearer <api key>"},
    json={"dataSourceRid": "<data source rid>"},
)
response.raise_for_status()
print(response.json())
```

**httpx**

```python
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/storage/data-deletion/v1/delete-channel-with-tags",
    headers={"Authorization": "Bearer <api key>"},
    json={"dataSourceRid": "<data source rid>"},
)
response.raise_for_status()
print(response.json())
```

**aiohttp**

```python
import asyncio

import aiohttp

async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/storage/data-deletion/v1/delete-channel-with-tags",
            headers={"Authorization": "Bearer <api key>"},
            json={"dataSourceRid": "<data source rid>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())

asyncio.run(main())
```

Response: `200`

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

### Delete data

POST `/storage/data-deletion/v1/delete-data`

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.

Body

`dataSourceRid` string
:   ​

`timeRange` [`Range`](https://dev.nominal.io/api/rest/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/rest/data-deletion-service.md#timestamp)
    :   ​

        Fields of `Timestamp`

        `seconds` string (int64)
        :   ​

        `nanos` string (int64)
        :   ​

    `end` [`Timestamp`](https://dev.nominal.io/api/rest/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.

`channelNames` 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.

`deleteMetadata` 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

An empty JSON object, `{}`.

Request

**curl**

```shell
curl -X POST "https://api.gov.nominal.io/api/storage/data-deletion/v1/delete-data" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "dataSourceRid": "<data source rid>",
  "timeRange": {
    "start": {
      "seconds": "1",
      "nanos": "1"
    },
    "end": {
      "seconds": "1",
      "nanos": "1"
    }
  },
  "tags": {
    "<key>": "<value>"
  },
  "channelNames": [
    "<channel names>"
  ],
  "deleteMetadata": true
}'
```

**requests**

```python
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/storage/data-deletion/v1/delete-data",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "dataSourceRid": "<data source rid>",
        "timeRange": {
            "start": {"seconds": "1", "nanos": "1"},
            "end": {"seconds": "1", "nanos": "1"},
        },
        "tags": {"<key>": "<value>"},
        "channelNames": ["<channel names>"],
        "deleteMetadata": True,
    },
)
response.raise_for_status()
print(response.json())
```

**httpx**

```python
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/storage/data-deletion/v1/delete-data",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "dataSourceRid": "<data source rid>",
        "timeRange": {
            "start": {"seconds": "1", "nanos": "1"},
            "end": {"seconds": "1", "nanos": "1"},
        },
        "tags": {"<key>": "<value>"},
        "channelNames": ["<channel names>"],
        "deleteMetadata": True,
    },
)
response.raise_for_status()
print(response.json())
```

**aiohttp**

```python
import asyncio

import aiohttp

async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/storage/data-deletion/v1/delete-data",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "dataSourceRid": "<data source rid>",
                "timeRange": {
                    "start": {"seconds": "1", "nanos": "1"},
                    "end": {"seconds": "1", "nanos": "1"},
                },
                "tags": {"<key>": "<value>"},
                "channelNames": ["<channel names>"],
                "deleteMetadata": True,
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())

asyncio.run(main())
```

Response: `200`

```json
{}
```

### Undelete channel with tags

POST `/storage/data-deletion/v1/undelete-channel-with-tags`

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.

Body

`dataSourceRid` string required
:   ​

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

    Fields of `ChannelWithTags`

    `channel` string
    :   ​

    `tags` map of string to string
    :   ​

Response

An empty JSON object, `{}`.

Request

**curl**

```shell
curl -X POST "https://api.gov.nominal.io/api/storage/data-deletion/v1/undelete-channel-with-tags" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "dataSourceRid": "<data source rid>"
}'
```

**requests**

```python
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/storage/data-deletion/v1/undelete-channel-with-tags",
    headers={"Authorization": "Bearer <api key>"},
    json={"dataSourceRid": "<data source rid>"},
)
response.raise_for_status()
print(response.json())
```

**httpx**

```python
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/storage/data-deletion/v1/undelete-channel-with-tags",
    headers={"Authorization": "Bearer <api key>"},
    json={"dataSourceRid": "<data source rid>"},
)
response.raise_for_status()
print(response.json())
```

**aiohttp**

```python
import asyncio

import aiohttp

async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/storage/data-deletion/v1/undelete-channel-with-tags",
            headers={"Authorization": "Bearer <api key>"},
            json={"dataSourceRid": "<data source rid>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())

asyncio.run(main())
```

Response: `200`

```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/rest/data-deletion-service.md#timestamp)
:   ​

`end` [`Timestamp`](https://dev.nominal.io/api/rest/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` string (int64)
:   ​

`nanos` string (int64)
:   ​

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