iT邦幫忙

2026 iThome 鐵人賽

DAY 20
0
Vibe Coding

夢幻甜品師闖工程世界:Vibe Coding vs 專業開發的 0→1 冒險攻略系列 第 20

Day 20|同一張訂單,前台後場怎麼可以各自解讀?從 API 契約看懂 API 文件

  • 分享至 

  • xImage
  •  

昨天,我們把一支 Web API 裡會出現的 Method、Path、Parameter、Request、Response、Status Code,一個一個放回同一張 HTTP 溝通地圖裡。

但知道 API 是怎麼說話之後,下一個問題是:

Frontend 和 Backend 怎麼確定,彼此理解的是同一套規則?

假設 Frontend 以為 Backend 會回:

{
  "title": "週末下午茶"
}

但 Backend 實際回的是:

{
  "name": "週末下午茶"
}

問題不一定是哪一邊 Code 寫錯了。

而是:

Frontend 和 Backend 對這支 API 的規則,根本沒有對上。

那到底要怎麼把這些規則先講清楚,讓兩邊都照同一套來?

這就是今天的主角:

API Contract(API 契約)。


API Contract 到底是什麼?

API Contract(API 契約),可以先理解成:

API 的使用者和提供者,先把「怎麼呼叫、怎麼回應」講清楚的規則。

放在前後端分離的 Web 專案裡,就是 Frontend 和 Backend 要先對齊:

要呼叫哪一支 API?
要傳什麼資料?
資料長什麼樣?
成功會收到什麼?
使用這支 API 有哪些限制?

所以 API Contract 不是某一個固定格式的檔案。

真正重要的是,把雙方要遵守的內容講清楚。

先直接看一份人類比較好讀的示意版本。

假設現在要定義:

取得單一活動

API:取得單一活動

Method(HTTP 方法)
GET

Path(路徑)
/api/activities/{id}

Path Parameter(路徑參數)
id
→ string 字串
→ required 必填
→ Activity ID

Authentication(身分驗證)
需要登入

Success Response(成功回應)
200 OK

Response Body(回應內容)

{
  "id": "abc123",
  "title": "週末下午茶",
  "location": "台北"
}

Response Schema(回應資料結構)

id
→ string 字串
→ required:回應中必須存在

title
→ string 字串
→ required:回應中必須存在

location
→ string 字串
→ nullable 可以是 null

Failure Response(失敗回應)

404 Not Found
→ 找不到指定活動

一支 API 的契約,不只是:

「這個網址可以打。」

它還要把:

怎麼呼叫
↓
要帶什麼
↓
資料怎麼規定
↓
最後會拿到什麼

講清楚。

Method、Path、Parameter 這些昨天已經拆過的部分,今天就先跳過啦~

接下來,就來看這份 Contract 裡,還沒被我們拆解過的 Schema(資料結構規格)。


Schema:資料到底要長什麼樣?

假設一支建立活動的 API 只說:

請傳一個 Request Body。

這句話其實還遠遠不夠。

因為 Frontend 下一秒就會開始問:

裡面有哪些欄位?
title 是文字還是數字?
一定要傳嗎?
location 沒資料時怎麼辦?
時間要用什麼格式?

這些就是 Schema(資料結構規格)在處理的事情。

例如:

Request Body
│
├─ title
│  ├─ type:string 字串
│  └─ required:必填
│
├─ location
│  ├─ type:string 字串
│  └─ optional:選填
│
└─ startAt
   ├─ type:string 字串
   ├─ format:date-time 日期時間
   └─ required:必填

也就是說,Contract 不只要說:

「有一個 title。」

還要說:

「title 是 string,而且必填。」

甚至「欄位可以不出現」,和「欄位存在但值是 null」,對使用端來說也可能代表兩種不同的 Contract。

但 Contract 也不是把這些欄位填完就結束了。

接下來還要決定,Frontend 之後到底要照哪一套規則來送資料、讀資料。

例如:

日期時間統一用什麼格式?

沒有資料時,
是回 null,
還是乾脆不出現這個欄位?

列表資料很多時,
要不要 Pagination(分頁)?

像分頁就可能設計成:

?page=2

也可能是:

?cursor=abc123

分頁本身還有不同做法,今天先不往下展開。

重點是:

只要這個決定會改變 Frontend 怎麼呼叫 API、怎麼讀資料,它就可能成為 API Contract 的一部分。


為什麼叫「契約」?因為別人真的會依賴

假設 Backend 原本回:

{
  "title": "週末下午茶"
}

Frontend 已經按照這份 Contract 寫:

讀取 response.title

後來 Backend 把欄位改成:

{
  "name": "週末下午茶"
}

Backend 自己可能還是正常運作。

但既有 Frontend 已經按照原本的 Contract 寫好了。

現在就可能壞掉。

這類會破壞既有使用端相容性的修改,通常就屬於:

Breaking Change(破壞性變更)。

所以一支 API 一旦開始被別人依賴,問題就不再只是:

「Backend 現在能不能跑?」

還要問:

「已經依賴這份 API 的人,會不會被我一起改壞?」

既然這些規則真的會被別人依賴,那就不能只存在 Backend Code、聊天室紀錄,或某個人的腦袋裡。

這時就會進到下一層:

