nitinkg
(Nitin Gupta)
April 22, 2026, 8:38am
1
Hi,
I’m trying to delete a draft using the API:
DELETE /drafts/{draft_key}.json
The draft exists (verified via GET /drafts.json) and I’m using the correct draft_key and sequence.
API Request (Postman / backend)
DELETE https://<base_url>/drafts/{draft_key}.json
Headers:
Api-Key: <api_key>
Api-Username: <username>
Content-Type: application/x-www-form-urlencoded / application/json
Body (tried both):
x-www-form-urlencoded:
draft_key=new_topic_xxxxx
sequence=12
or raw JSON:
{
"draft_key": "new_topic_xxxxx",
"sequence": 12
}
Response
{
"errors": ["The requested URL or resource could not be found."],
"error_type": "not_found"
}
From UI (works)
The same delete works from the browser using:
DELETE /drafts/{draft_key}.json
form data: draft_key + sequence
session cookies + CSRF token
Question
Is draft deletion supported via API key auth, same as the other APIs? If supported, what is the correct way to call this endpoint?
Thanks.
Have you tried passing the username as a query param as well? (aka. adding ?username=<username> to the URL)
Looks like we were not being quite consistent with how we allowed the API to fall-back to the Api-Username username when no username query param was being provided.
That should be fixed with
main ← fetch-target-user-helper
opened 10:29AM - 22 Apr 26 UTC
Admin callers using the API to `DELETE /drafts/:id.json` or `DELETE /review/:id.… json` received a `not_found` error when the `username` param was omitted, even though the resource existed and was owned by the API user (`Api-Username`). The destroy actions always called `fetch_user_from_params` on the API path, which raises `Discourse::NotFound` when neither `username` nor `external_id` is provided — forcing callers to redundantly pass `username=<self>` to delete their own resources.
Extract the target-user resolution into a shared `fetch_target_user` helper in `ApplicationController` that mirrors the pattern already used by `topics#set_notifications`: for API requests, an admin can target another user via `username`/`external_id`; otherwise the action operates on `current_user`. This also aligns API capabilities with the UI — non-admin API callers can now manage their own drafts/reviewables, matching what they can already do via the web.
Migrated call sites:
- `DraftsController#destroy` and `#bulk_destroy`
- `ReviewablesController#destroy`
- `TopicsController#set_notifications` (now uses the helper instead of its inline version)
https://meta.discourse.org/t/401220