diff --git a/specification/DigitalOcean-public.v2.yaml b/specification/DigitalOcean-public.v2.yaml index eba28b02b..3c1682d2b 100644 --- a/specification/DigitalOcean-public.v2.yaml +++ b/specification/DigitalOcean-public.v2.yaml @@ -586,8 +586,9 @@ tags: Use the consent endpoints to manage whether signals collection is enabled for each agent, the session endpoints to browse agent - conversations and their detected signals, and the export endpoints - to create downloadable archives of signals data for offline analysis. + conversations and their detected signals, the export endpoints + to create downloadable archives of signals data for offline analysis, + and the deletion endpoints to permanently delete signals data. - name: Sizes description: |- @@ -1890,6 +1891,17 @@ paths: get: $ref: "resources/signals/signals_get_export_download.yml" + /v1/signals/deletions: + get: + $ref: "resources/signals/signals_list_deletions.yml" + + post: + $ref: "resources/signals/signals_create_deletion.yml" + + /v1/signals/deletions/{deletion_id}: + get: + $ref: "resources/signals/signals_get_deletion.yml" + /v2/kubernetes/clusters: get: $ref: "resources/kubernetes/kubernetes_list_clusters.yml" diff --git a/specification/resources/signals/examples/curl/signals_create_deletion.yml b/specification/resources/signals/examples/curl/signals_create_deletion.yml new file mode 100644 index 000000000..1b847dd1f --- /dev/null +++ b/specification/resources/signals/examples/curl/signals_create_deletion.yml @@ -0,0 +1,7 @@ +lang: cURL +source: |- + curl -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + -d '{"type":"agent","team_id":12345678,"agent_id":"01a10d3f-2c09-764f-99f8-458e521627f3"}' \ + "https://api.digitalocean.com/v1/signals/deletions" diff --git a/specification/resources/signals/examples/curl/signals_get_deletion.yml b/specification/resources/signals/examples/curl/signals_get_deletion.yml new file mode 100644 index 000000000..1b28c9245 --- /dev/null +++ b/specification/resources/signals/examples/curl/signals_get_deletion.yml @@ -0,0 +1,5 @@ +lang: cURL +source: |- + curl -X GET \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + "https://api.digitalocean.com/v1/signals/deletions/01J9ZX0N5Q7M2K3R4S5T6V7W8X" diff --git a/specification/resources/signals/examples/curl/signals_list_deletions.yml b/specification/resources/signals/examples/curl/signals_list_deletions.yml new file mode 100644 index 000000000..103a18c05 --- /dev/null +++ b/specification/resources/signals/examples/curl/signals_list_deletions.yml @@ -0,0 +1,5 @@ +lang: cURL +source: |- + curl -X GET \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + "https://api.digitalocean.com/v1/signals/deletions?limit=20" diff --git a/specification/resources/signals/models/create_deletion_request.yml b/specification/resources/signals/models/create_deletion_request.yml new file mode 100644 index 000000000..eea28cfb5 --- /dev/null +++ b/specification/resources/signals/models/create_deletion_request.yml @@ -0,0 +1,30 @@ +type: object +description: Request body to create a new signals data deletion job. +properties: + type: + type: string + description: >- + The scope of the deletion. `agent` deletes data for one agent and + requires `agent_id`. `inference` deletes data for the team's Serverless + Inference requests. + enum: + - agent + - inference + example: agent + team_id: + type: integer + format: int64 + description: The team whose data should be deleted. Must match the authenticated team. + example: 12345678 + agent_id: + type: string + format: uuid + description: >- + The agent whose data should be deleted. For Harness Runtime, this is the + Environment Config ID. Required when `type` is `agent`; must be omitted + when `type` is `inference`. + example: 01a10d3f-2c09-764f-99f8-458e521627f3 +required: + - type + - team_id +additionalProperties: false diff --git a/specification/resources/signals/models/deletion_job.yml b/specification/resources/signals/models/deletion_job.yml new file mode 100644 index 000000000..e2375ade5 --- /dev/null +++ b/specification/resources/signals/models/deletion_job.yml @@ -0,0 +1,65 @@ +type: object +description: A deletion job that permanently removes signals data for an agent or for a team's Serverless Inference usage. +properties: + team_id: + type: integer + format: int64 + description: The team that owns the deletion job. + example: 12345678 + deletion_id: + type: string + description: The unique identifier for the deletion job (ULID). + example: 01J9ZX0N5Q7M2K3R4S5T6V7W8X + type: + type: string + description: >- + The scope of the deletion. `agent` deletes data for one agent. + `inference` deletes data for the team's Serverless Inference requests. + enum: + - agent + - inference + example: agent + agent_id: + type: string + format: uuid + description: >- + The agent whose data is being deleted. For Harness Runtime, this is the + Environment Config ID. Only present for `agent` deletions. + example: 01a10d3f-2c09-764f-99f8-458e521627f3 + status: + type: string + description: The current status of the deletion job. + enum: + - queued + - running + - complete + - failed + example: running + error_message: + type: string + nullable: true + description: Error message if the deletion failed, or null otherwise. + example: null + created_at: + type: integer + format: int64 + description: Unix timestamp when the deletion job was created. + example: 1791036405 + started_at: + type: integer + format: int64 + nullable: true + description: Unix timestamp when processing started, or null if still queued. + example: 1791036410 + completed_at: + type: integer + format: int64 + nullable: true + description: Unix timestamp when the deletion finished, or null if still in progress. + example: null +required: + - team_id + - deletion_id + - type + - status + - created_at diff --git a/specification/resources/signals/parameters.yml b/specification/resources/signals/parameters.yml index 30fd3db09..963aa9936 100644 --- a/specification/resources/signals/parameters.yml +++ b/specification/resources/signals/parameters.yml @@ -28,6 +28,15 @@ export_id: format: uuid example: 9f13c09c-c877-436b-9863-dcc39c9dd737 +deletion_id: + in: path + name: deletion_id + description: A unique identifier for a data deletion job. + required: true + schema: + type: string + example: 01J9ZX0N5Q7M2K3R4S5T6V7W8X + limit: in: query name: limit diff --git a/specification/resources/signals/responses/deletion_job_accepted_response.yml b/specification/resources/signals/responses/deletion_job_accepted_response.yml new file mode 100644 index 000000000..32ab717df --- /dev/null +++ b/specification/resources/signals/responses/deletion_job_accepted_response.yml @@ -0,0 +1,25 @@ +description: >- + The deletion job was accepted and will be processed asynchronously. + +headers: + ratelimit-limit: + $ref: '../../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../../shared/headers.yml#/ratelimit-reset' + +content: + application/json: + schema: + $ref: '../models/deletion_job.yml' + example: + team_id: 12345678 + deletion_id: 01J9ZX0N5Q7M2K3R4S5T6V7W8X + type: agent + agent_id: 01a10d3f-2c09-764f-99f8-458e521627f3 + status: queued + error_message: null + created_at: 1791036405 + started_at: null + completed_at: null diff --git a/specification/resources/signals/responses/deletion_job_response.yml b/specification/resources/signals/responses/deletion_job_response.yml new file mode 100644 index 000000000..405438ecd --- /dev/null +++ b/specification/resources/signals/responses/deletion_job_response.yml @@ -0,0 +1,24 @@ +description: A single deletion job. + +headers: + ratelimit-limit: + $ref: '../../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../../shared/headers.yml#/ratelimit-reset' + +content: + application/json: + schema: + $ref: '../models/deletion_job.yml' + example: + team_id: 12345678 + deletion_id: 01J9ZX0N5Q7M2K3R4S5T6V7W8X + type: agent + agent_id: 01a10d3f-2c09-764f-99f8-458e521627f3 + status: running + error_message: null + created_at: 1791036405 + started_at: 1791036410 + completed_at: null diff --git a/specification/resources/signals/responses/list_deletions_response.yml b/specification/resources/signals/responses/list_deletions_response.yml new file mode 100644 index 000000000..8b5a8c888 --- /dev/null +++ b/specification/resources/signals/responses/list_deletions_response.yml @@ -0,0 +1,63 @@ +description: A paginated list of deletion jobs. + +headers: + ratelimit-limit: + $ref: '../../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../../shared/headers.yml#/ratelimit-reset' + +content: + application/json: + schema: + type: object + properties: + edges: + type: array + items: + type: object + properties: + cursor: + type: string + description: An opaque cursor for pagination. + example: eyJkIjoiMDFKOVpYME41UTdNMkszUjRTNVQ2VjdXOFgifQ== + node: + $ref: '../models/deletion_job.yml' + page_info: + type: object + properties: + has_next_page: + type: boolean + description: Whether there are more results after this page. + end_cursor: + type: string + description: >- + Cursor of the last item. Pass as `after` to fetch the next + page. Present only when there are more results. + example: eyJkIjoiMDFKOVpXN0E4QjlDMEQxRTJGM0c0SDVKNksifQ== + example: + edges: + - cursor: eyJkIjoiMDFKOVpYME41UTdNMkszUjRTNVQ2VjdXOFgifQ== + node: + team_id: 12345678 + deletion_id: 01J9ZX0N5Q7M2K3R4S5T6V7W8X + type: agent + agent_id: 01a10d3f-2c09-764f-99f8-458e521627f3 + status: running + error_message: null + created_at: 1791036405 + started_at: 1791036410 + completed_at: null + - cursor: eyJkIjoiMDFKOVpXN0E4QjlDMEQxRTJGM0c0SDVKNksifQ== + node: + team_id: 12345678 + deletion_id: 01J9ZW7A8B9C0D1E2F3G4H5J6K + type: inference + status: complete + error_message: null + created_at: 1790950005 + started_at: 1790950010 + completed_at: 1790950605 + page_info: + has_next_page: false diff --git a/specification/resources/signals/signals_create_deletion.yml b/specification/resources/signals/signals_create_deletion.yml new file mode 100644 index 000000000..d7365e5f7 --- /dev/null +++ b/specification/resources/signals/signals_create_deletion.yml @@ -0,0 +1,82 @@ +operationId: signals_create_deletion + +summary: Create a Data Deletion Job + +description: | + To permanently delete signals data, send a POST request to + `/v1/signals/deletions`. + + Two deletion types are supported: + + - `agent` — deletes sessions, dialogues, and signal reports for one agent. + Requires `agent_id`. The agent's data is hidden immediately and signals + collection is disabled for the agent, even if the job later fails. Wait + until the job is complete before enabling signals for the agent again. + - `inference` — deletes sessions, dialogues, and signal reports for the + team's Serverless Inference requests made before the deletion. Signals + continues to analyze new requests. + + Deletion is permanent and cannot be undone. The job runs asynchronously; + poll the get endpoint to check status. To retry a failed job, send the same + request again. Export files created earlier are not deleted and remain + available until they expire. + + The endpoint is idempotent: if a queued or running job already exists for + the same target, it is returned with `200 OK`. A new job returns + `202 Accepted`. Each team can have a limited number of active jobs; + requests beyond that limit return `429 Too Many Requests`. + +tags: + - Signals + +requestBody: + required: true + content: + application/json: + schema: + $ref: 'models/create_deletion_request.yml' + examples: + Agent: + value: + type: agent + team_id: 12345678 + agent_id: 01a10d3f-2c09-764f-99f8-458e521627f3 + Inference: + value: + type: inference + team_id: 12345678 + +responses: + '200': + $ref: 'responses/deletion_job_response.yml' + + '202': + $ref: 'responses/deletion_job_accepted_response.yml' + + '400': + $ref: '../../shared/responses/bad_request.yml' + + '401': + $ref: '../../shared/responses/unauthorized.yml' + + '403': + $ref: '../../shared/responses/forbidden.yml' + + '404': + $ref: '../../shared/responses/not_found.yml' + + '429': + $ref: '../../shared/responses/too_many_requests.yml' + + '500': + $ref: '../../shared/responses/server_error.yml' + + default: + $ref: '../../shared/responses/unexpected_error.yml' + +x-codeSamples: + - $ref: 'examples/curl/signals_create_deletion.yml' + +security: + - bearer_auth: + - 'signals:delete' diff --git a/specification/resources/signals/signals_get_deletion.yml b/specification/resources/signals/signals_get_deletion.yml new file mode 100644 index 000000000..756cd6863 --- /dev/null +++ b/specification/resources/signals/signals_get_deletion.yml @@ -0,0 +1,39 @@ +operationId: signals_get_deletion + +summary: Retrieve a Data Deletion Job + +description: | + To retrieve the status of a signals data deletion job, send a GET request + to `/v1/signals/deletions/{deletion_id}`. + +tags: + - Signals + +parameters: + - $ref: 'parameters.yml#/deletion_id' + +responses: + '200': + $ref: 'responses/deletion_job_response.yml' + + '401': + $ref: '../../shared/responses/unauthorized.yml' + + '404': + $ref: '../../shared/responses/not_found.yml' + + '429': + $ref: '../../shared/responses/too_many_requests.yml' + + '500': + $ref: '../../shared/responses/server_error.yml' + + default: + $ref: '../../shared/responses/unexpected_error.yml' + +x-codeSamples: + - $ref: 'examples/curl/signals_get_deletion.yml' + +security: + - bearer_auth: + - 'signals:read' diff --git a/specification/resources/signals/signals_list_deletions.yml b/specification/resources/signals/signals_list_deletions.yml new file mode 100644 index 000000000..e3bba5ce1 --- /dev/null +++ b/specification/resources/signals/signals_list_deletions.yml @@ -0,0 +1,41 @@ +operationId: signals_list_deletions + +summary: List Data Deletion Jobs + +description: | + To list signals data deletion jobs for your team, newest first, send a GET + request to `/v1/signals/deletions`. Results are paginated using + cursor-based pagination with `limit` and `after` parameters. + +tags: + - Signals + +parameters: + - $ref: 'parameters.yml#/limit' + - $ref: 'parameters.yml#/after' + +responses: + '200': + $ref: 'responses/list_deletions_response.yml' + + '400': + $ref: '../../shared/responses/bad_request.yml' + + '401': + $ref: '../../shared/responses/unauthorized.yml' + + '429': + $ref: '../../shared/responses/too_many_requests.yml' + + '500': + $ref: '../../shared/responses/server_error.yml' + + default: + $ref: '../../shared/responses/unexpected_error.yml' + +x-codeSamples: + - $ref: 'examples/curl/signals_list_deletions.yml' + +security: + - bearer_auth: + - 'signals:read'