APIとは？基本概念・操作コマンドについて解説

こんにちは！古川です。
未経験からWEBエンジニアに転職することができましたが、コーディングテストの一環でAPIの問題が出たことがあります。
正直テンパったので、理解定着、備忘録のために記録します。
もし間違いがございましたらご指摘いただけますと幸いです。

# APIとは？
正式名称は、Application Programming Interface（アプリケーション プログラミング インターフェース）です。
アプリをプログラミングするために使われる入り口とも表現されます。（厳密にインターフェースは、接点・境界面を意味します。）

身近な例では、ソーシャルログイン機能などがあります。
新しくアプリを利用する度に、それぞれで毎回ユーザー登録するのは大変なので、GoogleやLINEアカウントなどに紐づけて会員情報を管理してもらうことなどができます。

よくある導線としては、
1. 利用アプリのログインページから、ソーシャルログインボタン（例：Googleログイン）をクリックする
2. 管理元（例：Google）へリダイレクトされる
3. （例：Googleアカウントのパスワード入力など）認証作業をする
4. 認証トークンを取得できる
5. 利用アプリへリダイレクトされ、ログイン完了となる

このような流れを、多くの方が体験されたかと思います。
また、同じように決済代行サービス（Amazon, Paypay）などにもAPIが使われています。

# APIの主な役割は？
大きく4つ挙げられます。

| 4つの役割 | 働き |
|:------------:|:------------|
| データの提供 | 他のアプリケーションが利用できるように、特定のデータや機能を提供します。 |
| データの取得 | 他のサービスからデータを取得するための手段を提供します。 |
| セキュリティ | APIを通じてデータをやり取りする際のセキュリティを確保します。<br>例えば、APIキーを使用して認証を行うことがあります。 |
| 効率的な通信 | 必要なデータのみを取得することで、通信の効率を上げることができます。 |

# RESTってそもそも何やねん？
REST API, RESTful APIとかよく聞くと思います。
何か簡単で便利なんでしょ？くらいの認識ですので、改めておさらいします。

正式名称は、Representational State Transferです。
直訳すると「表現的な状態の転送」となります。

```
Representational: 表現的な、表現するもの
State: 状態
Transfer: 転送、移すこと
```

なので、REST, RESTfulは、「ウェブ上の情報やデータ（状態）を、ある形式（表現）でやり取り（転送）するという考え方」を意味します。
この考え方に沿って、操作できるAPIを、REST API, RESTful APIと言います。

# RESTの原則って何だっけ？
ウェブ上の情報やサービスを、効果的に提供・利用するための「ルール」や「ガイドライン」を示しています。

| 原則 | 意味 |
|:------------:|:------------|
| リソース指向 | ウェブ上の情報やサービスは「リソース」として扱い、それぞれ一意のURL（アドレス）で識別されます。<br>（例：オンライン書店の各本は、それぞれのURLを持つリソースとして扱われます。） |
| ステートレス性 | 各リクエストは独立しており、前後のリクエストとの関連性は持ちません。<br>サーバーは、クライアントの状態を保存しないため、クライアントは必要な情報を毎回リクエストに含める必要があります。<br>（例：オンラインショッピングのカートに商品を追加するたびに、その情報をサーバーに送信します。） |
| クライアント-サーバー構造 | クライアント（例：ブラウザやアプリ）はユーザーインターフェースを担当し、サーバーはデータの管理とビジネスロジックを担当します。<br>この分離により、クライアントとサーバーは独立して進化・変更することができます。 |
| 一貫性のあるインターフェース | RESTful APIは、一般的な規約や標準に基づいて設計されるため、利用者にとって予測しやすく、使いやすいインターフェースとなります。 |
| レイヤードシステム | システムは複数のレイヤー（層）で構成され、各レイヤーは特定の機能を担当します。<br>これにより、システム全体の柔軟性と拡張性が向上します。 |
| キャッシュ可能 | 応答データはキャッシュ可能としてマークされることができ、これによりクライアントのパフォーマンスが向上します。<br>（例：よくアクセスされるウェブページのデータは、一時的に保存して再利用することで、読み込み速度を向上させることができます。） |

# API 基本操作方法
APIは、通常HTTP（HyperText Transfer Protocol）を使用して操作されます。
```1. GETメソッドの使用例:
curl https://api.example.com/data
```

