結論

仕様とは、システムが「何を、どんな条件で、どう動くか」を決めた約束ごとです。それを文書にしたものが仕様書です。

この記事でわかること

  • 要件・仕様・設計の違いの表と、仕様書8種の早見表
  • 会議室予約で書いた1枚の機能仕様と11件の受け入れ条件
  • OpenAPIのAPI仕様を検証ツール2つで確かめた結果

2026年10月23日更新|OpenAPI 3.2・openapi-spec-validator 0.9.0で確認

仕様は、開発の流れの真ん中にあります。要件(何が必要か)を、作る人が迷わない具体的な決まりにしたものが仕様で、テストは「仕様どおりに動くか」を確かめます。

flowchart TD
    A[要件<br>何のために何が必要か] --> B[仕様<br>何をどう動かすか]
    B --> C[設計<br>どう作るか]
    C --> D[実装<br>コードを書く]
    D --> E[テスト<br>仕様どおりか確かめる]
    E -. 合わなければ直す .-> B

急いでいる人向けに、よく調べられることの答えを先にまとめます。

知りたいこと 答え 詳しい節
仕様とは 何を・どう動かすかの決まりごと 仕様とは
読み方・英語 しよう/specification(略して spec) 仕様とは
仕様書とは 仕様を文書にまとめたもの 仕様と仕様書の違い
要件との違い 要件は必要なこと、仕様はその具体的な決まり 要件・仕様・設計の違い
設計との違い 仕様は「何を」、設計は「どう作るか」 要件・仕様・設計の違い
「仕様です」の意味 決めたとおりの動きで、バグではないという意味 「仕様です」の意味
仕様変更とは 決めた後に変えること。影響と費用を確かめて合意 仕様変更の扱い
API の仕様の書き方 OpenAPI(YAML)で書き、ツールで検証する OpenAPI
AI 開発との関係 仕様駆動開発は、仕様を先に書いて AI に渡す 仕様駆動開発

