API設計の原則と現実のギャップを埋めるには
まず草薙氏は、API設計に適した開発プロセスについて議論する。多くの現場では、APIを実装しながら設計して、コードのコメントなどをもとに、ツールでOpenAPI形式の仕様書を出力して、補足文を付け足す。そんな流れでAPI開発が進んでいくことが多いのではないだろうか。しかし、このやり方では、仕様やドキュメントと実装が乖離してしまい、将来的には技術的負債になることが多いと、草薙氏は問題提起する。
そこで草薙氏が勧めるのが、API仕様を先に決めてから開発する、APIファースト開発というアプローチだ。まずAPIで実現したい機能について、API開発者と利用者が、技術・ビジネスの両面から検討し、合意を得る。この合意は、APIコントラクトと呼ばれ、強い拘束力を持つ取り決めだ。APIコントラクトをもとに仕様書を作成し、モックとテストを用いて仮説を検証し、想定どおりに動作するか検証する。そして最新の状況を反映しながら、開発、テスト、実装、ドキュメント作成のイテレーションを繰り返して開発を進めるスタイルだ。

続いて、良いAPI設計が従うべき原則とは何だろうか。草薙氏が勧めるのは、HTTPの標準仕様やRESTの原則に従うことだ。例えば、HTTPには、メソッドやヘッダ、ステータスコードなど、さまざまな規約が存在している。そしてAPIは、対象となるデータをURLで識別する統一インターフェースの使用、クライアントとサーバの分離、ステートレスな動作を行うといったRESTfulな振る舞いをするのが望ましい。これらに従うことで、利用者の学習が容易になり、バグの混入の防止、パフォーマンスの最適化、再利用性の向上など、さまざまなメリットが生じる。またスケーラブルで、Webのパフォーマンスを引き出す実装を、自然に行うことが可能になる。
しかし現実のAPI設計では、原則だけではうまくいかないケースがつきものだ。多くのAPIで使われている、現実的な実装にも目を向けるべきだと、草薙氏は指摘する。特にポピュラーなサービスのAPI設計には、開発者の試行錯誤や深い議論が反映されている。こうした知見を取り入れることで、より優れたAPIを設計できると、草薙氏は言う。
そこで草薙氏が紹介したのは、欧州の大手ファッションECサイト Zalandoが公開したRESTful API設計のガイドラインだ。基本的にはRESTの原則に従いつつ、自社のサービスの特性に合わせてルールを決めている好例だと草薙氏は言う。Zalandoの他にも、さまざまな企業が、API設計のガイドラインを公開している。それらを参考にしながら、「自社のビジネスに合わせて、それぞれの現場でAPI設計ガイドラインを決めて、それを守りながら開発を進めるのがおすすめだ」と、草薙氏は言う。

次のページでは、それらのAPI設計ガイドラインの中から、代表的なポイントを抜粋して紹介する。
現場で役立つAPI設計のポイント集
(1)APIエンドポイントには明確で一貫性のある名前を使う
RESTの原則では、一意のリソースをURLで表現する。そしてリソースとは物や事象を指すので、通常はURLのパス名に名詞を用いる。動詞や短縮形を用いるのは不適切だ。その際、リソースの集合にアクセスするケースが多いので、一般的には名詞の複数型を用いる。
良い例 | 悪い例 |
---|---|
/products | /getProducts |
/customers | /cust |
/orders | /order-info |
例外:search(慣用的に使われる) |
より複雑なデータを取得する場合、リソース同士の関係をURLで表現する。その際は、あるリソースの個別IDの後に、関連するリソースのパスを続けるのが一般的だ。例えば、特定の商品についての注文一覧や、顧客が複数の住所を持っている場合の一覧を取得する場合、以下のようなURL形式となる。
関係 | 例 |
---|---|
商品の注文 | /products/:product_id/orders |
顧客の住所 | /customers/:customer_id/addresses |
APIエンドポイントは適切に抽象化を行う。データベースのテーブル名をそのままURLとして使うなど、実装に依存した構造をAPIに反映するのは避けるべきだ。またページごとに専用のAPIを設けるなど、アプリの用途に特化しすぎる設計も望ましくない。ただし、内部システム向けのAPIで、パフォーマンス向上などの事情が存在する場合は、この限りではない。
(2)必須情報にはパラメータを使い、追加情報にはクエリ文字列を使う
パスパラメータは、特定の製品情報や、特定の顧客情報など、一意のリソースを指定してアクセスする際に使う。例えば、URLでリソースの集合を指定した後に、IDを付与する形で用いる。
リソース | 例 |
---|---|
特定の製品情報 | /products/12345 |
特定の顧客情報 | /customers/23456 |
特定の注文情報 | /orders/34567 |
クエリパラメータは、フィルタや並べ替えなど、取得するデータのバリエーションを指定するために用いる。クエリパラメータは省略可能な項目にだけ使い、一意のリソースを表すのに必須の項目に使ってはならない。
目的 | 例 |
---|---|
フィルタ | /products?category=electronics |
並べ替え | /products?price=desc |
結果の限定 | /orders?status=pending&limit=10 |
(3)エンドポイントが何をするかに基づいて正しいHTTPメソッドを使用する
エンドポイントで表されるリソースに対してどうアクセスし、どんな操作を行うかを指定するのがHTTPメソッドだ。APIにおいても、HTTPプロトコルの標準仕様に沿って、適切に使用しなければならない。特に、CRUD(Create, Read, Update, Delete)操作は頻繁に行われるため、HTTPメソッドに対応するようにリソースへの操作を行うことが、RESTful APIにおける原則だ。
(4)APIがデータを正しく受け取り、応答できるように設計する
Content-Typeヘッダで、リクエストボディのデータ形式を正しく設定することで、APIサーバが受け取ったデータを適切に解釈でき、また意図したデータが送信されたことを確認できる。逆に、クライアントが受け取りたいデータ形式は、Acceptリクエストヘッダで指定する。レスポンスデータに複数の形式が想定される場合、q(Quality Value)を付与することで、受け取りたい形式の優先度を指定する。サーバはクライアントの希望を考慮して、レスポンスデータ形式を決定する。このようなヘッダでレスポンスデータ形式を指定する方法を、コンテンツネゴシエーションと呼ぶ。ただし、ヘッダを使わず、単にクエリパラメータで形式を指定する方法も、よく使われる。
コンテンツネゴシエーションは、データ形式以外にも、言語指定や、APIのバージョニングにも用いられる。一度公開したAPIを変更する際は、従来の利用者がAPIを使用し続けられるよう、慎重なバージョン管理が必要になる。特に、後方互換性のないmajorバージョンアップについては、一定期間、APIの新旧バージョンを共存させることになるだろう。その際、URLにバージョン番号を組み込むURLバージョニング、クエリパラメータによるバージョニングなどの方法があるが、コンテンツネゴシエーションによる方法が最も柔軟だという。
指定方法 | 例 | 説明 |
---|---|---|
URLバージョニング | /v1/products | URLにメジャーバージョンを含める |
クエリパラメータ | /products?price=desc | クエリとしてバージョンを指定 |
ヘッダ | Accept: application/vnd.api+json;version=1 | コンテンツネゴシエーションを使用 |
適切なステータスコードや、一貫したエラーレスポンスを返すことも重要だ。そうすることで、API利用者が、クライアントに期待されている振る舞いを理解するのに役立つ。原則的にステータスコードは、HTTP標準に準拠するのが望ましい。ただし現実の実装では、さまざまな例外があるので、ステータスコードの細かいユースケースについては、実際のAPIガイドラインを参照するのが良い。またエラーレスポンスについては、RFC 7807という標準仕様が策定されているので、参考にしてほしい。
キャッシングの適切なコントロールでAPIを高速化
(5)よく使うデータをキャッシュしてAPIを高速化する
APIを高速化しつつ、正確なデータを、意図したタイミングで確実に届けるためには、キャッシングの適切なコントロールが欠かせない。データの鮮度が重要か否か、更新頻度の多寡など、APIが提供するデータの性質に応じて、Cache-Controlヘッダのパラメータを適切に設定する必要がある。ケースに応じたパラメータ設定は下記のフローチャートを参考にしてほしい。

