# DELETE /v1/scans/{id}

Delete a stored scan

Deletes a scan the account still holds, before its retention window would have ended: the stored result, its history row and its thumbnail. It cannot be undone – the scan can no longer be read, listed or replayed through an `Idempotency-Key`. The credit the scan drew is not returned, and the period's usage counters keep counting it. Only a live key deletes, and only its own account's scans; anything else – an unknown id, another account's scan, a scan whose window has passed, a sandbox key – is `404`.

Deletes a stored scan before its retention window would have ended: the stored result, its history row and its thumbnail. It cannot be undone.

After it, the scan is neither read by `GET /v1/scans/{id}` nor listed by `GET /v1/scans`, and for 24 hours a retry under the `Idempotency-Key` that created it answers 409 `idempotency_replay_unavailable` instead of recognizing again. After that the key is forgotten, as it is for a scan kept for zero hours.

The credit the scan drew is not returned, and the period's usage counters keep counting it.

Send it with no body and no `Content-Type` header. A JSON content type with an empty body is refused as `invalid_request`.

## Request

| | |
|---|---|
| Method | `DELETE` |
| Path | `/v1/scans/{id}` |
| Authentication | `Authorization: Bearer <api key>` |

### Path parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `id` | string | yes | Scan identifier: a UUID version 7 (RFC 9562), canonical lower-case `8-4-4-4-12`. Its leading 48 bits are the millisecond the scan was made, so ids sort in the order the scans happened – but treat the value as opaque: nothing else about it is part of the contract. |

## Responses

### 200

The scan was deleted.

Body: `ScanDeletion`.

| Field | Type | Description |
|---|---|---|
| `id` | ScanId | Scan identifier: a UUID version 7 (RFC 9562), canonical lower-case `8-4-4-4-12`. Its leading 48 bits are the millisecond the scan was made, so ids sort in the order the scans happened – but treat the value as opaque: nothing else about it is part of the contract. |
| `deleted` | boolean | Always true: the stored result is gone and cannot be read back. |

```json
{
  "id": "01a0af18-cd8d-7a61-9f2d-4c7b8e105da3",
  "deleted": true
}
```

### 401

Missing or malformed `Authorization: Bearer <api key>` header, or an unknown key.

Body: `ErrorResponse`.

```json
{
  "error": {
    "code": "unauthorized",
    "message": "Send your API key as `Authorization: Bearer <key>`.",
    "docs_url": "https://doc.cheap/docs/errors/unauthorized",
    "request_id": "req_9e6b1f7c-2d4a-4b83-9c51-7f0ad3e8b642",
    "event_id": null
  }
}
```

### 404

No scan with this id exists, or its retention window has passed.

Body: `ErrorResponse`.

```json
{
  "error": {
    "code": "not_found",
    "message": "No scan with id 01a0af18-cd8d-7a61-9f2d-4c7b8e105da3 exists or it has expired.",
    "docs_url": "https://doc.cheap/docs/errors/not_found",
    "request_id": "req_9e6b1f7c-2d4a-4b83-9c51-7f0ad3e8b642",
    "event_id": null
  }
}
```

### 429

Rate limit exceeded for this key or IP.

Body: `ErrorResponse`.

```json
{
  "error": {
    "code": "rate_limited",
    "message": "Sandbox limit of 10 requests per hour per IP reached.",
    "docs_url": "https://doc.cheap/docs/errors/rate_limited",
    "request_id": "req_9e6b1f7c-2d4a-4b83-9c51-7f0ad3e8b642",
    "event_id": null
  }
}
```

### 500

Unexpected failure on the server; the scan was not charged.

Body: `ErrorResponse`.

```json
{
  "error": {
    "code": "internal_error",
    "message": "Unexpected error.",
    "docs_url": "https://doc.cheap/docs/errors/internal_error",
    "request_id": "req_9e6b1f7c-2d4a-4b83-9c51-7f0ad3e8b642",
    "event_id": null
  }
}
```

### 503

Temporarily unable to serve the request: a store this service depends on is unreachable. Nothing was charged and it may be retried, after the `Retry-After` seconds where that header is present.

Body: `ErrorResponse`.

```json
{
  "error": {
    "code": "service_unavailable",
    "message": "The service is temporarily unable to handle this request; nothing was charged. Retry shortly.",
    "docs_url": "https://doc.cheap/docs/errors/service_unavailable",
    "request_id": "req_9e6b1f7c-2d4a-4b83-9c51-7f0ad3e8b642",
    "event_id": null
  }
}
```

## Error codes reachable here

| Code | When | Page |
|---|---|---|
| `internal_error` | The service failed in a way it does not model. Nothing was deleted. | [internal_error](https://doc.cheap/docs/errors/internal_error) |
| `not_found` | No scan with that id is stored for this account – it was never stored, it belongs to another account, its retention window has passed, it was already deleted, or the key is a sandbox key. The cases are not distinguished. | [not_found](https://doc.cheap/docs/errors/not_found) |
| `rate_limited` | The caller is over the rate limit for its key kind. | [rate_limited](https://doc.cheap/docs/errors/rate_limited) |
| `service_unavailable` | A store this endpoint writes to is unreachable, so nothing was deleted; retry after the `Retry-After` seconds. | [service_unavailable](https://doc.cheap/docs/errors/service_unavailable) |
| `unauthorized` | The `Authorization` header is missing, malformed or names an unknown key. | [unauthorized](https://doc.cheap/docs/errors/unauthorized) |

Every error body carries the same shape; the full list is on [Errors](https://doc.cheap/docs/reference/errors).
