メインコンテンツへスキップ
ブログ一覧に戻る
Web制作・運用

API入門:システム連携の基本を理解しよう

2024年8月30日
最終更新: 2026年10月8日
11分で読めます

この記事でわかること

APIとは何か?Webサービス間の連携に欠かせないAPIの基本概念から、実際の使い方、セキュリティまで、初心者にもわかりやすく解説します。

30秒で要点

  • APIは、別のプログラムに頼める操作と、その頼み方・返し方を決めた窓口です。Web APIだけでなく、ライブラリやOSにもAPIがあります。
  • HTTP APIは、URL、メソッド、ヘッダー、本文を組み合わせて呼び出します。応答は「通信できたか」「HTTPの結果は何か」「本文が期待どおりか」を分けて確認します。
  • APIを使うだけで安全になるわけではありません。誰が何をできるか、秘密の置き場所、料金・回数制限、重複実行を利用前に決めます。

予約サイトが空き状況を調べ、注文システムが配送状況を受け取る。こうした連携の窓口がAPIです。一方が相手のデータベースへ自由に入るのではなく、公開された操作を決められた形式で依頼します。

この記事は、APIを初めて使う人や、連携の依頼内容を整理したい担当者向けです。天気の取得、投稿の登録、支払いの依頼を例に、読み取りと書き込みの違いから確認します。以下の通信例は架空の教材で、実サービスへの送信を求めるものではありません。

APIの要求から認証・認可、応答の受け取り、JSON確認までの経路と、タイムアウト時に結果が不明になる場合を示す。
自作の概念図。通信の成功と業務処理の成功は別で、応答がない書き込みを未受付と決め付けない。実APIや公式構成図ではありません。

窓口があることと、利用してよいことは別

APIはApplication Programming Interfaceの略です。レストランなら、メニューが「頼める操作」、注文の伝票が「必要な入力」、提供された料理や品切れの返答が「結果」に相当します。この例えは、待ち時間や失敗、注文できない品目も含めて考えると役立ちます。

表が収まらない場合は、横にスクロールできます

要素連携で確かめること予約サービスの例
利用できる操作読むだけか、登録・取消もできるか空席を見る、予約する、取り消す
入力の契約必須項目、型、単位、許される値日付、人数、店舗ID
権限誰の情報に、どの操作を許すか自分の予約だけを取り消せる
結果成功、拒否、処理中、結果不明をどう表すか予約番号、満席、確認待ち
運用条件上限、課金、保守、変更通知回数制限、APIの廃止予定

窓口を分けることで内部の実装を隠せますが、権限確認や入力検証は実装が必要です。「API経由だから安全」「APIキーがあれば全操作を許す」とは考えません。

Web APIはネットワーク越しに利用するものです。ライブラリAPIはプログラムから呼ぶ関数など、OS APIはファイルや通信などの機能を使う入口です。JavaScriptのDOM APIもAPIの一例で、すべてが外部サービスや課金サービスではありません。プログラミングの基礎とサーバーの役割を合わせると、窓口の位置を整理できます。

HTTPでは、要求と応答を一組で読む

URLは対象、メソッドは操作の意味、ヘッダーは認証情報や形式などの付帯情報、本文は送るデータです。サービスの仕様に従い、必要な組み合わせを確認します。

表が収まらない場合は、横にスクロールできます

メソッド一般的な用途架空APIの例注意
GET表現を取得する/users/123読み取りのはずの操作に削除などを混ぜない
POSTデータを処理・登録する/users再送で二重登録になる可能性を確認する
PUT対象の表現を置き換える/users/123一部更新と同じ意味にしない。仕様を読む
DELETE対象を削除する/users/123認可と取り消せない影響を確認する

HTTPには、安全性や冪等性というメソッドの意味があります。冪等性は、同じ要求を繰り返したときの意図した効果についての性質です。同じ本文が必ず返る、途中で失敗しない、課金が必ず一度になる、という保証ではありません。RFC 9110のメソッドの性質が基準になります。

REST、SOAP、GraphQLは同じ分類ではない

RESTは設計上の考え方、SOAPはメッセージ交換の仕様、GraphQLはスキーマに基づいて問い合わせるための仕組みです。「URLとJSONを使うものは全部REST」と覚えるより、そのAPIの契約を読む方が実務では役立ちます。

SOAPはXMLを用いた拡張可能な枠組みです。SOAPの中核仕様だけで、すべての認証・暗号化・信頼性が完成するわけではありません。必要な拡張と設定を確認します。SOAP 1.2の位置づけにも、この範囲が示されています。