確認環境:Ubuntu 24.04.4 LTS。この記事の例(会議室予約の API)の仕様は OpenAPI 3.2 で書き、openapi-spec-validator 0.9.0(Python 3.11.15)と Redocly CLI 2.70.0(Node.js 22.22.2)で検証しました。業務ルールの受け入れ条件は pytest 9.1.1 で実行し、API の応答が仕様どおりかは openapi-schema-validator 0.9.0 で確かめています。仕様変更の差分は Git 2.43.0 で取りました。言葉の意味はデジタル大辞泉・精選版日本国語大辞典・IT用語がわかる辞典(コトバンク)、OpenAPI は OpenAPI Specification v3.2.1、仕様駆動開発は Kiro と GitHub Spec Kit の公式ドキュメントで確かめました(確認日 2026年10月23日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「仕様とは|要件・設計との違いと仕様書の書き方をIT開発の実例で解説」

仕様とは(意味・読み方・英語)

この節では、「仕様」という言葉の意味と、IT・システム開発でどう使われるかが分かります。

仕様(しよう)とは、物やシステムの作り・中身・動き方を決めたものです。 デジタル大辞泉は「仕様」を「物事をする方法。しかた。やりかた。」と「機械類や建築物などの構造や内容。」と説明しています。IT用語がわかる辞典は「設計の詳細。規格・性能・機能・搭載部品など。」とし、「スペック」ともいう、としています。

英語では specification(スペシフィケーション)で、略して spec(スペック)と呼びます。精選版日本国語大辞典によると、「し」は動詞「する」の連用形で、「仕」は当て字です。

システム開発での仕様は、「この機能は、何を受け取り、どんな条件で、何を返すか」を、誰が読んでも同じ意味になるように決めたものです。 身近な例として、自動販売機の仕様を書くと次のようになります。

1何ができるか(機能)

お金を入れてボタンを押すと、その商品が出てくる。おつりが出る。

2どんな条件で(ルール)

使えるのは10円・50円・100円・500円玉と千円札。金額が足りないとボタンが光らない。

3どれくらいの性能で(非機能)

ボタンを押して3秒以内に商品が出る。30本まで入る。屋外の気温でも動く。

仕様があるから、作る人は迷わずに作れ、確かめる人は「正しく動いているか」を判定できます。 「お金が足りないときはどうなる?」に答えが書いていなければ、作る人ごとに動きが変わります。仕様は、関係する人みんなが同じものを思い浮かべるための約束です。

仕様と仕様書の違い(「仕様」と「使用」の違いも)

この節では、「仕様」と「仕様書」、同じ読みの「使用」との違いが分かります。

言葉 意味 例
仕様 決めた内容そのもの 「画像は10MBまで送れる」という決まり
仕様書 仕様を文書にまとめたもの 機能仕様書・画面仕様書・API 仕様書
使用 物を使うこと 「会議室を使用する」「使用料」

仕様は決まりそのもの、仕様書はその決まりを書き残して共有するための文書です。 会話で「仕様を確認して」と言われたら、多くは「仕様書を読んで、決まりを確かめて」という意味です。

「仕様」と「使用」はどちらも「しよう」と読みます。「使用」は「使う」ことで、作りや決まりの意味はありません。「仕様書」を「使用書」、「仕様変更」を「使用変更」と書くのは誤りです。

要件・仕様・設計の違い(表と図)

この節では、混同しやすい「要件」「仕様」「設計」と、「規格」「スペック」との違いが分かります。

会議室予約システムで比べると

要件社員が会議室を空き状況を見て予約でき、ダブルブッキングが起きないこと
→
仕様予約は30分単位・30分以上4時間以内。同じ会議室で時間が重なると 409 エラーを返す

設計は、その仕様を「どのテーブル・どのクラス・どの SQL で」作るかを決める

言葉 決めること 会議室予約の例 主に書く文書
要件 何のために、何が必要か ダブルブッキングを無くしたい 要件定義書
仕様 何を、どんな条件で、どう動かすか 時間が重なる予約は 409 で断る 機能仕様書・外部設計書
設計 どう作るか(中の作り) 予約テーブルに会議室と時刻の索引を張る 基本設計書・詳細設計書
規格 多くの製品に共通の決まり 日時は ISO 8601(RFC 3339)の形 JIS・ISO・RFC
スペック 性能や数値の一覧 同時に100人が使っても1秒以内に返す 仕様書の性能の欄

要件は「ゴール」、仕様は「ゴールにたどり着く具体的な決まり」、設計は「その決まりを実現する作り方」です。 要件は利用者や発注者の言葉で書き、仕様は作る人とテストする人がそのまま使える言葉と数値で書きます。

日本のシステム開発では、この3つの境目がきっちり分かれているとは限りません。要件定義書に画面の項目まで書くこともあり、基本設計書(外部設計書)を「外部仕様書」と呼ぶこともあります。名前よりも「利用者から見た動き」か「中の作り」かで見分けると迷いません。 利用者から見える動き(画面・入力・出力・エラー)を決めたものが外部仕様、プログラムの中の作りを決めたものが内部仕様です。

ほかにも似た言葉があります。

  • 機能と仕様:機能は「できること」(予約できる)、仕様は機能の決まり(30分単位で予約できる)です。
  • 性能と仕様:性能は速さや量(1秒以内)で、仕様の一部として書きます。非機能の仕様とも呼びます。
  • マニュアルと仕様:マニュアルは使い方の説明、仕様は作るための決まりです。

仕様書の種類(工程との対応)

この節では、システム開発で作る主な仕様書と、それぞれをいつ・誰のために書くかが分かります。

flowchart TD
    A[要件定義書<br>何が必要か] --> B[外部仕様<br>画面・API・帳票]
    B --> C[内部仕様<br>クラス・テーブル]
    C --> D[実装]
    B -.-> E[テスト仕様書<br>何をどう確かめるか]
    A -.-> E
仕様書 書くこと 主な読み手
要求仕様書・要件定義書 目的、必要な機能、性能などの条件 発注者・プロジェクト全員
機能仕様書 機能ごとの入力・処理のルール・出力・エラー 開発者・テスト担当
画面仕様書 画面の項目・入力チェック・ボタンの動き・遷移 開発者・デザイナー
API 仕様書 URL・メソッド・リクエストとレスポンスの形・エラー API を使う側・作る側
帳票・ファイル仕様書 CSV や PDF の項目・並び順・文字コード 連携先・開発者
テーブル定義書(DB 仕様) テーブル・列・型・制約・索引 開発者・DB 管理者
非機能仕様 性能・可用性・セキュリティ・運用の条件 基盤担当・運用担当
テスト仕様書 テストケース・手順・期待する結果 テスト担当

テスト仕様書の「期待する結果」は、機能仕様書や画面仕様書から作ります。 仕様があいまいだと、期待する結果が書けません。工程とテストの対応は、要件定義・基本設計・詳細設計がそれぞれシステムテスト・結合テスト・単体テストで確かめられる形(V字モデル)でよく説明されます。

要件定義書の書き方は、関連記事「要件定義書の書き方|記入例と要件ID・受け入れ基準」で、外部仕様をまとめる基本設計書は、関連記事「基本設計書の書き方|項目・記入例とレビューの観点」で扱っています。

仕様書に書く項目と例(会議室予約を1枚書く)

この節では、機能仕様書に何を書けばよいかと、小さな機能で実際に1枚書いた例が分かります。

機能仕様書に書く項目

項目 書くこと 抜けると起きること
機能 ID・名前・目的 どの要件のための機能か 何のための決まりか分からない
利用者・前提条件 誰が、どんな状態で使うか ログイン前に使えるのか迷う
入力 項目・型・必須・桁数・範囲 入力チェックが人によって違う
業務ルール 計算・判定・制約の条件 端の値(ちょうど4時間など)の扱いが割れる
出力・結果 成功したときに返すもの・変わるデータ 画面や API の戻り値が決まらない
エラー 条件ごとのエラーと伝え方 エラーのときの動きが作る人まかせ
非機能 速さ・同時に使う数・記録 性能のテストで合否が決まらない
受け入れ条件 「この入力ならこの結果」の具体例 完成したかどうかを判定できない

例:機能仕様「会議室を予約する」(F-RSV-01)

架空の社内システムで、会議室を予約する機能の仕様を1枚にまとめた例です。

項目 内容
機能 ID・名前 F-RSV-01 会議室を予約する
目的 会議室のダブルブッキングを無くす(要件 REQ-03)
利用者・前提 ログインした社員。会議室は R101(定員8人)・R102(定員4人)
入力 会議室 ID・開始日時・終了日時・件名(1〜50文字)・参加人数(1人以上)
BR-01〜BR-03 会議室 ID は登録済みのもの。時刻は30分単位。利用時間は30分以上4時間以内
BR-04・BR-05 9:00〜21:00 の間で、同じ日に終わる。開始が今より前の予約はできない
BR-06・BR-07 参加人数は定員以下。同じ会議室で時間が重なる予約はできない(終了と次の開始が同じ時刻は重ならない)
出力 予約番号(RSV- と6桁の数字)を付けて登録し、201 と予約の内容を返す
エラー 入力の誤りは 400(INVALID_INPUT・OUT_OF_HOURS・CAPACITY_OVER)、重なりは 409(OVERLAP)
非機能 応答は1秒以内(95%)。予約の登録と取り消しは操作ログに残す

ポイントは、BR-07 の「終了と次の開始が同じ時刻は重ならない」のように、端の値の扱いまで書くことです。 10:00〜11:00 の予約があるとき、11:00〜12:00 を予約できるかどうかは、「重なる」の意味をどう読むかで答えが変わります。次の節で、この一文が無いと実際に何が起きるかを動かして確かめます。

受け入れ条件(具体例の表)

仕様の文章だけでは読み違いが残るので、「この入力なら、この結果」を具体例で並べます。既存の予約は R101 の 10:00〜11:00 です。

入力(R101・11月4日) 期待する結果 確かめるルール
13:00〜13:30・4人 予約できる 最短30分
13:00〜17:00・4人 予約できる 最長4時間
13:00〜17:30・4人 INVALID_INPUT 4時間を超える
13:15〜14:00・4人 INVALID_INPUT 30分単位でない
20:30〜21:00・4人 予約できる 21:00 ちょうどに終わる
8:30〜9:30・4人 OUT_OF_HOURS 9:00 より前に始まる
13:00〜14:00・8人 予約できる 定員ちょうど
13:00〜14:00・9人 CAPACITY_OVER 定員を1人超える
10:30〜11:30・4人 OVERLAP 既存の予約と重なる
11:00〜12:00・4人 予約できる 既存の終了時刻から始まる
9:00〜10:00・4人 予約できる 既存の開始時刻に終わる
7個業務ルールBR-01〜BR-07
11件受け入れ条件境目の値を中心に
5種エラーコード400・409・404 で返す

受け入れ条件は「ちょうど」と「1つ超える」を並べるのが基本です(境界値)。テストケースへの展開は、関連記事「テスト仕様書の書き方|テストケースの記入例と観点の洗い出し方」で扱っています。

あいまいな仕様と確かめられる仕様(テストで実行)

この節では、あいまいな仕様が実装にどう表れるかと、受け入れ条件をテストにして確かめる方法が分かります。

あいまいな書き方 → 確かめられる書き方

あいまい予約が重ならないようにする。長すぎる予約はできない。すぐに結果を返す
→
確かめられる終了と次の開始が同じ時刻は重ならない。4時間を超える予約は INVALID_INPUT。応答は1秒以内(95%)

「重ならない」「長すぎる」「すぐに」は、人によって境目が違う言葉

上の受け入れ条件を、そのまま pytest のテストにしました。業務ルールを実装した check() 関数に入力を渡し、期待する結果と比べます。

"""仕様の「受け入れ条件」をそのままテストにしたもの(test_rules.py)"""
from datetime import datetime
import pytest
from rules import check

NOW = datetime.fromisoformat("2026-11-01T09:00:00+09:00")
BOOKED = [{"roomId": "R101", "startAt": "2026-11-04T10:00:00+09:00", "endAt": "2026-11-04T11:00:00+09:00"}]

def req(start, end, room="R101", n=4):
    d = "2026-11-04T"
    return {"roomId": room, "startAt": d + start + ":00+09:00", "endAt": d + end + ":00+09:00",
            "title": "定例", "attendees": n}

@pytest.mark.parametrize("start,end,n,expected", [
    ("13:00", "13:30", 4, None),            # 最短30分 → 予約できる
    ("13:00", "17:00", 4, None),            # 最長4時間 → 予約できる
    ("13:00", "17:30", 4, "INVALID_INPUT"), # 4時間30分 → できない
    ("13:15", "14:00", 4, "INVALID_INPUT"), # 30分単位でない
    ("20:30", "21:00", 4, None),            # 21:00 ちょうどに終わる → できる
    ("08:30", "09:30", 4, "OUT_OF_HOURS"),  # 9:00 より前に始まる
    ("13:00", "14:00", 8, None),            # 定員ちょうど
    ("13:00", "14:00", 9, "CAPACITY_OVER"), # 定員を1人超える
    ("10:30", "11:30", 4, "OVERLAP"),       # 既存 10:00〜11:00 と重なる
    ("11:00", "12:00", 4, None),            # 既存の終了 11:00 から始まる → 重ならない
    ("09:00", "10:00", 4, None),            # 既存の開始 10:00 に終わる → 重ならない
])
def test_acceptance(start, end, n, expected):
    assert check(req(start, end, n=n), BOOKED, NOW) == expected

最初の実装は、「重ならない」を「時間が接していても重なりとみなす」と読んで、次のように書かれていました。

# rules.py の BR-07(最初の実装)
if s <= re_ and rs <= e:     # 端が接するだけでも「重なる」と判定している
    return "OVERLAP"

テストを実行した結果です。

FAILED test_rules.py::test_acceptance[11:00-12:00-4-None] - AssertionError: a...
FAILED test_rules.py::test_acceptance[09:00-10:00-4-None] - AssertionError: a...
2 failed, 9 passed in 0.03s

失敗した1件の詳細には、AssertionError: assert 'OVERLAP' == None と出ました。11:00〜12:00 と 9:00〜10:00 は「予約できる」はずが、OVERLAP で断られました。 仕様に「終了と次の開始が同じ時刻は重ならない」と書いてあれば、実装する人もテストする人も同じ答えを出せます。比べる記号を < に直すと、次のとおり11件すべて通りました。

# rules.py の BR-07(直した後)
if s < re_ and rs < e:       # 端が接するだけなら重ならない
    return "OVERLAP"
...........                                                              [100%]
11 passed in 0.02s

受け入れ条件を具体例で書いておくと、そのままテストになり、仕様と実装のずれを機械的に見つけられます。 あいまいな言葉(すぐに・多い・なるべく・適切に・など)が仕様書に残っていないかは、レビューのときに探します。

「仕様です」の意味(仕様とバグの見分け方)

この節では、「それは仕様です」と言われたときの意味と、仕様かバグかの見分け方が分かります。

「仕様です」は、「その動きは、決めたとおりの動きで、作りの誤り(バグ)ではない」という意味です。 たとえば、会議室予約で 21:30 までの予約ができないことを問い合わせて「仕様です」と返ってきたら、「9:00〜21:00 と決めてあり、そのとおりに動いている」という意味です。

ただし、利用者から見て困る動きが「仕様」なら、仕様そのものを見直す話になります。見分け方を表にまとめます。

状況 呼び方 直すもの
仕様書どおりに動いていて、困っていない 仕様どおり なし
仕様書どおりに動かない バグ(実装の誤り) コード
仕様書どおりだが、利用者が困る 仕様の誤り 仕様(仕様変更として扱う)
仕様書に書いていない場面で起きた 仕様の漏れ 仕様を決めて、必要ならコード
仕様書の読み方が人によって違う 仕様のあいまいさ 仕様の文言と受け入れ条件

「仕様です」と言えるのは、その動きが仕様書に書いてあるときだけです。 書いていない動きを「仕様」と呼ぶと、仕様の漏れが見つからないままになります。前の節の OVERLAP の例は、仕様に一文が無ければ「仕様のあいまいさ」、一文があれば「バグ」になります。

仕様変更の扱い(流れと影響の確かめ方)

この節では、仕様変更とは何か、どう進めるか、変更の影響をどう見つけるかが分かります。

仕様変更とは、一度決めて合意した仕様を、後から変えることです。 決めた後の変更は、作り直し・テストのやり直し・費用や納期に影響するので、決まった手順で進めます。

1

変更の要求を記録する

何を・なぜ変えたいかを、変更要求として番号を付けて残す。口頭の依頼もここに書く。

変更要求

2

影響を調べる

変わる仕様書・画面・API・データ・テストを洗い出し、作業量・費用・納期を見積もる。

影響分析

3

関係者で決める

やる・やらない・時期をずらすを決め、費用と納期の変化に合意する。

承認

4

仕様書を直して版を上げる

どこを変えたかが分かるように、版数・変更日・変更内容を残す。

改訂履歴

5

実装を直してテストする

変わった部分と、影響を受ける部分のテストを流し直す。

回帰テスト

仕様変更の例:最長4時間を3時間に変える

会議室予約の仕様を v1.1.0 に変えました。変更は「利用時間の上限を4時間から3時間にする」と「使いたい備品(任意)を指定できるようにする」の2つです。API の仕様(OpenAPI)の差分を Git で見ると、次のとおりです。

@@ -1,7 +1,7 @@
 openapi: 3.2.0
 info:
   title: 会議室予約 API
-  version: 1.0.0
+  version: 1.1.0
@@ -91,7 +91,7 @@ components:
         endAt:
           type: string
           format: date-time
-          description: 終了日時。開始の30分後〜4時間後
+          description: 終了日時。開始の30分後〜3時間後
@@ -100,6 +100,12 @@ components:
           type: integer
           minimum: 1
           description: 参加人数。会議室の定員以下
+        equipment:
+          type: array
+          items:
+            type: string
+            enum: [projector, whiteboard, webcam]
+          description: 使いたい備品(任意。v1.1.0 で追加)

業務ルールの実装(timedelta(hours=4) を hours=3 に)だけを直して、前の節の受け入れ条件のテストを流しました。

FAILED test_rules.py::test_acceptance[13:00-17:00-4-None] - AssertionError: a...
1 failed, 10 passed in 0.01s

詳細は AssertionError: assert 'INVALID_INPUT' == None でした。「13:00〜17:00 は予約できる」という受け入れ条件が失敗し、仕様変更が影響する場所をテストが教えてくれました。 受け入れ条件の表と、テストの期待する結果も「13:00〜16:00 は予約できる、13:00〜16:30 は INVALID_INPUT」のように直す必要があります。実際の開発では、ここに画面の説明文・利用者への案内・すでに4時間で入っている予約の扱いも加わります。

使う側に影響しにくい変更

任意の項目を足す(equipment)

新しい API を足す

エラーの説明文を分かりやすくする

使う側に影響する変更

受け付ける範囲を狭める(4時間→3時間)

必須の項目を足す・項目名を変える

返す値の形やエラーコードを変える

API の版の上げ方は、使う側に影響しない変更は小さく(1.0.0 → 1.1.0)、影響する変更は大きく(1.x → 2.0.0)上げる決め方がよく使われます。変更要求の記録の形とフローは、関連記事「仕様変更の管理方法 変更管理表テンプレートと変更要求フロー」で扱っています。

OpenAPIでAPIの仕様を書いて検証する

この節では、API の仕様を OpenAPI で書く形と、書いた仕様が正しいか、実装が仕様どおりかをツールで確かめる方法が分かります。

OpenAPI は、HTTP の API の仕様を YAML か JSON で書くための決まり(OpenAPI Specification、OAS)です。 公式の仕様書は OAS を「HTTP API のための、標準的で言語に依存しないインターフェースの定義」と説明し、ソースコードや通信を見なくても、人と機械がサービスにできることを理解できることを目的にしています。2026年10月23日時点の最新版は v3.2.1(2026年9月10日付)です。

flowchart LR
    A[openapi.yaml<br>API の仕様] --> B[検証ツール<br>書き方の誤り]
    A --> C[ドキュメント<br>HTML で読む]
    A --> D[応答のチェック<br>実装と照らす]
    A --> E[コード生成<br>クライアント・型]

会議室予約 API の仕様(openapi.yaml)

前の節の機能仕様 F-RSV-01 を、API の仕様として書いた全体です(123行)。

openapi: 3.2.0
info:
  title: 会議室予約 API
  version: 1.0.0
  description: 社内の会議室を予約する API(機能仕様 F-RSV-01 に対応)
  license:
    name: 社内利用のみ
    url: https://example.com/license
servers:
  - url: http://127.0.0.1:36900
security:
  - bearerAuth: []
paths:
  /reservations:
    post:
      operationId: createReservation
      summary: 会議室を予約する
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReservationRequest'
            example:
              roomId: R101
              startAt: '2026-11-04T10:00:00+09:00'
              endAt: '2026-11-04T11:00:00+09:00'
              title: 定例会議
              attendees: 6
      responses:
        '201':
          description: 予約できた
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Reservation'
        '400':
          description: 入力が仕様の範囲外
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: 同じ会議室の同じ時間に予約がある
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /reservations/{reservationId}:
    get:
      operationId: getReservation
      summary: 予約を1件取得する
      parameters:
        - name: reservationId
          in: path
          required: true
          schema:
            type: string
            pattern: '^RSV-[0-9]{6}$'
      responses:
        '200':
          description: 見つかった
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Reservation'
        '404':
          description: 予約が無い
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
  schemas:
    ReservationRequest:
      type: object
      required: [roomId, startAt, endAt, title, attendees]
      properties:
        roomId:
          type: string
          pattern: '^R[0-9]{3}$'
          description: 会議室ID(例 R101)
        startAt:
          type: string
          format: date-time
          description: 開始日時。30分単位
        endAt:
          type: string
          format: date-time
          description: 終了日時。開始の30分後〜4時間後
        title:
          type: string
          minLength: 1
          maxLength: 50
        attendees:
          type: integer
          minimum: 1
          description: 参加人数。会議室の定員以下
    Reservation:
      allOf:
        - $ref: '#/components/schemas/ReservationRequest'
        - type: object
          required: [id, createdAt]
          properties:
            id:
              type: string
              pattern: '^RSV-[0-9]{6}$'
            createdAt:
              type: string
              format: date-time
    Error:
      type: object
      required: [code, message]
      properties:
        code:
          type: string
          enum: [INVALID_INPUT, OUT_OF_HOURS, CAPACITY_OVER, OVERLAP, NOT_FOUND]
        message:
          type: string
部分 書くこと この例では
openapi 使う OAS の版(必須) 3.2.0
info API の名前と版(必須) 会議室予約 API・1.0.0
paths URL とメソッドごとの入力と応答 POST /reservations など2つ
components.schemas データの形(型・必須・範囲) 予約・エラーの形
security 認証の方式 Bearer トークン

機能仕様の「件名は1〜50文字」「予約番号は RSV- と6桁」は、minLength・maxLength・pattern で機械が読める形になります。 一方で、「時間が重なる予約はできない」のような複数のデータにまたがるルールは OpenAPI の型では書けないので、description と機能仕様書・受け入れ条件で伝えます。OAS v3.2.1 では openapi と info が必須で、paths・components・webhooks のどれか1つ以上が必要です。

openapi-spec-validator で書き方の誤りを見つける

openapi-spec-validator は、OpenAPI の文書が OAS の決まりどおりに書けているかを確かめる Python のツールです。PyPI のページでは 2.0・3.0・3.1・3.2 に対応しています。

pip install openapi-spec-validator
openapi-spec-validator openapi.yaml
openapi.yaml: OK

先頭を最新版の openapi: 3.2.1 に変えても、openapi-spec-validator と後で使う Redocly CLI の両方で OK でした。わざと誤りを入れた4つのファイルを検証した結果です。

入れた誤り 出たエラー(原文の1行目) 終了コード
info を消した Validation Error: 'info' is a required property 1
パスのパラメーターを required: false Validation Error: True was expected 1
参照先の名前を打ち間違えた Error: '/components/schemas/Reservaton' does not exist within {…} 2
type: integer を type: int と書いた Validation Error: 'int' is not valid under any of the given schemas 1

エラーには、どこが誤りかも出ます。 たとえばパスのパラメーターの誤りでは、続けて次のように場所が示されました。URL の一部になるパスのパラメーターは、OAS で required: true と決まっています。

On instance['paths']['/reservations/{reservationId}']['get']['parameters'][0]['required']:
    False

type: int の誤りでは、'int' is not one of ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] と、書ける型の一覧も出ました。