```2. POSTメソッドの使用例 (新しいデータを送信する場合):
curl -X POST -H "Content-Type: application/json" -d '{"key":"value"}' https://api.example.com/data
```

```3. PUTメソッドの使用例 (データを更新する場合):
curl -X PUT -H "Content-Type: application/json" -d '{"key":"new-value"}' https://api.example.com/data/id
```

```4. DELETEメソッドの使用例:
curl -X DELETE https://api.example.com/data/id
```

# [PokeAPI](https://pokeapi.co/docs/v2#pokemon)を叩いてみよう！
APIが「アプリをプログラミングするために使われる入り口」とも表現されることから、情報を要求することを「叩く」と言います。

まず、吐き出されるjsonは1行で長く見にくいため、見やすく改行・整形してくれる[jqコマンド](https://jqlang.github.io/jq/)を打ちます。
```
❯❯❯brew install jq
Running `brew update --auto-update`...
==> Auto-updated Homebrew!
Updated 3 taps (homebrew/services, homebrew/core and homebrew/cask).
==> New Formulae
badkeys             eatmemory           mentat              saf-cli
bob                 gossip              node@20             snyk-cli
cf2tf               gptline             nvimpager           ssh-mitm
chainloop-cli       haiti               opentofu            sshportal
cloudsplaining      jupyter-r           pciutils            three-body
dcp                 karmadactl          perl-xml-parser     wormhole-william
diffoci             libdicom            python-psutil       xeol
dockly              libnghttp3          rekor-cli           zix
==> New Casks
affine                                   nvs
batchoutput-pdf                          simplex
brickstore                               songkong
commandpost                              spacedrive
free-podcast-transcription               writerside
kuaitie                                  xsplit-vcam
low-profile

You have 74 outdated formulae installed.

==> Downloading https://ghcr.io/v2/homebrew/core/jq/manifests/1.7
######################################################################### 100.0%
==> Fetching jq
==> Downloading https://ghcr.io/v2/homebrew/core/jq/blobs/sha256:e4b23ebcff759f5
######################################################################### 100.0%
==> Pouring jq--1.7.ventura.bottle.tar.gz
🍺  /usr/local/Cellar/jq/1.7: 19 files, 1.3MB
==> Running `brew cleanup jq`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
~
```
では、curlコマンドで、1番目のポケモンの名前と写真を叩きます。
```
❯❯❯curl -s https://pokeapi.co/api/v2/pokemon/1/ | jq '.name, .sprites.front_default'

"bulbasaur"
"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/1.png"
~
```
"bulbasaur"はフシギダネの英名です。
さらにURLにアクセスするとちゃんと画像も表示されますね！
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662494/518607e4-4b9d-e723-00b9-b3407cf7cfe0.png)

では、今度はゼニガメの英名（squirtle）で何番目か（id）も調べてみましょう。
```
❯❯❯curl -s https://pokeapi.co/api/v2/pokemon/squirtle/ | jq '.id, .sprites.front_default'

7
"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/7.png"
~
```
ちゃんと7番目のidと画像も返してくれました！
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662494/aab8c5ad-e88f-4426-1529-534cbe091066.png)

では最後に、4番目のあの子も高さと重さも調べてみましょう。
```
❯❯❯curl -s https://pokeapi.co/api/v2/pokemon/4/ | jq '.name, .height, .weight, .sprites.front_default'

"charmander"
6
85
"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/4.png"
~
```
「ん？６mじゃないし、6cmでもないな。。」と思って[調べました](https://pokeapi.co/docs/v2#pokemon)が、

| Name | Description | Type |
|:------------:|:------------:|:------------:|
| height | The height of this Pokémon in decimetres. | 	integer |
| weight | The weight of this Pokémon in hectograms. | integer |

- 高さ (height): デシメートル (dm): 1dm = 0.1m = 10cm
- 重さ (weight): ヘクトグラム (hg): 1hg = 0.1kg = 100g

とのこと。
つまり、ヒトカゲは、0.6メートル、8.5キログラムだそうです！そのくらいなイメージ！

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662494/f979b27a-9946-946d-31da-af2b28db37d9.png)

-----

一般的に公開されているAPIでは、POST, PUT, DELETEができないのでGETメソッドのみになりましたが、APIについてまとめてみました。
プログラミング学習者の方々のお役に立てれば嬉しい限りです。