GraphQLでは、サービス側が提供するスキーマの範囲内で、欲しいフィールドを選べます。次はuserとrecentPostsを提供する架空のスキーマを前提にした問い合わせ教材です。任意のGraphQL APIにそのまま送れるものではありません。

query UserRecentPosts {
  user(id: "123") {
    name
    recentPosts {
      title
      date
    }
  }
}

必要なフィールドを選べても、問い合わせが常に軽いとは限りません。件数や深さ、権限、バックエンドの処理を別に確認します。GraphQL公式のQueriesとGraphQL入門が次の入口です。

天気、投稿、支払いでは失敗の影響が違う

天気は、値だけでなく単位を読む

次は天気を取得する架空のHTTP要求です。example.invalidは教材用で、実際の天気サービスのURLではありません。パラメータ名や単位はAPIごとに確認します。

GET /weather?city=Tokyo&unit=celsius HTTP/1.1
Host: example.invalid
Accept: application/json

応答本文も合成データです。気温の数値だけを読み、摂氏なのか華氏なのかを見落とすと、通信が成功していても表示を誤ります。観測時刻と取得時刻の違いも確認します。

{
  "city": "Tokyo",
  "temperature": 19,
  "temperatureUnit": "celsius",
  "humidityPercent": 70,
  "observedAt": "2026-10-04T00:00:00Z"
}

投稿は、送信と公開の権限を分ける

次は架空の投稿登録です。実SNSの現行エンドポイントや必要な権限を示すものではありません。利用者の認可、公開先、本文、送信結果を確認してから実装します。

POST /posts HTTP/1.1
Host: example.invalid
Content-Type: application/json

{"text":"APIの仕組みを学ぶための架空の投稿です。"}

返事が来ない場合も、相手が受け付けていないとは限りません。結果の照会方法や、重複登録を防ぐための提供仕様がなければ、無条件に送り直さない設計にします。

支払いは、処理結果が不明な状態を残す

次も実決済サービスの使い方ではなく、金額・通貨・注文との対応を読む教材です。amountYenはこの架空仕様で円単位と定義しており、実APIの金額単位を推定してはいけません。

POST /payment-requests HTTP/1.1
Host: example.invalid
Content-Type: application/json

{"orderId":"sample-order-001","amountYen":1000,"currency":"JPY"}

支払いでは「成功」「失敗」に加え、「応答が届かず結果を確認中」を扱います。実装する段階で、提供元の認証方式、金額単位、再送キー、結果照会、Webhook、テスト環境を確認してください。この記事の教材は決済・投稿を実行しません。

JSONを読めても、正しい結果とは限らない

JSONは文字列、数値、真偽値、配列、オブジェクトなどを表す形式です。次は架空のユーザー情報です。見やすい表示例であり、実在する個人情報ではありません。

{
  "id": 123,
  "name": "サンプル利用者",
  "email": "sample@example.com",
  "isActive": true,
  "hobbies": ["読書", "旅行"],
  "address": {"city": "サンプル市", "zipcode": "000-0000"}
}

本文をJSONとして解析できることと、必要な項目が正しい型で入っていることは別です。idが欠ける、配列だと思っていたものが文字列になる、といった場合を扱います。ログへ応答全体を保存すると、秘密や個人情報も残るため、記録する項目を決めておきます。

小さな読み取り関数で失敗を分ける

JavaScriptではHTTPエラーを明示的に確認する

fetch()は、HTTP 404や500が返っただけではPromiseがrejectされません。response.okを確かめ、本文の解析失敗と入力・型の不一致も扱います。MDNのUsing Fetchを参照してください。

次は、呼び出し先を注入できる関数と、外部通信をしない合成応答の例です。読み取りの教材に限定し、自動再試行や実認証は追加していません。

async function readUser(url, { fetchImpl = fetch, timeoutMs = 1000 } = {}) {
  if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
    throw new TypeError("timeoutMs must be positive");
  }
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), timeoutMs);
  try {
    const response = await fetchImpl(url, { signal: controller.signal });
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    const data = await response.json();
    if (data === null || typeof data !== "object" ||
        !Number.isInteger(data.id) || typeof data.name !== "string") {
      throw new TypeError("Unexpected user payload");
    }
    return { id: data.id, name: data.name };
  } finally {
    clearTimeout(timer);
  }
}

const offlineFetch = async () => new Response(
  JSON.stringify({ id: 123, name: "サンプル利用者" }),
  { status: 200, headers: { "Content-Type": "application/json" } }
);
console.log(await readUser("https://example.invalid/users/123", {
  fetchImpl: offlineFetch
}));

