{
  "swagger": "2.0",
  "info": {
    "title": "Data deletion service, Dataset retention service",
    "version": "0.1507.0",
    "description": "Send your API key as a bearer token: `Authorization: Bearer <api key>`."
  },
  "tags": [
    {
      "name": "DataDeletionService",
      "x-displayName": "Data deletion service",
      "description": "Data Deletion Service manages deletion of stored data."
    },
    {
      "name": "DatasetRetentionService",
      "x-displayName": "Dataset retention service",
      "description": "Manages retention policies and exemptions for datasets."
    }
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/storage/data-deletion/v1/delete-channel-with-tags": {
      "post": {
        "operationId": "DataDeletionService_DeleteChannelWithTags",
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/DeleteChannelWithTagsResponse"
            },
            "x-example": {
              "channelWithTags": [
                {
                  "channel": "<channel>",
                  "tags": {
                    "<key>": "<value>"
                  }
                }
              ]
            }
          }
        },
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/DeleteChannelWithTagsRequest"
            },
            "x-example": {
              "dataSourceRid": "<data source rid>"
            }
          }
        ],
        "tags": [
          "DataDeletionService"
        ],
        "summary": "Delete channel with tags",
        "description": "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."
      }
    },
    "/storage/data-deletion/v1/delete-data": {
      "post": {
        "description": "Do not use it for new integrations.\n\nDeletes 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.",
        "operationId": "DataDeletionService_DeleteData",
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/DeleteDataResponse"
            },
            "x-example": {}
          }
        },
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/DeleteDataRequest"
            },
            "x-example": {
              "dataSourceRid": "<data source rid>",
              "timeRange": {
                "start": {
                  "seconds": "1",
                  "nanos": "1"
                },
                "end": {
                  "seconds": "1",
                  "nanos": "1"
                }
              },
              "tags": {
                "<key>": "<value>"
              },
              "channelNames": [
                "<channel names>"
              ],
              "deleteMetadata": true
            }
          }
        ],
        "tags": [
          "DataDeletionService"
        ],
        "summary": "Delete data"
      }
    },
    "/storage/data-deletion/v1/undelete-channel-with-tags": {
      "post": {
        "operationId": "DataDeletionService_UndeleteChannelWithTags",
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/UndeleteChannelWithTagsResponse"
            },
            "x-example": {}
          }
        },
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UndeleteChannelWithTagsRequest"
            },
            "x-example": {
              "dataSourceRid": "<data source rid>"
            }
          }
        ],
        "tags": [
          "DataDeletionService"
        ],
        "summary": "Undelete channel with tags",
        "description": "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."
      }
    },
    "/storage/dataset-retention/v1/exemptions": {
      "post": {
        "operationId": "DatasetRetentionService_UpsertDatasetRetentionExemption",
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/UpsertDatasetRetentionExemptionResponse"
            },
            "x-example": {
              "exemption": {
                "datasetRid": "<dataset rid>",
                "sourceId": "<source id>",
                "bounds": {
                  "start": {
                    "seconds": "1",
                    "nanos": "1"
                  },
                  "end": {
                    "seconds": "1",
                    "nanos": "1"
                  }
                },
                "description": "<description>"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpsertDatasetRetentionExemptionRequest"
            },
            "x-example": {
              "datasetRid": "<dataset rid>",
              "sourceId": "<source id>",
              "bounds": {
                "start": {
                  "seconds": "1",
                  "nanos": "1"
                },
                "end": {
                  "seconds": "1",
                  "nanos": "1"
                }
              }
            }
          }
        ],
        "tags": [
          "DatasetRetentionService"
        ],
        "summary": "Upsert dataset retention exemption",
        "description": "Create or update a retention exemption for a dataset. The exemption is keyed by (dataset_rid, source_id) — upserting with the same key updates the time range."
      }
    },
    "/storage/dataset-retention/v1/exemptions/list": {
      "post": {
        "operationId": "DatasetRetentionService_ListDatasetRetentionExemptions",
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/ListDatasetRetentionExemptionsResponse"
            },
            "x-example": {
              "exemptions": [
                {
                  "datasetRid": "<dataset rid>",
                  "sourceId": "<source id>",
                  "bounds": {
                    "start": {
                      "seconds": "1",
                      "nanos": "1"
                    },
                    "end": {
                      "seconds": "1",
                      "nanos": "1"
                    }
                  },
                  "description": "<description>"
                }
              ],
              "nextPageToken": "<next page token>"
            }
          }
        },
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ListDatasetRetentionExemptionsRequest"
            },
            "x-example": {
              "datasetRid": "<dataset rid>",
              "bounds": {
                "start": {
                  "seconds": "1",
                  "nanos": "1"
                },
                "end": {
                  "seconds": "1",
                  "nanos": "1"
                }
              }
            }
          }
        ],
        "tags": [
          "DatasetRetentionService"
        ],
        "summary": "List dataset retention exemptions",
        "description": "List retention exemptions for a dataset, filtered to those overlapping the given time range."
      }
    },
    "/storage/dataset-retention/v1/exemptions/{datasetRid}/{sourceId}": {
      "delete": {
        "operationId": "DatasetRetentionService_DeleteDatasetRetentionExemption",
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/DeleteDatasetRetentionExemptionResponse"
            },
            "x-example": {}
          }
        },
        "parameters": [
          {
            "name": "datasetRid",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "sourceId",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "tags": [
          "DatasetRetentionService"
        ],
        "summary": "Delete dataset retention exemption",
        "description": "Delete a retention exemption for a dataset."
      }
    },
    "/storage/dataset-retention/v1/policy/{datasetRid}": {
      "put": {
        "operationId": "DatasetRetentionService_UpdateRetentionPolicy",
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/UpdateRetentionPolicyResponse"
            },
            "x-example": {}
          }
        },
        "parameters": [
          {
            "name": "datasetRid",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpdateRetentionPolicyBody"
            },
            "x-example": {
              "retentionPolicy": {
                "keepForever": {}
              }
            }
          }
        ],
        "tags": [
          "DatasetRetentionService"
        ],
        "summary": "Update retention policy",
        "description": "Update or remove the retention policy for a dataset. When a policy is set, data older than the policy's expiry will be deleted."
      }
    },
    "/storage/dataset-retention/v1/watermarks/{datasetRid}": {
      "get": {
        "operationId": "DatasetRetentionService_GetDatasetRetentionWatermark",
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/GetDatasetRetentionWatermarkResponse"
            },
            "x-example": {
              "watermark": {
                "seconds": "1",
                "nanos": "1"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "datasetRid",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "tags": [
          "DatasetRetentionService"
        ],
        "summary": "Get dataset retention watermark",
        "description": "Get the retention watermark for a dataset."
      },
      "put": {
        "operationId": "DatasetRetentionService_UpdateDatasetRetentionWatermark",
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/UpdateDatasetRetentionWatermarkResponse"
            },
            "x-example": {
              "watermark": {
                "seconds": "1",
                "nanos": "1"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "datasetRid",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/UpdateDatasetRetentionWatermarkBody"
            },
            "x-example": {
              "watermark": {
                "seconds": "1",
                "nanos": "1"
              }
            }
          }
        ],
        "tags": [
          "DatasetRetentionService"
        ],
        "summary": "Update dataset retention watermark",
        "description": "Update the retention watermark for a dataset."
      }
    }
  },
  "definitions": {
    "ChannelWithTags": {
      "type": "object",
      "properties": {
        "channel": {
          "type": "string"
        },
        "tags": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        }
      },
      "description": "Identifies a channel with its associated tags."
    },
    "DatasetRetentionExemption": {
      "type": "object",
      "properties": {
        "datasetRid": {
          "type": "string",
          "description": "The dataset this exemption applies to."
        },
        "sourceId": {
          "type": "string",
          "description": "Identifier for the source of this exemption (e.g. run RID)."
        },
        "bounds": {
          "$ref": "#/definitions/Range",
          "description": "Inclusive time range to exempt from retention."
        },
        "description": {
          "type": "string",
          "maxLength": 1024,
          "x-constraints": [
            "At most 1,024 characters."
          ]
        }
      },
      "description": "A retention exemption for a dataset, representing a time range that should be preserved regardless of the dataset's retention policy.",
      "required": [
        "datasetRid",
        "sourceId",
        "bounds"
      ]
    },
    "UpdateDatasetRetentionWatermarkBody": {
      "type": "object",
      "properties": {
        "watermark": {
          "$ref": "#/definitions/Timestamp"
        }
      },
      "required": [
        "watermark"
      ],
      "example": {
        "watermark": {
          "seconds": "1",
          "nanos": "1"
        }
      }
    },
    "UpdateRetentionPolicyBody": {
      "type": "object",
      "properties": {
        "retentionPolicy": {
          "$ref": "#/definitions/RetentionPolicy",
          "description": "If absent, the retention policy is removed (reverts to default/keep-forever)."
        }
      },
      "example": {
        "retentionPolicy": {
          "keepForever": {}
        }
      }
    },
    "DeleteChannelWithTagsRequest": {
      "type": "object",
      "properties": {
        "dataSourceRid": {
          "type": "string"
        },
        "channel": {
          "type": "string",
          "description": "If channel is provided, only channels with tags matching that channel will be deleted."
        },
        "tags": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "description": "At least one tag must be specified in the request. Deletes all data containing the specified tags.",
          "minProperties": 1,
          "x-constraints": [
            "At least 1 entrie."
          ]
        },
        "apply": {
          "type": "boolean",
          "description": "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."
        }
      },
      "required": [
        "dataSourceRid"
      ],
      "example": {
        "dataSourceRid": "<data source rid>"
      }
    },
    "DeleteChannelWithTagsResponse": {
      "type": "object",
      "properties": {
        "channelWithTags": {
          "type": "array",
          "items": {
            "type": "object",
            "$ref": "#/definitions/ChannelWithTags"
          },
          "description": "The list of ChannelWithTags that were deleted or would be deleted (when apply is false)."
        }
      }
    },
    "DeleteDataRequest": {
      "type": "object",
      "properties": {
        "dataSourceRid": {
          "type": "string"
        },
        "timeRange": {
          "$ref": "#/definitions/Range",
          "description": "If specified, will only delete data within the given time range. If not specified, will delete data across all time."
        },
        "tags": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "description": "If specified, will only delete data that fully matches the given tags. If not specified, will delete data across all tags."
        },
        "channelNames": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "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": {
          "type": "boolean",
          "description": "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."
        }
      },
      "example": {
        "dataSourceRid": "<data source rid>",
        "timeRange": {
          "start": {
            "seconds": "1",
            "nanos": "1"
          },
          "end": {
            "seconds": "1",
            "nanos": "1"
          }
        },
        "tags": {
          "<key>": "<value>"
        },
        "channelNames": [
          "<channel names>"
        ],
        "deleteMetadata": true
      }
    },
    "DeleteDataResponse": {
      "type": "object"
    },
    "DeleteDatasetRetentionExemptionResponse": {
      "type": "object"
    },
    "GetDatasetRetentionWatermarkResponse": {
      "type": "object",
      "properties": {
        "watermark": {
          "$ref": "#/definitions/Timestamp"
        }
      }
    },
    "KeepForever": {
      "type": "object"
    },
    "KeepUntilExpiry": {
      "type": "object",
      "properties": {
        "expiryDays": {
          "type": "integer",
          "format": "int32",
          "minimum": 0,
          "exclusiveMinimum": true,
          "x-constraints": [
            "Greater than 0."
          ]
        }
      }
    },
    "ListDatasetRetentionExemptionsRequest": {
      "type": "object",
      "properties": {
        "datasetRid": {
          "type": "string"
        },
        "bounds": {
          "$ref": "#/definitions/Range",
          "description": "Filter exemptions that overlap with this time range."
        },
        "pageSize": {
          "type": "integer",
          "format": "int32",
          "minimum": 1,
          "maximum": 1000,
          "x-constraints": [
            "From 1 to 1,000."
          ]
        },
        "nextPageToken": {
          "type": "string"
        }
      },
      "required": [
        "datasetRid",
        "bounds"
      ],
      "example": {
        "datasetRid": "<dataset rid>",
        "bounds": {
          "start": {
            "seconds": "1",
            "nanos": "1"
          },
          "end": {
            "seconds": "1",
            "nanos": "1"
          }
        }
      }
    },
    "ListDatasetRetentionExemptionsResponse": {
      "type": "object",
      "properties": {
        "exemptions": {
          "type": "array",
          "items": {
            "type": "object",
            "$ref": "#/definitions/DatasetRetentionExemption"
          }
        },
        "nextPageToken": {
          "type": "string"
        }
      }
    },
    "RetentionPolicy": {
      "type": "object",
      "properties": {
        "keepForever": {
          "$ref": "#/definitions/KeepForever"
        },
        "keepUntilExpiry": {
          "$ref": "#/definitions/KeepUntilExpiry"
        }
      },
      "x-oneofs": [
        {
          "fields": [
            "keepForever",
            "keepUntilExpiry"
          ],
          "required": true
        }
      ],
      "description": "Set exactly one of the fields below.",
      "example": {
        "keepForever": {}
      }
    },
    "UndeleteChannelWithTagsRequest": {
      "type": "object",
      "properties": {
        "dataSourceRid": {
          "type": "string"
        },
        "channelWithTags": {
          "type": "array",
          "items": {
            "type": "object",
            "$ref": "#/definitions/ChannelWithTags"
          },
          "minItems": 1,
          "maxItems": 1000,
          "x-constraints": [
            "1 to 1,000 items."
          ]
        }
      },
      "required": [
        "dataSourceRid"
      ],
      "example": {
        "dataSourceRid": "<data source rid>"
      }
    },
    "UndeleteChannelWithTagsResponse": {
      "type": "object"
    },
    "UpdateDatasetRetentionWatermarkResponse": {
      "type": "object",
      "properties": {
        "watermark": {
          "$ref": "#/definitions/Timestamp"
        }
      }
    },
    "UpdateRetentionPolicyResponse": {
      "type": "object"
    },
    "UpsertDatasetRetentionExemptionRequest": {
      "type": "object",
      "properties": {
        "datasetRid": {
          "type": "string"
        },
        "sourceId": {
          "type": "string"
        },
        "bounds": {
          "$ref": "#/definitions/Range",
          "description": "Inclusive time range to exempt from retention."
        },
        "description": {
          "type": "string",
          "maxLength": 1024,
          "x-constraints": [
            "At most 1,024 characters."
          ]
        }
      },
      "required": [
        "datasetRid",
        "sourceId",
        "bounds"
      ],
      "example": {
        "datasetRid": "<dataset rid>",
        "sourceId": "<source id>",
        "bounds": {
          "start": {
            "seconds": "1",
            "nanos": "1"
          },
          "end": {
            "seconds": "1",
            "nanos": "1"
          }
        }
      }
    },
    "UpsertDatasetRetentionExemptionResponse": {
      "type": "object",
      "properties": {
        "exemption": {
          "$ref": "#/definitions/DatasetRetentionExemption"
        }
      }
    },
    "Range": {
      "type": "object",
      "properties": {
        "start": {
          "$ref": "#/definitions/Timestamp"
        },
        "end": {
          "$ref": "#/definitions/Timestamp"
        }
      },
      "description": "Deprecated for new APIs. Define an API-owned range with the endpoint semantics it needs instead.",
      "x-deprecated": true
    },
    "Timestamp": {
      "type": "object",
      "properties": {
        "seconds": {
          "type": "string",
          "format": "int64"
        },
        "nanos": {
          "type": "string",
          "format": "int64"
        }
      },
      "description": "Deprecated for new APIs. Use google.protobuf.Timestamp for absolute instants.\n\nThis 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.",
      "x-deprecated": true
    }
  },
  "securityDefinitions": {
    "ApiKey": {
      "type": "apiKey",
      "in": "header",
      "name": "Authorization",
      "description": "Your API key as a bearer token: `Authorization: Bearer <api key>`."
    }
  },
  "security": [
    {
      "ApiKey": []
    }
  ]
}