Redocly CLI で書き方のルールも確かめる

Redocly CLI の lint は、OAS の決まりに加えて、推奨のルール(recommended)でも確かめます。認証(security)と license を書く前の版を確かめた結果です。

[1] openapi.yaml:10:5 at #/paths/~1reservations/post

Every operation should have security defined on it or on the root level.

Error was generated by the security-defined rule.

([2] は GET /reservations/{reservationId} で同じエラー)

[3] openapi.yaml:2:1 at #/info

Info object should contain `license` field.

Warning was generated by the info-license rule.

❌ Validation failed with 2 errors and 1 warning.

openapi-spec-validator は OK を出した文書でも、Redocly CLI は「認証が決まっていない API」を誤りとして止めました(終了コード 1)。 仕様として正しい形かどうかと、チームで決めた書き方を守っているかどうかは別の確認です。security と license を足すと、Woohoo! Your API description is valid. 🎉 と出ました。redocly build-docs openapi.yaml で、この仕様から読みやすい HTML のドキュメント(261 KiB の1ファイル)も作れました。

実装が仕様どおりかを確かめる

仕様は、書いたら終わりではなく、実装と照らして初めて役に立ちます。小さな API サーバーを書き、実際の応答が openapi.yaml の形に合うかを openapi-schema-validator で確かめました。