またAPIから大量のデータを返す際は、クエリパラメータによるページネーションで、レスポンスを分割して返す。逆にAPIが大量のデータを受け取る場合は、バッチ処理用のエンドポイントを用意する。項目ごとに都度APIを呼び出すとオーバーヘッドが増えるので、配列としてまとめてデータを渡すのが定石だ。またバッチ処理やアップロードなど時間がかかる処理には、ロングランオペレーションという実装が必要になる。具体的には処理の開始、状態の確認、キャンセル用など、複数のエンドポイントを用意し、クライアントがそのURLを定期的にポーリングして状態を確認する方法。あるいは処理が完了した際にWebhookコールバックを通じて通知を受け取る方法がある。
(6)目的にあった認証・認可方式を選定
パブリックAPIにおいて、認証と認可は必要不可欠だ。APIの呼び出しごとに認可サーバへ問い合わせを行うと、オーバーヘッドが増加してしまうことがある。トークンの有効期限、トークンの長さをどうするか、毎回権限をチェックする必要があるのかといった点を、セキュリティ面と利便性の両面から総合的に判断し、最適な認可方法を選ぶことが必要だ。他にも、異なるオリジンにリクエストが必要な場合のCORS関連ヘッダによるアクセス制御、APIへの一定時間内の大量アクセスを制限するためのレートリミットなど、APIセキュリティを担保するためのさまざまな仕組みがある。
(7)APIの使い方を明確かつ詳細に説明するドキュメントを作る
草薙氏が最後に強調した重要なポイントは、APIドキュメントをしっかり作成することだ。現在は、OpenAPI仕様に従って、API仕様書とドキュメントを作成する方法が一般的だ。この仕様に従うことで、人間と機械の双方が理解しやすくなり、テスト、モックの自動生成も容易になる。
ただし、OpenAPI仕様だけでは開発者にとって十分な情報を集約するには限界がある。そこで草薙氏が紹介したのが、API管理プラットフォーム「Postman」のコレクション機能だ。これは、APIの仕様書と実行可能なAPIを一体化した、いわば実行可能なAPIドキュメントのようなものだ。これらのツールを活用することで、API開発者の作業負担を大幅に軽減できると、草薙氏は言う。

最後に草薙氏は、成長を続けるPostmanコミュニティの活動を紹介して、講演を終えた。
「私たちは、Postmanのユーザーコミュニティによる勉強会やワークショップを頻繁に開催している。connpassページでのイベント情報に加え、XやDiscordでも情報発信をしている。Postmanコミュニティに、ぜひ足を運んでみてほしい」
Postmanコミュニティに参加しよう!
Postman Connpassグループでは、Postman主催のイベント・オンラインワークショップ情報の配信と参加登録を受け付けています。また、Postman JapanコミュニティDiscordでは、プロダクト・イベント情報や、Q&A、ユーザー同士の交流が行われています。ぜひご参加ください。