- API
- 技術 💻
唸るAPI設計8選|冪等性キー・ETag・楽観ロック・Retry-After・Webhook
APIって、使えるかどうかだけでなく設計の賢さが面白いんですよね。「その問題、そうやって解くのか」と唸るものが、けっこうあります。
今回は、仕組みを知って「ほぉー」となったものを8つ集めました。二重決済も、上書き事故も、Botも。「その手があったか」と唸った設計です。1つでも知らなかったら儲けものです。異論・追加も大歓迎です。
① パスワードを送らずに、漏洩を確かめる
いちばんの「ほぉー」から。
「このパスワード、過去の情報漏洩に含まれていませんか」を確かめたい。でも確かめるために送ったら、本末転倒ですよね。Have I Been Pwned の Pwned Passwords API は、この矛盾を解いています。k-匿名性という考え方です。
手元でハッシュ化して、その先頭5文字だけを送る。すると、その5文字で始まるハッシュの残りの部分が数百件まとめて返ってくるんです。あとは自分のものが含まれるかを、手元で照合する。
async function isPwned(password) {
// 1. 手元でハッシュ化
const buf = await crypto.subtle.digest('SHA-1', new TextEncoder().encode(password));
const hash = [...new Uint8Array(buf)]
.map(b => b.toString(16).padStart(2, '0')).join('').toUpperCase();
// 2. 送るのは先頭5文字だけ
const res = await fetch(`https://api.pwnedpasswords.com/range/${hash.slice(0, 5)}`);
const text = await res.text();
// 3. 残りは手元で照合
const hit = text.split('\n').find(line => line.startsWith(hash.slice(5)));
return hit ? Number(hit.split(':')[1]) : 0; // 漏洩回数
}
サーバー側は「誰が何を調べたか」を特定できません。送っていないものは、漏れようがないんですよね。認証不要・レート制限なし・無料です。月180億リクエストをさばいているそうです。
ひとつ注意点があって、入力のたびに叩くと、リクエストの流れからパスワードを推測できてしまいます。入力が終わってから一度だけ呼ぶのが推奨されています。
② 同じリクエストを2回送っても、1回しか実行されない
決済処理を送信した直後に、通信が切れた。……この状況、怖いですよね。届いたのか、届いていないのか分からない。再送すれば二重決済のリスク、送らなければ未処理のリスク。
これを解くのが冪等性キー(Idempotency-Key)です。リクエストに一意のキーを付けて送ります。サーバーは、そのキーで初めて来たリクエストだけを処理して、結果を保存する。
POST /v1/charges
Idempotency-Key: order-2026-0814-001
{ "amount": 5000 }
同じキーで再送されたら、処理はせずに保存済みの結果を返すんです。呼ぶ側は「届いたか不安なら、とりあえず再送していい」状態になります。この安心感、かなり大きいんですよね。
③ 変わっていなければ、本文を返さない
同じデータを定期的に取りに行く処理で効くやつです。
サーバーはレスポンスにETagという識別子を付けて返します。中身が変わると、この値も変わる仕組みですね。
GET /api/items
→ 200 OK
ETag: "v42"
次に取りに行くとき、その値を添えて聞きます。
GET /api/items
If-None-Match: "v42"
→ 304 Not Modified (本文なし)
変わっていなければ、本文を送らない。通信量も処理も、まるごと節約できるんですよね。ブラウザが裏で当たり前にやっていることですが、自分でAPIを叩くときに意識している人は意外と少ないかなと思います。
④ 鍵を渡さずに、一時的なアクセス権だけ配る
ファイルをダウンロードさせたい。でもアクセスキーを相手に渡すわけにはいかない。署名付きURLが、ここを解きます。
サーバー側が「このファイルに、この時刻まで、この操作だけ許す」という情報に署名を付けて、1本のURLにまとめるんです。受け取った側は、そのURLを叩くだけ。ログインも設定も要りません。
そして有効期限が切れれば、自動的に使えなくなる。権限を回収する処理を書かなくていいんですよね。期限つきの入館証を渡すイメージが近いかなと思います。
⑤ 上書き事故を、サーバー側で止める
2人が同じデータを同時に編集して、後から保存した方が勝つ。あの現象です。これも③のETagで防げます。更新するときに、自分が読んだときの値を添えて送るんです。
PUT /api/items/1
If-Match: "v42"
→ 200 OK (まだ誰も更新していない)
→ 412 Precondition Failed (誰かが先に更新していた)
412が返ってきたら、「他の人が編集しました。読み直してください」と伝えられます。データベースにロックをかけずに、衝突だけ検知できる。楽観ロックと呼ばれる考え方ですね。
「たぶん衝突しないだろう」と楽観的に進めて、ぶつかったときだけ対処する。この割り切りが賢いんですよね。
⑥ 「いつ再試行すればいいか」を、教えてくれる
上限に達したとき、429というステータスが返ってきます。そのとき一緒に返ってくるヘッダが親切なんです。
HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1755100800
Retry-After は「何秒後に再試行して」という指示。Remaining は残り回数、Reset は上限が回復する時刻です。つまり、勘で待つ必要がないんですよね。
残り回数を見ながらペースを落とす、という賢い制御も書けます。しかも上限に当たる前に減速できる。エラーが「怒られ」ではなく「案内」になっている設計、いいなと思います。
⑦ 聞きに行かない。向こうから届く
「注文が入ったら知りたい」。素直に作ると、1分ごとに問い合わせる形になりますよね。でも大半は「まだありません」という返事で、無駄が多い。
Webhookは、これを逆転させます。こちらのURLを登録しておくと、イベントが起きたときに向こうから送ってきてくれるんです。新聞を毎朝ポストまで取りに行くか、届けてもらうか。その差ですね。
ただし、届く側には注意が必要です。そのリクエストが本物かどうかを確かめる必要があるので。多くのサービスは、本文に対する署名をヘッダに付けて送ってきます。受け取った側で同じ計算をして、一致するかを確認する。この検証を忘れると、誰でも偽の通知を送れてしまうんですよね。
⑧ ユーザーに何もさせずに、Botを見分ける
「信号機の写真を選んでください」。あれ、正直つらいですよね。しかも最近はAIの方が正解率が高かったりします。
Cloudflare Turnstile のような仕組みは、ユーザーに操作させずに判定します。ブラウザの挙動や環境から、人間らしさを推定する。多くの場合、利用者は何も気づかないうちに通過しているんです。
「難しい問題を解かせて人間を証明する」から「何もしなくても分かる」へ。発想の転換が効いている例だなと思います。
番外編:賢い設計に、共通していること
並べてみて気づいたことがあります。①は「送らない」、③は「返さない」、⑦は「聞きに行かない」。何かを減らすことで問題を解いているんですよね。
②の冪等性キーも、⑤の楽観ロックも、「起きないように厳重に守る」のではなく「起きても大丈夫にする」という発想です。力ずくで解決するのではなく、前提をずらして問題そのものを消す。賢い設計って、だいたいこの形をしている気がします。
RJCの研修でも、APIを扱います
研修は4ヶ月・12段階で、Lv.04〜06でAPI・例外処理・UMLクラス図を扱います。APIを「使う側」の作法を知ると、自分が「作る側」に回ったときの設計も変わってくるんですよね。
そしてTechチームでは、こうした知見を検証して社内で共有しています。一人で全部を追いかけるのは大変ですが、持ち寄れば追いつけます。
よくいただくご質問
Q. どれから知っておくといいですか?
A. ②と⑥かなと思います。通信は必ず失敗するものなので、再送と待ち方を知っていると、堅い実装が書けるようになります。
Q. こういう設計、どうやって身につきますか?
A. 良くできたAPIのドキュメントを読むのがいちばんの近道です。「なんでこの仕様なんだろう」と考えると、だいたい理由があります。
Q. 未経験からでも、理解できるようになりますか?
A. なります。仕組み自体はシンプルなものが多いんですよね。研修でAPIの基礎から扱います。
Q. 話だけ聞くのはアリですか?
A. アリです。まず知るところから。
良い設計は、読むだけで勉強になります
今日の8つ、どれも「その手があったか」と思わせてくれるものでした。こういう仕組みは、自分がAPIを作る側になったときにも効いてきます。使う側で感心した設計は、だいたい真似する価値があるんですよね。
ひとつでも「ほぉー」があったら嬉しいです。みなさんが唸ったAPI設計も、ぜひ教えてください。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。