"""API の実際の応答が openapi.yaml(仕様)どおりかを確かめる(contract_check.py の要点)"""
import json, urllib.request, yaml
from openapi_schema_validator import OAS31Validator

spec = yaml.safe_load(open("openapi.yaml", encoding="utf-8"))

def inline(node):                       # "#/components/schemas/…" の参照を中身に置き換える
    if isinstance(node, dict):
        if "$ref" in node:
            target = spec
            for key in node["$ref"].lstrip("#/").split("/"): target = target[key]
            return inline(target)
        return {k: inline(v) for k, v in node.items()}
    return [inline(v) for v in node] if isinstance(node, list) else node

def verify(label, status, data, spec_path, method):
    op = spec["paths"][spec_path][method]
    if str(status) not in op["responses"]:
        print(f"NG {label}: {status} は仕様に無い状態コード"); return
    schema = op["responses"][str(status)]["content"]["application/json"]["schema"]
    errors = list(OAS31Validator(inline(schema)).iter_errors(data))
    print(("OK " if not errors else "NG ") + f"{label}: {status} {json.dumps(data, ensure_ascii=False)}")
    for e in errors:
        print("     →", e.message)

最初のサーバーは、予約番号を RSV-1 と連番だけで作り、重なったときのエラーコードを TIME_OVERLAP にしていました。

