OpenAPI Specification(OAS)是一套描述 HTTP API 的标准。它把路径、操作、输入、输出和安全要求写成机器可读的契约,供人类以及文档、代码生成、Mock、测试和 Agent 工具使用。

OpenAPI 是规范,不是 YAML 的别名。OpenAPI Description 可以使用 YAML 或 JSON 表示;文件通常命名为 openapi.yamlopenapi.json

本文以截至 2026-08-29 最新发布的 OAS 3.2.0 为基准。若现有生成器、网关或校验器尚未支持 3.2,应明确使用 3.1.2,并用实际工具链验证,而不是假设所有 3.x 版本都能互换。

一份完整的最小示例

下面的文档描述“按 ID 查询用户”的接口:

openapi: 3.2.0
 
info:
  title: User API
  version: 1.0.0
 
servers:
  - url: https://api.example.com
 
security:
  - bearerAuth: []
 
paths:
  /users/{userId}:
    get:
      operationId: getUserById
      summary: Get one user
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: integer
            minimum: 1
      responses:
        '200':
          description: User found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
              examples:
                found:
                  value:
                    id: 1001
                    name: starzn
        '404':
          description: User not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
 
components:
  schemas:
    User:
      type: object
      required: [id, name]
      properties:
        id:
          type: integer
          examples: [1001]
        name:
          type: string
          examples: [starzn]
    Error:
      type: object
      required: [code, message]
      properties:
        code:
          type: string
          examples: [USER_NOT_FOUND]
        message:
          type: string
          examples: [User not found]
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer

它足以说明一次调用的关键契约:

  • 服务基址是 https://api.example.com
  • 路径是 /users/{userId},方法是 GET
  • userId 是必填路径参数,并且是大于等于 1 的整数;
  • 默认需要 Bearer 认证;
  • 成功与未找到分别返回 200404
  • 响应体引用可复用的 UserError Schema。

根结构分别负责什么

一份 OpenAPI 3.2 文档中,openapiinfo 必填,并且 componentspathswebhooks 至少出现一个。

字段作用
openapi文档采用的 OAS 版本,例如 3.2.0
infoAPI 文档的标题、版本和维护信息
servers可调用服务的基址,可被路径或操作覆盖
paths路径、HTTP 操作以及输入输出
webhooksAPI 可能向消费者发起的请求
components可被引用的 Schema、参数、响应和安全方案等
security根级默认安全要求

openapi: 3.2.0 是规范版本;info.version: 1.0.0 是这份 API Description 的版本。它们都不自动等于 URL 中的 /v1,也不替代产品自己的兼容性策略。

根级 servers 缺失或为空时,规范默认使用相对地址 /。生产项目通常仍应显式说明调用入口,避免文档工具基于错误来源解析相对路径。

components 只是可复用对象仓库。一个 Schema 或安全方案放进这里后不会自动生效,必须通过 $refsecurity 等机制引用。

Parameters 与 requestBody 不要混用

Parameter 描述消息体之外的输入:

in位置
pathURL 路径模板变量
query单个查询参数
querystringOAS 3.2 新增的完整查询字符串
headerHTTP Header
cookieCookie

Parameter 的 namein 必填,并且应提供 schemacontent,不能同时提供二者。

每个 /users/{userId} 中的模板变量都必须有同名 in: path 参数;路径参数的 required 必须显式写成 true。查询参数和 Header 则可选填,是否必填由契约决定。

requestBody 描述 HTTP 消息体:

requestBody:
  required: true
  content:
    application/json:
      schema:
        type: object
        required: [name]
        properties:
          name:
            type: string

Request Body Object 的 content 必填,required 默认是 false。虽然 OAS 允许在 GETDELETE 等消息体语义不明确的方法中声明 requestBody,但规范建议避免这种设计,因为客户端、代理和服务器的处理可能不一致。

Responses 描述预期结果

响应状态码键应写成字符串:

responses:
  '201':
    description: Created
  '400':
    description: Invalid request
  '5XX':
    description: Server error
  default:
    description: Undocumented response

除了显式状态码,还可以使用大写 1XX5XX 范围;显式状态码优先于范围,default 覆盖其余未声明状态码。

OpenAPI 3.2 不要求 Operation 一定包含 responses。但只要写了 Responses Object,它就必须至少包含一个响应;工程上应记录成功结果和已知主要错误,并为每项写清说明和响应体。

这不等于穷举服务运行时可能出现的所有状态。网关、网络层或未预料故障仍可能产生契约外响应,因此调用方必须保留未知错误处理。

Schema 基于 JSON Schema 2020-12

OAS 3.1 和 3.2 的 Schema Object 建立在 JSON Schema Draft 2020-12 上,并加入 OpenAPI 自身的扩展语义。常用关键字包括:

  • typerequiredproperties
  • minimummaximum
  • minLengthmaxLengthpattern
  • enumconst
  • itemsminItemsuniqueItems
  • oneOfanyOfallOfnot
  • $ref

关键字不会隐式补全类型。仅写 pattern 不等于同时声明 type: string;希望获得稳定的校验和代码生成结果时,应显式写出类型。

