---
title: "Cancel a price alert (soft-delete; row persists for DSAR + history)"
method: DELETE
path: "/api/alerts/{alert_id}"
tags: ["Alerts"]
---

# Cancel a price alert (soft-delete; row persists for DSAR + history)

`DELETE /api/alerts/{alert_id}`

## Request

- Base URL: `https://www.oxfordledge.com` (the document declares no server; this is the origin it was published from)
- URL: `https://www.oxfordledge.com/api/alerts/{alert_id}`
- Auth: none declared

Soft-cancel the alert. Updates `status='cancelled'` rather than
DELETE so the row survives for DSAR exports + re-arm history. The
F11 30-day GDPR cron is the only path that hard-deletes the row.

Response shape:
  { "ok": True, "id": <alert_id> }   on success
  { "ok": False, "id": <alert_id>, "error": "not_found" }  on 404

Owner-scoped: a user cannot cancel another user's alert by guessing
IDs (helper's WHERE matches both id + user_id).

## Path parameters

- `alert_id` integer, required: The alert id to cancel.

## Response `200`

Successful Response

- AlertDeleteResponse: `DELETE /api/alerts/{id}` response. Frontend reads `data.ok` to decide whether to remove the row from the list-view or surface an error toast; `data.id` echoes the cancelled alert's id so the list-view can find + remove the right row.
  - `ok` boolean, required: True on successful soft-delete; false on not-found.
  - `id` integer, required: Echo of the path parameter for client-side row matching.

## Other responses

- `401`: Unauthorized
- `404`: Not Found
- `422`: Validation Error
- `500`: Internal Server Error

---

[API](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api.md) · [All operations](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api/llms.txt) · [OpenAPI document](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api/revisions/e832a1260f0b?raw)