NG 予約する: 201 {"roomId": "R101", …, "id": "RSV-1", "createdAt": "2026-10-23T17:02:43+09:00"}
     → 'RSV-1' does not match '^RSV-[0-9]{6}$'
NG 同じ時間に予約: 409 {"code": "TIME_OVERLAP", "message": "OVERLAP"}
     → 'TIME_OVERLAP' is not one of ['INVALID_INPUT', 'OUT_OF_HOURS', 'CAPACITY_OVER', 'OVERLAP', 'NOT_FOUND']
OK 定員オーバー: 400 {"code": "CAPACITY_OVER", "message": "CAPACITY_OVER"}
NG 予約を取得: 200 {"roomId": "R101", …, "id": "RSV-1", "createdAt": "2026-10-23T17:02:43+09:00"}
     → 'RSV-1' does not match '^RSV-[0-9]{6}$'

予約番号を f"RSV-{n:06d}"(6桁にゼロで埋める)に、エラーコードを OVERLAP に直すと、4件とも OK になりました。

OK 予約する: 201 {"roomId": "R101", …, "id": "RSV-000001", "createdAt": "2026-10-23T17:02:50+09:00"}
OK 同じ時間に予約: 409 {"code": "OVERLAP", "message": "OVERLAP"}
OK 定員オーバー: 400 {"code": "CAPACITY_OVER", "message": "CAPACITY_OVER"}
OK 予約を取得: 200 {"roomId": "R101", …, "id": "RSV-000001", "createdAt": "2026-10-23T17:02:50+09:00"}