API Documentation(API 文件)。


API Documentation:把契約變成大家查得到的資訊

API Contract 是:

大家共同遵守的規則本身。

API Documentation(API 文件)則是:

把這些規則整理、保存成可以查閱的資訊。

所以兩邊內容看起來本來就會很像。

API 文件裡一樣可能會看到:

Method
Path
Parameters
Request Body
Schema
Responses
Authentication

因為它本來就是在描述那份 Contract。

差別在於:

API Contract
→ 我們承諾什麼

API Documentation
→ 把這些承諾整理成可以查閱的內容

而 API 文件也不一定要使用某一個特定工具。

最簡單可以自己寫 Markdown:

## 取得活動詳情

GET /api/activities/{id}

需要登入。

Path Parameter:
- id:Activity ID

成功:
- 200

找不到:
- 404

也可以整理在 README、Wiki、Notion,或其他 API 文件工具裡。

真正重要的是:

那份文件是不是還跟現在真正的 API 一致。


拿到一份 API 文件,我到底先看哪裡?

第一次拿到一份 API 文件,裡面可能密密麻麻列了一大堆 Endpoint。

最簡單的讀法,是沿著一次 Request → Response 的方向看:

Method + Path
→ 這支 API 做什麼?

Parameters / Request Body
→ 我要傳什麼?

Schema
→ 每個欄位怎麼規定?

Responses
→ 不同結果會收到什麼?

Authentication
→ 這支 API 需不需要身分驗證?

其實就是把昨天學過的 HTTP 結構重新拿來用。

昨天是在問:

「一次 API 溝通裡有哪些東西?」

今天讀 API 文件時,則是在問:

「這一支 API 對這些東西到底怎麼規定?」

只要抓住這個順序,看到一大份 API 文件時,就比較知道該從哪裡開始。

但每個人都自己寫文件,格式不就又不一樣了嗎?

所以如果希望這份文件有一套更標準化的描述方式,而且工具也能解析,就會進到接下來的:

OpenAPI。


OpenAPI:把同一份 API 用標準結構描述下來

OpenAPI Specification(OpenAPI 規格) 是一套用來描述 HTTP API 的標準規格。

它提供一套結構化方式,去表達:

有哪些 Path?
有哪些 Method?
Parameters 怎麼定義?
Request Body 長什麼樣?
Response 長什麼樣?
需要什麼 Authentication?

所以 OpenAPI 不是另一份新的 API Contract。

比較接近:

API Contract
→ 規則本身

API Documentation
→ 把規則整理成可以查閱的文件

OpenAPI
→ 用標準化、結構化格式描述 HTTP API

前面那份「取得單一活動」的人類好讀版,如果換成一小段 OpenAPI,大概會看到這樣:

paths:
  /api/activities/{id}:
    get:
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string

      responses:
        "200":
          description: 取得活動成功

        "404":
          description: 找不到活動

現在不用學 YAML 語法。

只要把它跟前面那份 Contract 對照:

/api/activities/{id}
→ Path(路徑)

get
→ Method(HTTP 方法)

parameters
→ 這支 API 需要哪些參數

id
→ Path Parameter(路徑參數)

required: true
→ 必填

schema
→ 資料結構規格

responses
→ 可能出現的 Response(回應)

其實描述的還是同一件事。

差別只在於:

前面是方便人理解的整理方式;OpenAPI 則提供一套有固定結構、工具也能解析的描述方式。


BuJo:文件寫下來之後,還要跟實作對得起來

BuJo 原本就有手寫的 API_DOCS.md,後來再把 API 文件整理成 OpenAPI,並搭配 swagger-jsdocswagger-ui-express,讓 API 可以透過 /api-docs 查看。

整理的過程中,我們也重新把文件和實際的 Route、Controller 一支一支對照。

這時才發現,有些地方兩邊其實沒有完全一致。

例如某支 API 在活動不存在時,文件原本記錄的是:

400

但 Code 實際回的是:

404

這件事反而讓我更理解 API 文件的價值。

文件不是寫完就永遠正確的答案,而是一份可以讓團隊共同查看、比對和維護的 Contract 描述。

API 改了,文件也要跟著更新;真的出現落差時,至少還有一個共同基準,可以把「原本約定的是什麼」和「現在實作的是什麼」攤開來確認。


接得起來,只是第一步

我現在再看 API Contract,最有感的是:

只要使用端開始依賴某個 API 行為,它就不再只是 Backend 裡的一個實作細節,而是一份對外的承諾。

把這些規則寫清楚、留下來,真正重要的不是多一份文件,而是讓 Frontend、Backend,甚至之後接手的人,都知道現在共同遵守的是哪一套。

而這份「共同遵守的規則」,當然也不只管事情順利完成的時候。

原來連失敗之後要怎麼走,都要先排練!?

明天,就繼續來拆這條失敗路線。


上一篇
Day 19|前台喊單,後場真的聽得懂嗎?從 API 看懂前後端怎麼用 HTTP 說話
下一篇
Day 21|甜點做壞了,總不能只說「出錯了」吧?從狀態碼看懂 API 錯誤處理
系列文
夢幻甜品師闖工程世界:Vibe Coding vs 專業開發的 0→1 冒險攻略30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言