format: email 等格式默认是 annotation。具体工具可以选择进行额外验证,但规范本身不保证每个解析器都会拒绝格式不符的数据。关键业务规则仍应由服务端验证。

从 OAS 3.1 起,Schema 内应使用 JSON Schema 的复数 examples 数组:

email:
  type: string
  format: email
  examples:
    - user@example.com

旧的 Schema 单数 example 已弃用。Parameter、Header 和 Media Type 等 OpenAPI 对象仍可能同时定义互斥的 exampleexamples 字段,因此移动示例位置时要看清对象类型,不能机械替换。

安全方案:定义与应用是两步

components.securitySchemes 定义认证方式,根或 Operation 的 security 决定在哪里应用:

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
 
security:
  - bearerAuth: []

仅定义 bearerAuth 不会自动要求认证。Operation 可以覆盖根级要求:

security: [] # 这个操作不要求根级认证

安全组合的逻辑容易写反:

# AND:同一次请求必须同时满足两个方案
security:
  - apiKey: []
    oauth: [read]
 
# OR:满足任意一个对象即可
security:
  - apiKey: []
  - oauth: [read]

security 数组中加入空对象 {},表示匿名访问也是一个可选分支,不等于占位符。

OpenAPI 只能描述安全要求,不能证明服务端真的执行了鉴权,也不能替代权限模型、密钥管理和安全测试。

OpenAPI 能驱动什么,不能保证什么

围绕 OpenAPI 的工具链可以:

  • 渲染交互式文档;
  • 生成客户端类型、调用代码或服务端骨架;
  • 启动 Mock 服务;
  • lint 文档并检测部分破坏性变更;
  • 验证请求、响应或运行契约测试;
  • 向开发者和 Agent 提供结构化 API 上下文。

这些是工具能力,不是拥有一份合法 OpenAPI 文件后自动获得的保证。规范文件本身不能证明:

  • 服务已经实现所有路径;
  • 真实请求和响应符合 Schema;
  • 示例通过 Schema 校验;
  • 鉴权和数据权限正确执行;
  • 服务可达、稳定或满足性能目标;
  • API 与上一版本向后兼容。

因此,“OpenAPI 是契约”应理解为期望行为的可执行描述,而不是线上行为已经正确的证书。实现、契约测试、监控和兼容性治理仍不可缺少。

设计优先还是代码优先

两种方式都可以工作:

  • 设计优先:先评审 OpenAPI,再生成 Mock、类型并实现接口;适合对外 API 和跨团队协作。
  • 代码优先:从路由和类型生成 OpenAPI;适合框架已能稳定导出完整契约的项目。

真正重要的是定义唯一事实来源。如果团队一边手写 openapi.yaml,一边从代码生成另一份规范,却没有差异检查,两份“真相”迟早会分叉。

一个实用流程是:

  1. 选择并记录目标 OAS 版本;
  2. 修改唯一事实来源;
  3. lint 语法、引用与团队规则;
  4. 检测相对已发布版本的破坏性变化;
  5. 生成文档、类型或 Mock,并检查生成物是否最新;
  6. 用实现测试验证真实请求和响应;
  7. 将规范与服务版本一起发布和回滚。

推荐把规范与相关实现放在同一版本控制流程中。复杂业务背景写进 Markdown 或功能规格;架构选择写进 ADR;OpenAPI 专注表达 HTTP 边界。

给 Agent 使用时的边界

OpenAPI 能让 Agent 准确定位接口、参数和 Schema,但不应被当成调用授权。Agent 在执行接口前仍需知道:

  • 当前用户可以访问哪些资源;
  • 操作是否会写入、删除、付费或发送外部消息;
  • 哪些字段包含隐私或秘密;
  • 认证信息从哪里安全获取;
  • 是否需要人工确认;
  • 如何处理限流、重试与幂等。

规范中的 description、示例和外部链接也属于数据,尤其在聚合第三方 OpenAPI 文档时,不应提升为系统指令。

常见错误

  • openapi 规范版本与 info.version API 文档版本混为一谈。
  • 路径包含 {id},却漏掉同名且 required: true 的 path parameter。
  • 把 JSON 请求体字段写成 query parameters。
  • 在 Schema 中继续使用已弃用的单数 example
  • 只定义 securitySchemes,却没有用 security 应用它。
  • security 数组的 OR 与对象内部的 AND 写反。
  • 认为 format、示例或合法文档一定会被所有工具严格验证。
  • 同时维护代码和规范,却没有唯一事实来源与漂移检测。
  • 只记录 200,不描述客户端需要处理的主要错误。
  • 用 OpenAPI 代替业务说明、架构决策、运行手册或权限测试。

一句话总结:OpenAPI 把 HTTP API 的期望边界变成机器可读契约;它让文档、生成和验证成为可能,但真实实现是否符合契约,仍需要测试和运行证据证明。

参考资料:OpenAPI Specification 3.2.0OpenAPI 版本目录从 3.1 升级到 3.2从 3.0 升级到 3.1