画面を作る人や連携先は、仕様の RSV- と6桁、OVERLAP を信じてプログラムを書きます。 応答が仕様とずれると、使う側のプログラムが壊れます。仕様を機械が読める形で書いておくと、このずれを自動で見つけられます。OpenAPI のテンプレートとチームでの運用は、関連記事「OpenAPIの書き方|YAMLのテンプレートとチームで使う運用」で扱っています。

仕様駆動開発との関係(AIに仕様を渡す)

この節では、AI で開発するときに仕様がどう使われるかが分かります。

仕様駆動開発(Spec-Driven Development、SDD)は、コードを書く前に仕様を文書にし、その仕様に沿って AI エージェントに設計・タスク分解・実装をさせる進め方です。 GitHub の Spec Kit は、SDD を「どう作るか(how)を決める前に、何をなぜ作るか(what と why)を定義する」進め方と説明しています。

ツール 仕様として作るもの 公式の説明
Kiro requirements.md・design.md・tasks.md ユーザーストーリーと受け入れ基準、設計、追跡できるタスクに分ける
GitHub Spec Kit 仕様・技術計画・タスク /speckit-specify・/speckit-plan・/speckit-tasks などで順に作る

AI に渡す仕様でも、大事なことは人に渡す仕様と同じです。 入力・ルール・エラー・受け入れ条件が具体的なほど、AI が作るコードのずれは小さくなります。この記事の会議室予約の機能仕様と受け入れ条件の表は、そのまま AI への指示にも使える形です。AI に渡す仕様書のテンプレートと進め方は、関連記事「仕様駆動開発(SDD)とは?AIに渡す仕様書テンプレートと進め方」で扱っています。