ブラウザでは、別オリジンへのアクセスにCORSの条件も関わります。CORSはサーバー側の認可の代わりではありません。タイムアウトを設けても、すでに始まった相手側の処理を必ず取り消せるとは限りません。この合成応答だけでは通信・ブラウザ・CORSの動作を確かめたことになりません。

Pythonでも、タイムアウトとHTTPの結果を別に扱う

次はRequestsを使う関数です。実利用にはRequestsが導入された環境が必要ですが、末尾の呼び出しでは合成セッションを渡すため外部へ送信しません。実通信でのタイムアウトは、処理全体の絶対的な締め切りと同じではありません。Requests公式のTimeoutsで範囲を確認します。

import requests

def read_user(url, session=requests):
    response = session.get(url, timeout=(3.05, 10))
    response.raise_for_status()
    data = response.json()
    if (not isinstance(data, dict)
            or type(data.get("id")) is not int
            or not isinstance(data.get("name"), str)):
        raise ValueError("Unexpected user payload")
    return {"id": data["id"], "name": data["name"]}

class OfflineResponse:
    def raise_for_status(self):
        return None

    def json(self):
        return {"id": 123, "name": "サンプル利用者"}

class OfflineSession:
    def get(self, url, *, timeout):
        return OfflineResponse()

print(read_user("https://example.invalid/users/123", OfflineSession()))

実装時は、通信例外、HTTPエラー、JSONの解析失敗、期待した項目の不一致を区別します。利用者へ秘密を含む例外全文を返さず、調査用の識別子や必要最小限の状態を残します。

認可、回数制限、費用を利用前に確認する

APIキーは呼び出すアプリの識別や利用量管理に使われますが、キーの権限や扱いは提供元によって違います。公開ブラウザへ秘密キーを埋め込まず、必要な操作だけの権限、保管先、失効・再発行の担当を決めます。

OAuthは、他のアプリへ限られたアクセスを許すための枠組みです。本人確認の方法や現在推奨されるフローまで、OAuthという名前だけで決まりません。RFC 6749の役割の説明と、採用する提供元の現行セキュリティ手順を分けて読みます。

表が収まらない場合は、横にスクロールできます

状態最初に見るもの避けたい対応
認証・権限で拒否された資格情報の期限、対象、権限秘密キーをログや質問文へ貼る
429が返った提供元の回数制限とRetry-After直ちに繰り返し送る
通信が途切れた読み取りか書き込みか、結果照会書き込みを結果不明のまま再送する
応答の項目が変わった仕様変更・バージョン・解析箇所解析できたので正常とする
費用が想定を超えた回数、転送量、課金単位、上限回数制限が支出上限も保証すると考える
429の仕様では、制限の数え方をすべて統一してはいません。Retry-Afterがある場合も、秒数かHTTP日付かを確認し、提供元の条件と最大試行回数に従います。キャッシュやまとめ取得も、情報の鮮度・権限・利用規約を満たす範囲で使います。

提供側は、最初の利用者が失敗を切り分けられるようにする

良いAPIの説明には、成功例だけでなく拒否や部分的な結果、変更時の影響も必要です。命名や応答形式をそろえ、入力・出力、認証と認可、エラー、件数・料金、変更通知をひとまとまりにします。

OpenAPIなどで仕様を記述しても、実装との一致を確認する仕事は残ります。入力検証、利用者ごとの認可、秘密の除去、負荷対策、監査、互換性を検討します。圧縮・データ量削減・キャッシュ・データベースの見直しは、遅い箇所を測ってから選びます。利用者別の応答を共有キャッシュへ混ぜないことも必要です。

最初の一件で確認すること

実サービスへ接続する前に、権限の小さいテスト環境と合成データで「成功」「HTTPエラー」「形式不一致」「遅延」「結果不明」を区別できるか確認します。教材の関数を試す段階では、合成応答のIDを文字列にする、HTTP 500にする、JSONを壊す、といった失敗の入口を用意できます。

次に、実際に許可された環境で一件だけ読み取り、料金・回数・秘密を残さないログを確認します。投稿や支払いなどの書き込みは、別途許可された検証計画と取り消し・照会手順をそろえてから進めます。

設計を進めるならAPI設計のベストプラクティス、結果通知にはWebhook入門、業務の構成にはシステムアーキテクチャ設計を参照してください。AIをAPI経由で使う方法でも、同じ失敗と費用の境界が必要になります。

よくある質問(FAQ)