HTTP DELETE メソッド:完全ガイド (2026年版)
REST APIにおけるHTTP DELETEメソッドについて知っておくべきことのすべて
Hyperealで構築を始めよう
Kling、Flux、Sora、Veoなどに単一のAPIでアクセス。無料クレジットで開始、数百万規模まで拡張可能。
クレジットカード不要 • 10万人以上の開発者 • エンタープライズ対応
HTTP DELETE メソッド:完全ガイド (2026年版)
HTTP DELETE メソッドは、サーバーからリソースを削除するために使用されます。これは RESTful API で使用される主要な4つの HTTP メソッド(GET、POST、PUT と並ぶ)の1つであり、API を扱う開発者にとって正しく理解しておくことは不可欠です。
このガイドでは、DELETE メソッドの仕組み、使用すべき場面、クライアント側とサーバー側での実装方法、および避けるべき一般的な間違いについて詳しく解説します。
HTTP DELETE メソッドとは?
DELETE メソッドは、指定された URI によって識別されるリソースを削除するようサーバーに要求します。DELETE 操作が成功すると、そのリソースはその場所に存在しなくなります。
DELETE /api/v1/users/42 HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
サーバーは結果を示すステータスコードで応答します。
HTTP/1.1 204 No Content
主な特徴
| 特性 | 値 | 説明 |
|---|---|---|
| リクエストボディ | 任意(通常は空) | ほとんどの実装ではボディを無視します |
| レスポンスボディ | 任意 | 204 はボディなし、200 は詳細を含む場合があります |
| べき等性 (Idempotent) | あり | 同じリソースを2回削除しても結果は変わりません |
| 安全性 (Safe) | なし | サーバーの状態を変更します |
| キャッシュ可能性 | なし | レスポンスはキャッシュすべきではありません |
DELETE レスポンスステータスコード
| ステータスコード | 意味 | 使用場面 |
|---|---|---|
| 200 OK | リソース削除完了。レスポンスに詳細を含む | 確認用のボディを返す場合 |
| 202 Accepted | 削除処理をキューに登録済み | 非同期削除(例:バックグラウンドジョブ)の場合 |
| 204 No Content | リソース削除完了。レスポンスボディなし | DELETE において最も一般的なレスポンス |
| 404 Not Found | リソースが存在しない | リソースが最初から作成されていない場合 |
| 401 Unauthorized | 認証が必要 | 認証情報が不足しているか無効な場合 |
| 403 Forbidden | 認証済みだが権限不足 | ユーザーに削除権限がない場合 |
| 409 Conflict | 現在の状態により削除不可 | 例:リソースに依存するレコードがある場合 |
200 と 204 の選択
# 204 No Content -- 最も一般的。レスポンスボディなし。
DELETE /api/v1/users/42
Response: 204 No Content
# 200 OK -- 削除されたリソースを返したい場合
DELETE /api/v1/users/42
Response: 200 OK
Body: {"id": 42, "name": "John", "deleted": true, "deletedAt": "2026-02-06T12:00:00Z"}
クライアントが詳細な確認を必要としない場合は 204 を使用します。元に戻す機能(Undo)や監査ログのために削除されたリソースを確認することにメリットがある場合は 200 を使用します。
実践:クライアント側の例
cURL
# シンプルな DELETE リクエスト
curl -X DELETE https://api.example.com/v1/users/42
# 認証付き DELETE
curl -X DELETE \
-H "Authorization: Bearer your_token_here" \
https://api.example.com/v1/users/42
# APIキー付き DELETE
curl -X DELETE \
-H "X-API-Key: your_api_key" \
https://api.example.com/v1/users/42
JavaScript (Fetch API)
// 基本的な DELETE リクエスト
const response = await fetch("https://api.example.com/v1/users/42", {
method: "DELETE",
headers: {
"Authorization": "Bearer your_token_here",
},
});
if (response.status === 204) {
console.log("User deleted successfully");
} else if (response.status === 404) {
console.log("User not found");
}
JavaScript (Axios)
import axios from "axios";
try {
await axios.delete("https://api.example.com/v1/users/42", {
headers: {
"Authorization": "Bearer your_token_here",
},
});
console.log("Deleted successfully");
} catch (error) {
if (error.response?.status === 404) {
console.log("User not found");
} else if (error.response?.status === 403) {
console.log("Not authorized to delete this user");
}
}
Python (requests)
import requests
response = requests.delete(
"https://api.example.com/v1/users/42",
headers={"Authorization": "Bearer your_token_here"}
)
if response.status_code == 204:
print("Deleted successfully")
elif response.status_code == 404:
print("User not found")
elif response.status_code == 409:
print("Cannot delete: user has dependent records")
Go
package main
import (
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("DELETE", "https://api.example.com/v1/users/42", nil)
req.Header.Set("Authorization", "Bearer your_token_here")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
switch resp.StatusCode {
case 204:
fmt.Println("Deleted successfully")
case 404:
fmt.Println("User not found")
case 403:
fmt.Println("Not authorized")
}
}
実践:サーバー側の例
Node.js (Express)
import express from "express";
const app = express();
app.delete("/api/v1/users/:id", async (req, res) => {
const { id } = req.params;
// ユーザーの存在確認
const user = await db.users.findById(id);
if (!user) {
return res.status(404).json({ error: "User not found" });
}
// 依存レコードのチェック
const orders = await db.orders.countByUserId(id);
if (orders > 0) {
return res.status(409).json({
error: "Cannot delete user with active orders",
orderCount: orders,
});
}
// ユーザーを削除
await db.users.deleteById(id);
// 204 No Content を返す
res.status(204).send();
});
Python (FastAPI)
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.delete("/api/v1/users/{user_id}", status_code=204)
async def delete_user(user_id: int):
user = await db.users.find_by_id(user_id)
if not user:
raise HTTPException(status_code=404, detail="User not found")
if await db.orders.count_by_user_id(user_id) > 0:
raise HTTPException(
status_code=409,
detail="Cannot delete user with active orders"
)
await db.users.delete_by_id(user_id)
# FastAPI は自動的にボディなしで 204 を返します
Go (net/http)
func deleteUserHandler(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
user, err := db.FindUserByID(id)
if err != nil || user == nil {
http.Error(w, "User not found", http.StatusNotFound)
return
}
if err := db.DeleteUser(id); err != nil {
http.Error(w, "Failed to delete user", http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusNoContent)
}
べき等性(Idempotency):なぜ重要か
DELETE メソッドは「べき等」です。つまり、同じ DELETE リクエストを複数回行っても、結果(リソースが削除されている、または存在しない状態)は同じになります。
DELETE /api/v1/users/42 -> 204 No Content (ユーザー削除成功)
DELETE /api/v1/users/42 -> 204 No Content (既に削除済み、結果は同じ)
ただし、ニュアンスの違いがあります。一部の API は、リソースが既に存在しないため、2回目以降のリクエストに対して 404 を返します。どちらのアプローチも有効です。
| アプローチ | 初回リクエスト | 2回目以降 | 厳密なべき等性 |
|---|---|---|---|
| 常に 204 | 204 | 204 | はい |
| 未存在なら 404 | 204 | 404 | 技術的には はい (リソースは削除されたまま) |
「常に 204」を返すアプローチは、クライアントが「今削除されたのか」と「既に削除されていたのか」を区別する必要がないため、よりシンプルです。
論理削除 (Soft Delete) vs 物理削除 (Hard Delete)
本番環境のシステムでは、多くのチームがデータを実際に削除する代わりに論理削除を実装しています。
物理削除 (Hard Delete)
-- データは永久に削除されます
DELETE FROM users WHERE id = 42;
論理削除 (Soft Delete)
-- データは削除済みとしてマークされますが、保持されます
UPDATE users SET deleted_at = NOW(), is_active = false WHERE id = 42;
| アプローチ | 復旧可能性 | ストレージ | コンプライアンス | 複雑さ |
|---|---|---|---|---|
| 物理削除 | 不可 | 節約できる | GDPRに対応しやすい | 単純 |
| 論理削除 | 可能 | 蓄積される | パージ(一掃)が必要 | 中程度 |
クライアントから見れば API エンドポイントは同じ(DELETE /api/v1/users/42)です。違いはサーバー側の実装にあります。
一括削除 (Bulk Delete)
複数のリソースを一度に削除する必要がある場合があります。一般的なパターンは以下の2つです。
パターン 1: クエリパラメータ
DELETE /api/v1/users?ids=1,2,3,4,5
パターン 2: リクエストボディ
curl -X DELETE https://api.example.com/v1/users \
-H "Content-Type: application/json" \
-d '{"ids": [1, 2, 3, 4, 5]}'
パターン 3: 削除専用エンドポイントへの POST
一部の API は DELETE でボディを送信することを避け、代わりに POST を使用します。
POST /api/v1/users/bulk-delete
Body: {"ids": [1, 2, 3, 4, 5]}
パターン 3 は、一部の HTTP クライアントやプロキシが DELETE リクエストからボディを削除してしまう可能性があるため、最も幅広い互換性があります。
一般的な間違い
1. 認可チェックの欠如
呼び出し元にリソースを削除する権限があることを必ず確認してください。
app.delete("/api/v1/posts/:id", async (req, res) => {
const post = await db.posts.findById(req.params.id);
if (post.authorId !== req.user.id && !req.user.isAdmin) {
return res.status(403).json({ error: "Not authorized" });
}
// ... 削除処理へ進む
});
2. カスケード削除の未処理
親リソースを削除すると、子のレコードが孤立(迷子)になる可能性があります。これを明示的に処理してください。
// ユーザーと関連するすべてのデータを削除
await db.transaction(async (tx) => {
await tx.comments.deleteByUserId(userId);
await tx.posts.deleteByUserId(userId);
await tx.sessions.deleteByUserId(userId);
await tx.users.deleteById(userId);
});
3. 破壊的なアクションに対する確認の欠如
重要なリソースについては、確認用のパラメータを必須にすることを検討してください。
DELETE /api/v1/projects/42?confirm=true
結論
HTTP DELETE メソッドの概念は単純ですが、慎重な実装が必要です。必ず認証と認可を行い、エッジケース(リソース不足、依存レコード)を処理し、データ保持の要件に基づいて論理削除と物理削除のどちらかを選択してください。
メディア生成 API と連携するアプリケーションを構築している場合、Hypereal AI はクリーンな REST API を提供しています。生成された資産の管理、アップロードされた画像の削除、完了したビデオ生成ジョブのクリーンアップなどに DELETE メソッドを活用できるでしょう。