仕様を書くときのチェックリスト

この節では、仕様を書き終えたときに見直す点が分かります。

  • 1どの要件のための仕様かが書いてあるか要件の番号(REQ-03 など)と目的。後で変えるときの判断の元になる
  • 2入力の型・必須・桁数・範囲が数値で書いてあるか「長すぎない」ではなく「1〜50文字」
  • 3端の値の扱いが書いてあるかちょうど4時間・定員ちょうど・終了と開始が同じ時刻
  • 4エラーの条件と返し方が全部あるか状態コード・エラーコード・利用者への伝え方
  • 5速さ・量などの非機能が数値で書いてあるか「すぐに」ではなく「1秒以内(95%)」
  • 6受け入れ条件が具体例で並んでいるかこの入力ならこの結果。そのままテストにできる形
  • 7版と変更履歴が残っているかいつ、何を、なぜ変えたか。API の仕様は info.version も上げる

チェックリストの3番(端の値)と6番(受け入れ条件)が抜けると、この記事の OVERLAP の例のように、作る人ごとに動きが変わります。

よくある質問

Q. 仕様とは簡単に言うと何ですか? A. システムや製品が「何を、どんな条件で、どう動くか」を決めた約束ごとです。たとえば「画像は10MBまで送れる」「予約は30分単位」のような決まりが仕様です。

