---
title: "Delete Custom Skill"
method: DELETE
path: "/skills/{public_id}"
tags: ["SKILLS"]
---

# Delete Custom Skill

`DELETE /skills/{public_id}`

Delete a skill: drop its attachments, its row, and its bundle.

The row is soft-deleted to keep an audit trail, but the bundle objects are
removed — there is no undelete, so retaining them would grow storage for a
recovery path that does not exist. The row is marked first so the user's
delete is durable; a failed object delete is logged rather than raised,
since the skill is already gone from their view.

The row is read under ``FOR UPDATE`` because ``bundle_token`` and ``files``
are read here and then used to delete objects. Without the lock a concurrent
bundle write can land its compare-and-swap between the two, and this request
deletes the prefix that write just retired while the row now names one whose
objects nothing will ever remove.

## Path parameters

- `public_id` string, required

## Response `200`

Successful Response

- StandardResponse
  - `ok` boolean, required

## Other responses

- `403` — Not the skill's creator
- `404` — Skill not found
- `422` — Validation Error

## Changes

- **2026-09-02** `fcb62c79da95` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/myaltimate/apis/fastapi/changes/skills/:public_id/delete.md)

---

[API](https://skmtc.dev/myaltimate/apis/fastapi.md) · [All operations](https://skmtc.dev/myaltimate/apis/fastapi/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/myaltimate/fastapi/revisions/b8f442483dc9/schema)