Q. 仕様の読み方と英語は? A. 「しよう」と読みます。英語は specification(スペシフィケーション)で、略して spec(スペック)と言います。仕様書は specification document や spec と呼ばれます。

Q. 仕様と使用の違いは? A. 仕様は作りや決まりのこと、使用は物を使うことです。どちらも「しよう」と読みますが、「仕様書」「仕様変更」を「使用」と書くのは誤りです。

Q. 仕様と要件の違いは? A. 要件は「何のために、何が必要か」というゴール、仕様は「それを満たすために、何をどう動かすか」の具体的な決まりです。「ダブルブッキングを無くしたい」が要件、「時間が重なる予約は 409 で断る」が仕様です。

Q. 仕様と設計の違いは? A. 仕様は利用者から見た「何を・どう動くか」、設計は「それをどう作るか」(テーブル・クラス・処理の順番)です。仕様が同じでも、設計は何通りもあります。

Q. 仕様とスペックの違いは? A. スペックは specification の略で、意味は同じです。日本語では、パソコンの CPU やメモリのような性能・数値の一覧を「スペック」と呼ぶことが多く、仕様の一部(性能の欄)を指して使われます。

Q. 「仕様です」とはどういう意味ですか?バグとの違いは? A. 「決めたとおりの動きで、作りの誤り(バグ)ではない」という意味です。仕様書どおりに動かないのがバグ、仕様書どおりだが困る動きは仕様の誤りで、仕様変更として直します。

Q. 仕様書とは何ですか?誰が書きますか? A. 仕様を文書にまとめたものです。要件定義書は発注者と一緒に、機能仕様書・画面仕様書・API 仕様書は設計を受け持つエンジニアが書くことが多く、テスト担当や API を使う側がレビューします。

Q. 外部仕様と内部仕様の違いは? A. 外部仕様は利用者から見える動き(画面・入力・出力・エラー・API)、内部仕様はプログラムの中の作り(クラス・テーブル・処理)です。基本設計書は外部仕様、詳細設計書は内部仕様にあたることが多いです。

Q. 仕様変更とは?費用はかかりますか? A. 一度決めて合意した仕様を後から変えることです。作り直しとテストのやり直しが発生するため、影響を調べ、費用と納期の変化に関係者が合意してから進めます。

Q. API 仕様書とは?OpenAPI とは? A. API 仕様書は、URL・メソッド・送るデータと返るデータの形・エラーを決めた文書です。OpenAPI は、それを YAML か JSON で書く決まりで、検証ツールでの確認・ドキュメントの生成・応答のチェックに使えます。

Q. 仕様駆動開発とは? A. コードを書く前に仕様(要件・設計・タスク)を文書にし、それに沿って AI エージェントに実装させる進め方です。Kiro や GitHub Spec Kit がこの形を取っています。

まとめ

  • 仕様は「何を、どんな条件で、どう動くか」の約束ごと。仕様書はそれを書いた文書。読みは「しよう」、英語は specification(spec)。
  • 要件は「何が必要か」、仕様は「その具体的な決まり」、設計は「どう作るか」。迷ったら「利用者から見た動き(外部仕様)」か「中の作り(内部仕様)」かで見分ける。
  • 機能仕様書には、入力・業務ルール・出力・エラー・非機能・受け入れ条件を書く。端の値の扱いまで書くと、読み違いが無くなる。
  • 受け入れ条件はそのままテストになる。「重ならない」の一文が無かった実装は11件中2件で失敗し、直すと全件通った。
  • 「仕様です」は決めたとおりの動きという意味。仕様書に書いていない動きは、仕様の漏れとして扱う。
  • 仕様変更は、記録→影響分析→合意→仕様書の改訂→テストの順。上限を4時間から3時間にした変更は、受け入れ条件のテストが1件失敗して影響を示した。
  • API の仕様は OpenAPI で書き、openapi-spec-validator と Redocly CLI で確かめ、実際の応答とも照らす。

参考・出典

確認日はいずれも 2026年10月23日です。

  • コトバンク「仕様」(デジタル大辞泉・精選版日本国語大辞典・IT用語がわかる辞典):https://kotobank.jp/word/仕様
  • Wikipedia「仕様書」:https://ja.wikipedia.org/wiki/仕様書
  • OpenAPI Initiative「OpenAPI Specification v3.2.1」:https://spec.openapis.org/oas/latest.html
  • PyPI「openapi-spec-validator」:https://pypi.org/project/openapi-spec-validator/
  • Redocly「lint(Redocly CLI)」:https://redocly.com/docs/cli/commands/lint
  • Redocly「security-defined rule」:https://redocly.com/docs/cli/rules/oas/security-defined
  • Kiro Docs「Specs」:https://kiro.dev/docs/specs/
  • GitHub「github/spec-kit」:https://github.com/github/spec-kit

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「仕様とは|要件・設計との違いと仕様書の書き方をIT開発の実例で解説」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?