应用程序接口(API)是一组确定的操作、数据类型、约定和规则,软件组件通过它使用另一个组件的功能。接口规定了调用方可以请求什么、将得到什么结果,同时隐藏提供方如何完成工作。这种稳定契约与可变实现之间的分离,使程序员能够基于他人编写的代码进行开发,使系统可以在不破坏用户的前提下被替换或升级,也使不同的组织和机器能够交换服务。这一思想是软件工程的核心,几乎支撑着所有现代程序,从为系统调用提供接口的操作系统内核,到从云服务获取数据的移动应用,都离不开它。
这一概念已从早期计算时代的本地子程序库,发展为支撑万维网、移动平台、支付网络和云计算基础设施的 Web API。其设计选择包括 REST、GraphQL 和 gRPC 等架构风格、事件驱动接口、机器可读的规范以及版本管理规则,这些选择受到简洁性、性能、安全性与长期兼容性之间权衡的影响。API 还引发了经济和法律方面的问题,因为它们既可以作为平台和竞争工具,也可能成为知识产权纠纷的对象。
本词条首先定义核心概念并梳理 API 的历史发展。随后概述主要类型和架构风格,再依次介绍接口描述、请求处理、安全、版本管理与设计实践的机制。最后几节涵盖文档与开发者体验、测试与性能、管理与商业模式、法律与竞争问题、各领域的应用、与其他学科的关系,以及包括 AI 系统使用 API 这一新兴现象在内的开放性问题。
定义与核心概念
应用程序编程接口(API)是一个软件组件向其他组件开放使用的一组操作、输入、输出、数据类型和错误条件。它充当提供方与使用方之间的契约:提供方负责实现行为,使用方则依赖这些行为。契约规定的内容包括提供方承诺的结果、调用的代价,以及调用在何种条件下会失败。它并不规定提供方如何实现这些结果。
公共接口与私有实现
公共接口是组件中使用方可以依赖的部分。私有实现则是其余的一切,包括内部数据结构、辅助例程、存储格式和算法。头文件中的函数声明就是典型例子:声明给出了名称、参数和返回类型,而函数体则是隐藏的。只要声明的契约仍然成立,提供方就可以重写、优化函数体,甚至整体替换,使用方不受影响。契约还包括一些非正式的承诺,例如前置条件、副作用、线程安全保证和顺序规则,这些往往与函数签名同样重要。
抽象与信息隐藏
抽象使开发者能够依据组件的行为来使用它,而无需了解其内部细节。信息隐藏原则最具影响力的表述来自 David Parnas 1972 年的论文《关于将系统分解为模块的准则》("On the Criteria To Be Used in Decomposing Systems into Modules")。Parnas 主张,模块边界应围绕那些可能发生变化的设计决策来划定,且每个模块只应暴露其他模块所需的内容。他以关键词上下文索引问题为例,比较了基于处理步骤的分解与基于隐藏决策的分解,结果表明第二种方法使后续修改的代价小得多。API 正是这一边界的实际形式:接口保持稳定,而数据表示等被隐藏的决策则可以自由演进。这一思想也是软件工程实践的普遍基础。
区分 API 与相关概念
- 应用二进制接口(ABI): ABI 是二进制层面的契约。它规定调用约定、数据布局、类型大小、对齐方式和符号名称,使编译后的机器码无需重新编译即可互操作。API 则是源代码层面的契约。同一个库的两个版本可能保持 API 不变却破坏 ABI,从而迫使依赖它的程序重新构建。出于这一原因,可参见 应用二进制接口。
- 网络协议: 协议规定通信双方在网络上交换的规则和消息格式,包括消息顺序、帧结构和错误信号的传递方式。TCP/IP 和 HTTP 都是协议。基于 HTTP 构建的 API 则规定应用层的操作,例如存在哪些资源、请求必须包含哪些字段。协议说明数据如何传输,API 说明程序可以请求什么。
- 库: 库是打包好的可复用代码集合,API 则是库对外暴露的接口。一个库可以提供多个 API,一个 API 也可以由多个不同的库或某个远程服务来实现。
- 软件开发工具包(SDK): SDK 通常是一个捆绑包,包含一个或多个 API、库、文档、示例代码,以及针对特定平台的编译器、调试器或模拟器等工具。API 是契约,SDK 则是让使用这一契约变得切实可行的工具包。
API 的基本要素
无论采用何种风格,大多数 API 都由以下相同的基本部分组成:
- 操作或端点: 使用方可以调用的具名动作,例如函数或方法;在 Web API 中,则是 URL 路径与 HTTP 方法的组合。
- 参数: 操作所接受的输入,包括哪些是必需的、哪些是可选的、它们的类型,以及允许的取值范围或格式。
- 返回值: 操作产生的结果及其结构,包括结果是否可能为空。
- 数据类型: 用于表示信息的类型体系,例如整数、字符串、时间戳、枚举和嵌套记录。双方对这些类型的理解不一致,是集成错误的常见来源。
- 错误条件: 操作可能失败的既定方式,以异常、错误码或结构化错误响应的形式表达,并附带触发这些错误的条件。
一个规范完善的 API 会精确定义以上五类要素,使使用方无需阅读实现代码即可正确使用它。这些要素也是后续主题的出发点,例如软件文档、版本管理以及 Web 接口的设计。
历史发展
API 的理念早于这个词本身。其最早的清晰形式是 1940 年代和 1950 年代的可复用子程序库。1951 年出版的那本书,是 1950 年 9 月撰写的一份报告的大规模印刷版,该报告标题为《EDSAC 程序编制及子程序库使用报告》,仅供内部传阅,分发对象不超过 100 人。作者莫里斯·威尔克斯(Maurice Wilkes)和大卫·惠勒(David Wheeler)将他们的例程保存在打孔纸带上,并整理在档案柜中。书中附带的每个例程的使用说明,就是现代读者所认识的 API 文档:这样的目录之所以被称为 API(或 API 规范、API 文档),是因为它指导程序员如何使用每个子程序。
1950 年代和 1960 年代的大型机计算塑造了下一阶段。程序通常以批处理方式在共享机器上运行,当时的软件往往是庞大的单体式代码。子程序是将这类程序拆分为可由不同人员编写和调用的部分的主要方式。操作系统增加了自己的服务层,而硬件市场高度分散,因此每台新机器往往意味着软件要重写。1964 年推出的 IBM System/360 系列及其操作系统 OS/360,是让同一套软件基础能够跨多个机型运行的早期尝试。
这一术语本身出现于 1968 年。"application program interface"(不带 -ing 后缀)一词最早见于 1968 年 AFIPS 会议上发表的论文 Data structures and techniques for remote computer graphics。作者用它来指代图形程序与系统其余部分之间的交互,其 API 的目标是使与硬件无关的程序成为可能。1974 年,C. J. 戴特(C. J. Date)在题为 The Relational and Network Approaches: Comparison of the Application Programming Interface 的论文中将这一术语引入数据库领域。此后,这一理念进入了当时的关系数据库架构标准。
Unix 贡献了稳定的系统调用接口这一理念。POSIX 的根源可以追溯到 1970 年代贝尔实验室开发的早期 UNIX。open() 和 write() 等调用为程序提供了一种文件抽象,隐藏了文件系统的内部细节。然而,随着 Unix 在各厂商之间扩散,软件可移植性成为一大挑战,为某一 UNIX 变体编写的应用程序,往往需要修改才能在另一变体上运行。
POSIX 正是对此问题的回应。1980 年代中期,IEEE 启动了正式的标准化工作(1003 项目,即"P1003"),旨在定义一套一致的、与厂商无关的接口。IEEE 于 1988 年发布了该标准的第一版,名为 IEEE Std 1003.1-1988。该标准以 System V 和 BSD Unix 为基础制定。POSIX 并不定义操作系统本身,而只定义应用程序与操作系统之间的接口,因此程序在源代码层面可以移植到其他操作系统。此后十年间,该标准不断扩展:1992 年的 POSIX.2(shell 和实用工具)、1993 年的 POSIX.1b(实时扩展)、1995 年的 POSIX.1c(线程扩展)。1997 年之后,为简化管理,所有 POSIX 标准被统一归入一个框架之下。
1980 年代末和 1990 年代,这一术语从大型机扩展到个人电脑和面向对象软件领域。计算机早期经历了从 1960 年代占用整个运行时段的大型机,到 1980 年代初个人电脑时代的发展。面向对象语言使类库变得切实可行:开发团队可以创建类库,供后续项目使用。框架这一理念,即库反过来调用用户代码,可追溯到 SIMULA 67 最重要的贡献之一。Windows 引入了封装不同程序模块的动态链接库(DLL),图形工具包和 Windows API 成为许多开发者日常语境中该术语的含义。随着术语含义的扩展,它最初只描述面向最终用户的程序(即所谓的应用程序)的接口,这一起源至今仍体现在"应用程序接口"这一名称中。如今,该术语的含义更加宽泛,还包括实用工具软件,甚至硬件接口。
向 Web API 的转变发生在千禧年之交。互联网和万维网确立之后,服务提供者开始通过 HTTP 向外部开发者开放其数据和服务。早期的例子包括电子商务和在线市场。亚马逊、eBay 和 Salesforce 等公司成为 API 热潮的主角,允许第三方开发者在其平台之上构建应用。随后出现了地图服务,21 世纪初的电商网站和地图服务提供商表明,远程接口能够带来流量并催生第三方产品。这些早期的 Web 接口使用基于 XML 的 RPC 和 SOAP 消息,下文的 Web 架构一节将对此进行讨论。
按范围与受众划分的 API 类型
API 通常根据其运行的位置、预期的使用者,以及调用是否停留在同一进程内还是跨越网络来分类。这些分类相互交叉,同一个接口可能同时属于几类。
按范围划分:语言、操作系统、硬件与 Web API
语言或库 API 是 编程语言 或其随附的库向程序员公开的一整套类型、函数和约定,例如开发者导入使用的标准集合或文件处理模块。操作系统 API 是操作系统向应用程序提供的一组服务,通常是用于文件、内存、进程和网络的系统调用;应用程序发出请求,由内核代其执行。硬件驱动程序接口是操作系统与设备驱动程序之间的约定,驱动程序将通用请求转换为特定磁盘、显卡或网卡能够理解的命令。远程或 Web API 通过网络访问,通常使用 HTTP,也是如今人们提到 API 时最常指的那一类,相关内容可参见万维网和互联网词条。每一层都隐藏了其下层的细节,因此针对某个库编写的程序无需了解该库具体调用了哪些系统调用。
按受众划分:公开、合作伙伴与私有 API
提供方心目中的受众在很大程度上决定了 API 的治理方式。公开或开放 API 对任何注册的开发者开放,通常有详尽的文档、谨慎的版本管理,并受已公布的速率限制保护。合作伙伴 API 只与特定组织共享,通常基于合同,因此往往附带入驻流程、专用配额和协商确定的服务水平承诺。私有或内部 API 只在某个组织内部使用,例如连接薪资和人力资源系统,或让微服务之间相互调用。由于提供方掌控所有使用者,内部接口有时文档稀少且变更迅速;然而,缺乏外部压力也可能让粗糙的设计长期存在,并随着组织扩大而变得难以维护。这些标签描述的是预期用途,而非技术上的可达范围:一个可以从公共互联网访问的私有端点,在意图上仍是私有接口,真正执行边界的是访问控制,而不是标签。
框架与库:谁掌控流程
库是一组可复用的代码,应用程序在需要某项功能时调用它,因此每次调用发生的时间和位置由应用自身的逻辑决定。框架则颠倒了这种关系。它提供程序的整体结构,规定应用代码可以插入的位置,然后在适当的时刻由框架调用这些代码。这种模式被称为控制反转,这一术语与图形用户界面和企业软件的设计有关,在这些系统中,框架的事件循环或生命周期管理器决定何时运行处理程序。两者的界限并不总是清晰,许多工具包同时结合了两种风格,但判断的常用标准仍是:谁调用谁。调用开发者请求处理程序的 Web 框架,与在循环中调用的数值计算库,尽管都被称为 API,却呈现出截然不同类型的接口。
本地实现与远程实现
API 可以在进程内实现,即调用方与实现共享同一地址空间,一次调用几乎只是一次函数调用;也可以通过网络访问,此时每次调用都变成机器之间交换的一条消息。这种差异带来了实际影响。本地调用通常在纳秒到微秒量级完成,失败方式有限,通常是抛出异常或返回错误码。远程调用可能耗时毫秒甚至更久,可能在传输中丢失或重复,还可能出现服务器上已成功执行、而客户端却收到超时的情况,因此使用者必须处理部分失败、重试以及结果不确定的问题。安全性也随之改变:进程内接口依赖所在进程的内存保护,而网络接口必须对调用方进行身份验证、加密流量,并防御可能来自任何地方的攻击。若把远程调用包装在一个看似本地的方法之后,就可能误导开发者对延迟和可靠性的判断,这也是面向网络的 API 通常从一开始就要明确设计超时和错误类型的原因之一。
Web API 架构风格
Web API 通过互联网、使用标准应用层协议进行访问。在如何组织请求、负载和契约的问题上,曾有多种架构风格相互竞争。它们的主要区别在于:对消息的约束有多严格、接口有多少内容需要预先描述,以及设计是以数据资源为中心还是以远程操作为中心。
SOAP 与 XML-RPC
XML-RPC 由 Dave Winer 与微软于 1998 年提出,它将远程过程调用编码为通过 HTTP POST 发送的 XML 文档,只包含整数、字符串、布尔值、数组和结构体等少量有类型的值。SOAP 最初是 Simple Object Access Protocol(简单对象访问协议)的缩写,它源自这一脉络,并于 2000 年提交给 W3C。每条 SOAP 消息都包裹在一个 envelope(信封)中:可选的 header 用于承载安全令牌等元数据,body 则承载实际负载。错误通过结构化的 fault 元素报告。接口通常使用 WSDL(Web 服务描述语言)描述,它列出操作、消息类型和绑定;负载则由 XML Schema 进行校验。这种形式化的特点吸引了希望生成客户端桩代码并使用配套工具的企业,并催生了用于安全、可靠消息传递和事务的 WS-* 规范族。其代价是冗长和工具依赖重:手写 SOAP 客户端十分繁琐,在浏览器中使用也很困难,而且 WS-* 各实现之间的互操作性往往较差。
REST
表现层状态转移(REST)由 Roy Fielding 在 2000 年于加州大学欧文分校完成的博士论文中命名并定义。Fielding 将其描述为一种从万维网本身的设计中抽象出来的架构风格。它的约束包括:客户端–服务器分离、无状态(每个请求都携带处理该请求所需的全部信息)、可缓存性、统一接口、分层系统,以及可选的按需代码。在 Web API 中,REST 通常表现为由 URI 标识的资源,例如用路径指代某个订单,再通过标准 HTTP 方法对其进行操作。GET 用于获取资源表示且不产生副作用;POST 用于创建资源或触发处理;PUT 和 DELETE 被定义为幂等操作;PATCH 用于应用局部修改。结果通过按类别分组的 HTTP 状态码来表示:2xx 表示成功,3xx 表示重定向,4xx 表示客户端错误,5xx 表示服务器错误。由于 GET 响应通过 URL 寻址,并带有缓存指令,共享缓存和代理服务器可以存储它们,这也是 REST 与既有 Web 基础设施高度契合的原因之一。Fielding 的定义还要求以超媒体作为驱动应用状态的手段;大多数实际 API 并未这样做,这一点将在关于设计原则的一节中讨论。许多被标为"REST"的接口,其行为更接近于承载在 HTTP 之上的远程过程调用。Leonard Richardson 提出的 0 至 3 级成熟度模型等分级方法,正是用来描述这一光谱。
GraphQL
GraphQL 大约从 2012 年起在 Facebook 内部开发,并于 2015 年公开发布;现在它作为一项开放规范由社区维护。GraphQL 服务并不提供许多固定端点,而是暴露一个单一端点和一份带类型的模式(schema),用以描述对象类型及其字段。客户端发送一条查询,准确列出它需要的字段,包括嵌套关联对象的字段,并以相同结构收到 JSON 响应。这减少了过度获取(响应中包含未使用的数据)和获取不足(客户端需要多次往返才能拼装出相关记录)的问题。写操作通过 mutation 表达,实时更新则通过 subscription 表达。
这种灵活性也带来了代价。查询通常以 POST 请求体的形式发送到同一个 URL,因此让 REST 得以良好运作的基于 URL 的 HTTP 缓存不能直接适用;缓存需要转移到字段或解析器(resolver)层面、预先注册并以标识符引用的持久化查询,或客户端的规范化缓存中。客户端控制权的增强也会把成本转移到服务器端,因为一个嵌套很深或字段很宽的查询可能展开为大量后端调用。服务提供方的应对措施包括深度限制、复杂度评分、超时,以及按查询成本计量的速率限制。朴素的解析器实现可能会为列表中的每一项各发出一次数据库调用,即所谓的 N+1 问题,而批量加载器(batching loader)就是用来避免这一问题的。另外,授权必须逐字段、逐对象检查,而不能只在端点级别进行。
gRPC 与 RPC 风格
远程过程调用(RPC)风格早于 Web 出现,包括 Sun RPC、CORBA 和 Java RMI 等,它们把一次网络调用呈现为与普通本地函数调用无异。gRPC 由 Google 于 2015 年开源,是这一风格的现代代表。服务和方法在 Protocol Buffers 接口定义文件中声明,并可据此为多种语言生成客户端和服务端代码。消息以紧凑的二进制 Protocol Buffers 格式编码,并通过 HTTP/2 传输;HTTP/2 允许在单一连接上复用多个并发流,并压缩头部。gRPC 既支持一元调用,也支持客户端流、服务端流和双向流方法。
这些特性使 gRPC 非常适合组织内部的微服务通信:通信双方属于同一组织,序列化开销和延迟很重要,而且强类型契约可以减少集成错误。它在公共场景下的局限则较为实际:浏览器无法直接发起原生 gRPC 调用,需要借助 gRPC-Web 等转换层;二进制负载不便于用普通工具检查;兼容性则取决于对模式的严格演进。与其他 RPC 系统一样,它也容易让人忘记调用的分布式本质,因此超时、重试和部分失败都必须显式处理,这与任何分布式计算设计并无二致。
事件驱动与实时接口
请求–响应与事件驱动设计
大多数 Web API 采用请求–响应模式:使用方发送请求、等待并接收响应。提供方只在被请求时才作出回应。这种模式简单,但当使用方需要即时了解状态变化时效率低下。使用方必须轮询,即反复询问某件事是否已经发生变化。轮询是在延迟与负载之间做取舍:间隔太短会浪费大量请求,间隔太长则会延迟更新。
事件驱动设计则反转了主动权的方向。当相关状态发生变化时,提供方发布通知,使用方据此作出反应。同一个底层系统可以同时提供两种风格的接口。例如,支付服务既可以提供查询端点,用于获取某笔交易的当前状态,也可以在该状态变化时发送通知。
推送机制:Webhook、服务器发送事件与 WebSocket
Webhook 是一种 HTTP 回调。使用方向提供方注册一个 URL,当订阅的事件发生时,提供方会向该 URL 发送 HTTP POST 请求。Webhook 在支付、代码托管和即时通讯平台中很常见。由于使用方必须暴露一个可公开访问的端点,接收方通常会校验每个负载的签名,快速返回成功状态码,并异步处理实际工作。提供方通常会对失败的投递进行重试,因此接收方必须能够容忍重复投递和乱序到达。
服务器发送事件(SSE)保持单个 HTTP 响应处于打开状态,并以文本形式将事件从服务器流式推送到客户端。数据流是单向的,浏览器内置的机制可以自动重连,并从最后一个事件标识符处恢复。SSE 适用于新闻滚动条、进度指示器以及生成式模型的增量输出。
WebSocket 于 2011 年由 RFC 6455 标准化,它将 HTTP 连接升级为基于单个 TCP 连接的持久全双工通道。双方可随时发送消息。这种方式适用于聊天、多人游戏、协同编辑,以及金融服务中的行情数据流。其代价在于状态管理:每个连接都是长连接,因此负载均衡、重连逻辑以及故障后的重新订阅都成为需要考虑的设计问题。
消息代理与发布–订阅
在发布–订阅系统中,生产者将消息发布到命名的主题或频道,无需知道谁会消费这些消息。消息代理负责存储并转发这些消息。消费者订阅主题并接收消息副本,从而使一个事件可以扇出给多个相互独立的服务。由于代理会缓存消息,生产者与消费者在时间上是解耦的:消费者可以离线,之后再追赶未读消息。二者在位置和部署上也是解耦的,因为双方都无需知道对方的网络地址。Apache Kafka 和 RabbitMQ 等系统都实现了这一模型的不同变体,它们在消息顺序、保留策略和路由方面各有取舍。设计事件 API 时,需要像设计请求–响应契约一样,明确主题名称、消息结构(schema)及版本管理规则。
投递保证与幂等处理程序
消息系统会对投递做出明确承诺。至多一次(at-most-once)投递对每条消息只发送一次、不做重试,因此消息可能丢失,但绝不会重复。至少一次(at-least-once)投递会一直重试,直到消费者确认收到,因此消息不会丢失,但可能出现重复。恰好一次(exactly-once)处理,即每个事件只产生一次效果,在不可靠的网络上很难严格实现。实践中,系统通常通过组合至少一次投递与去重、事务性偏移量提交或幂等处理来近似实现它。消息的顺序保证也各不相同;许多代理只在分区或键的范围内保证消息有序。
因此,消费者处理程序应具备幂等性:对同一事件处理两次所产生的结果,必须与处理一次相同。常见的做法包括记录已处理事件的标识符、使用条件写入或版本检查,以及将状态变更设计为绝对赋值而非增量更新。若没有幂等处理,那些在传输层面安全的重试,就可能导致重复扣款、重复通知或记录不一致。
接口描述、模式与数据格式
机器可读的接口描述
机器可读的接口描述以软件能够解析的形式,记录 API 的操作、参数、数据类型和响应。对于基于 HTTP 的服务,应用最广泛的是 OpenAPI 规范(OpenAPI Specification),它源自 Swagger 规范,并于 2016 年移交给 Linux 基金会。OpenAPI 文档以 YAML 或 JSON 编写,列出每个路径、其上的操作、接受的参数和请求体、响应模式与状态码,以及所使用的安全方案。该规范并不要求重写现有服务,也不要求将软件与之绑定,因此描述文件既可以由运营方生成,也可以由第三方生成。
SOAP 时代的服务依赖 WSDL。2.0 版于 2007 年成为 W3C 推荐标准,它将服务的抽象功能(即交换的消息及其类型)与协议绑定、端点地址等具体细节分离开来。其前身 1.1 版未获 W3C 认可。GraphQL 使用带类型的模式,定义对象类型、查询和变更操作,客户端可以在运行时对该模式进行内省。对于二进制 RPC,协议缓冲区使用 .proto 文件定义消息和字段。每个字段都包含类型、名称和一个数字标签。在传输中标识字段的是这些标签而非名称,因此一旦消息投入使用,标签就绝不能重复使用。标签 1 至 15 以一个字节编码,标签 16 至 2047 以两个字节编码,19000 至 19999 的范围则保留给实现使用。已废弃的标签和名称应声明为 reserved,以免后续编辑者无意中将其重新分配。
机器可读描述的用途
由于描述本身是结构化数据,许多工具都可以使用它。文档生成器可以渲染交互式参考页面,代码生成器则可以生成多种语言的客户端库和服务端骨架。模拟服务器能够返回示例响应,使前端团队在后端尚未就绪时即可开始工作。验证器可以依据声明的模式检查传入的请求和传出的响应,比对工具则可以比较描述的两个版本,在发布前标出被删除的字段或已更改的类型。这些用途都依赖于描述的质量:如果文件与运行中的实现不一致,生成的客户端和模拟服务器就会误导使用者。这也是许多团队会从代码生成描述文件,或用描述文件来测试实现的原因,相关内容见文档与测试两节。
数据格式及其权衡
JSON 是基于文本的格式,可以直接在浏览器或日志文件中阅读,几乎所有语言都有相应的解析器支持,这也解释了它在 Web API 中的主导地位。其代价在于冗长,因为每个对象都会重复字段名;而且它的类型系统极为简单,没有原生的日期类型、二进制类型,也不区分整数大小。XML 同样是文本格式且具有自描述性,支持命名空间,并有 XML Schema 等模式语言,但通常体积更大、解析更慢,在企业、金融以及较早的 SOAP 系统中仍然常见。Protocol Buffers 是紧凑的二进制消息,其生成的类提供强类型访问,与等价的 JSON 相比,解析通常更快,载荷也更小。代价是没有模式就无法读取二进制消息,而且该库本身不压缩输出,因此往往需要在传输层另外添加数据压缩。其他二进制编码,如 MessagePack、CBOR 和 Avro,在类似场景中采用了各不相同的模式模型。在它们之间做选择,需要权衡便于调试的可读性与载荷大小、解析开销以及模式的严格程度。对真实载荷的实际测量,通常比一般性的经验法则更可靠。
序列化的陷阱
即使规范本身正确,许多互操作性故障仍然发生在序列化层。类型不匹配很常见:文档中规定为数字的字段可能以字符串形式到达,或者客户端期望可选字段缺省时,却收到了值为 null 的该字段。Protocol Buffers 通过严格的类型规定避免了部分问题,但在 proto3 中,未设置的数值字段与显式设为零的字段在传输中看起来完全相同,当零值本身具有含义时,这一点就会造成问题。
数值的表示方式会引发细微的错误。JSON 标准并未规定数值的精度,但许多解析器(包括 JavaScript 的默认解析器)会按照 浮点运算标准 IEEE 754 将其存储为双精度值,而这种格式只能精确表示不超过 2^53 的整数。因此,一个 64 位标识符或以最小货币单位表示的金额,可能在客户端被悄悄舍入。常见的补救办法是将这类数值以字符串形式传输。日期也会引发类似的问题:含糊的本地时间、缺失的时区偏移量,以及混淆以 Unix 纪元起算的秒数与毫秒数,都可能在没有任何错误提示的情况下使数据发生偏移。时间戳通常以带有明确偏移量的 ISO 8601 或 RFC 3339 字符串形式发送。
字符编码同样必须明确指定。系统之间交换的 JSON 通常采用 UTF-8 编码的 Unicode统一码,而 Protocol Buffers 则要求字符串字段必须是有效的 UTF-8。长度限制是常见的分歧来源,因为同一段文本按字节、UTF-16 码元或码点计数,结果各不相同。最后,模式验证必须决定如何处理未知字段:严格拒绝可以让错误尽早暴露,而宽容处理则使旧客户端能够兼容新增的字段。无论采用哪种方式,在边界处进行验证,并明确 null、默认值和缺失字段的处理规则,都能防止最常见的静默故障。
请求、响应与错误处理
一次 API 调用是一段结构固定的简短交互。调用方组装一个请求,其中包含端点(通常是一个 URL)以及表明预期操作的 HTTP 方法,并附带一些请求头,用于传递内容类型、可接受的响应格式以及标识调用方身份的凭证等元数据。写入类操作通常在请求体中携带数据负载,多为 JSON 格式。提供方对请求进行身份验证和校验,执行相应操作,然后返回状态行、响应头,以及大多数成功调用所附带的响应体。由于流量需要穿越互联网,并且常常经过负载均衡器、网关和代理,中间环节完全可能自行作出应答。因此,客户端收到的状态码可能根本不是被调用的应用程序返回的,错误处理时必须考虑响应的来源。
HTTP 状态码是三位数字,其首位数字给出大致的结果类别。4xx 响应表示请求本身存在问题,客户端应在修改请求后再重试,若原样重复请求,得到的仍是同样的结果。5xx 响应则表示服务器无法完成一个合法的请求,因此相同的请求在之后的尝试中往往能够成功。实践中,一些更细的区分同样重要:401 Unauthorized 表示缺少身份验证信息或身份验证无效,而 403 Forbidden 表示已通过身份验证,但无权访问该资源。429 响应表明已超出速率限制,503 则表示服务暂时不可用,通常是因为过载或正在维护。仅靠状态码的粒度较粗,因此设计良好的 API 会在响应体中加入结构化的错误对象。这样的对象通常包含稳定的机器可读错误代码、人类可读的错误消息、相关时指明出错的字段,以及可供支持人员追踪的请求标识符。客户端应当依据稳定的错误代码和状态码类别进行分支处理,而不是依赖消息文本,因为消息文本可能在不作通知的情况下被改写或翻译。若在响应体中隐藏错误,却返回成功状态码,则会破坏通用的监控、代理和重试逻辑,这是一种常见的设计缺陷。
分页决定了大型集合如何分批返回,而两种主要策略在数据变动时的表现并不相同。偏移量分页在 SQL 中表现为 LIMIT 与 OFFSET,在 URL 中则表现为页码,它要求服务器跳过若干条记录。偏移量分页会扫描并丢弃偏移量之前的每一行,因此翻到靠后的页面时要做大量额外工作,而第一页则不需要。它的一致性问题比开销更严重:如果两次请求之间有记录被插入或删除,它可能会悄无声息地漏掉或重复某些行。游标分页则返回一个不透明的位置标记,由下一次请求带回。基于键集(keyset)的游标通过索引列定位到上次看到的位置,因此无论翻到多深,开销大致保持恒定,并且在并发写入时结果依然稳定。其代价是游标无法直接跳转到任意页面,而且基于游标的遍历要求稳定的排序顺序。若仅按非唯一列排序而不加入决胜字段,生成的游标就不可预测,因此通常会把唯一标识符附加到排序键上。在两种方案之间切换本身就是对消费者的破坏性变更,这也使该主题与版本管理联系起来。
网络故障具有不确定性,而客户端的超时正是这种不确定性变得危险的地方。请求超时时,客户端无法判断服务器是否已经处理了该请求。对于 GET 这类安全方法,这并无大碍;但 HTTP 将 GET、HEAD、PUT 和 DELETE 定义为幂等方法,即执行一次与执行多次的效果相同。POST 则不是幂等的。若对支付或下单的 POST 请求盲目重试,客户可能被重复扣款。重试应仅限于超时、429 和 503 等暂时性故障,并且应采用逐步退避的策略。在指数退避中,两次尝试之间的等待时间按倍数增长,通常在每次失败后翻倍。加入随机性(即抖动)很重要,因为若没有抖动,同时重试一个已宕机服务的客户端会在相同的同步间隔上再次集中请求。客户端还应遵从服务器给出的重试指引,并限制重试所花费的总时长。
应对非幂等操作的标准做法是使用幂等键。客户端为每个逻辑操作生成一个唯一值,并在每次尝试时都随请求发送,通常放在 Idempotency-Key 请求头中。服务器会将该键与处理结果一并记录下来,因此重复的请求会直接返回已保存的结果,而不会再次执行其副作用。重试时必须复用同一个键:若每次重试都生成新键,服务器就会把每次重试都当作一个新操作。服务器还必须决定这些键的有效期,常见的默认值是二十四小时。最后需要指出,幂等性只能保护单次调用,本身并不能使多步骤的工作流变得安全,较长流程中的每一步仍然需要各自的恢复逻辑。
认证、授权与安全
API 安全依赖于两个不同的问题:谁在发起调用(认证),以及该调用者是否有权对所请求的数据执行所请求的操作(授权)。大多数严重的 API 安全故障都源于这两个问题中至少有一个被错误地回答,而所选用的凭证方案决定了每个问题能被可靠回答的程度。
凭证及常见方法
最简单的机制是 API 密钥,即发放给开发者或应用的一个不透明字符串,附加在每次请求中。密钥标识的是调用方项目,而非具体的人。因此它适用于计量和配额管理,但作为逐用户决策的依据则较为薄弱;若密钥泄露到客户端代码或日志中,就必须轮换。HTTP 基本认证(Basic 认证)在编码后的请求头中发送用户名和密码,因此其安全性完全取决于加密传输。承载令牌(Bearer token)通过 Authorization 请求头传递,仅凭持有即被接受,因此令牌的有效期、存储方式和传输保护成为核心关注点。
OAuth 2.0 解决的是另一类问题:让第三方应用在无需获知用户密码的情况下访问用户的数据。OAuth 2.0 RFC 6749(2012 年 10 月):IETF 发布的委托授权标准,涉及访问令牌,以及授权码、隐式、客户端凭证和密码等授权流程。该标准定义了四种角色:作为资源所有者的用户、作为客户端的应用、签发令牌的授权服务器,以及承载受保护 API 的资源服务器。其授权类型适用于不同的客户端。授权码模式(Authorization Code)是带后端的 Web 应用的标准方案,涉及用户代理与后端之间的“以码换令牌”交换;客户端凭证模式则用于没有用户参与的机器对机器访问。作用域(scope)用于限定令牌可执行的操作范围。作为草案后继的 OAuth 2.1 旨在整合当前实践,并删除隐式流程。需要注意的是,RFC 6749 所规定的 OAuth 2.0 并非认证协议,而是一个授权框架。OpenID Connect 弥补了这一空白,它在 OAuth 2.0 之上叠加了身份服务,返回一个经签名的 ID 令牌,用以描述用户是谁以及其通过何种方式完成认证。
令牌:JWT 与双向 TLS
JSON Web Token(JWT)是一项开放标准(RFC 7519),定义了一种紧凑且自包含的方式,以 JSON 对象的形式在各方之间安全地传递信息。经签名的令牌由三部分组成,各部分以点号分隔:头部、声明(claims)载荷和签名。iss(签发者)、sub(主体)和 aud(受众)等标准声明使接收方服务能够核验令牌由谁签发、与何人相关,以及是否为该服务而签发。每个拟处理该 JWT 的主体都必须在受众声明中以某个值标明自身身份。关于 JWT 验证的最佳实践指南收录于 RFC 8725。
这里的设计选择是一种权衡。由于令牌是自包含的,资源服务器可以在本地验证其签名和有效期,无需在每次请求时调用中央会话存储。其代价是:除非系统额外引入吊销列表或中央检查,否则已签名的令牌在过期前始终有效,因此在发生泄露后吊销会更慢。集中式会话检查或令牌内省(introspection)可以实现即时吊销,但会增加一次网络跳转,并引入共享的运行时依赖。一种常见的折中方案是:将短期有效的访问令牌与可被集中吊销的长期刷新令牌配合使用。
双向 TLS(mTLS)将认证下沉到传输层。在 TLS 握手期间,服务器同样会请求并验证客户端证书,因此在发送任何请求之前,双方就已经过密码学方式的身份识别。这种方式适用于服务间通信以及受监管的金融接口,但其代价在于证书的签发、轮换和吊销需要运维投入,而且它标识的是机器或应用,而非终端用户。
速率限制与配额
速率限制和配额用于限制客户端在一个时间窗口内可消耗的资源量,限制维度可以是 API 密钥、用户、IP 地址或端点。它们用于防范滥用、爬取和拒绝服务攻击。OWASP 的列表将此归入“无限制的资源消耗”;在 2019 年版中,该类别名为 API 04:2019 – Lack of Resources & Rate limiting(资源缺失与速率限制不足)。限制措施与访问控制之间存在多方面的相互作用。配额只有与已认证的身份绑定时才有意义,因此按用户设定的限制比按 IP 设定的限制更公平,因为分布式攻击者很容易绕过后者。然而,按身份设定限制意味着限制在认证之后才生效,因此登录和密码重置等未认证端点需要单独的保护。最后,速率限制不能替代授权:它可以减缓对调用方本不应看到的记录的枚举,但无法阻止看似合法的请求返回错误的对象。
主要漏洞类别
OWASP API 安全十大风险于 2019 年 12 月 31 日首次发布,并于 2023 年修订。榜首条目“对象级授权失效”(broken object level authorization)被普遍认为是最严重的问题。当 API 端点接受一个对象标识符(用户 ID、订单 ID、文档 ID)并返回该对象,却未检查调用用户是否有权访问该特定对象时,就会出现此问题。由于攻击者只需遍历标识符即可利用,此类缺陷很容易规模化。
按照 OWASP 的表述,“认证失效”(broken authentication)指认证机制常常实现不当,使攻击者能够攻陷认证令牌,或利用实现缺陷临时或永久地冒充其他用户的身份。2023 年版将“过度数据暴露”与“批量赋值”合并为“对象属性级授权失效”(broken object property level authorization),涵盖响应中泄露调用方不应看到的字段,以及请求中设置调用方不应控制的字段等情形。“功能级授权失效”(broken function level authorization)涉及缺少角色检查的管理或特权操作,而“无限制的资源消耗”则涵盖上文所述的速率限制缺口。
2023 年版还新增了“敏感业务流程的无限制访问”(Unrestricted Access to Sensitive Business Flows)、“服务端请求伪造”(Server Side Request Forgery)和“不安全地使用 API”(Unsafe Consumption of APIs)。注入类问题值得单独说明:在 2019 年版列表中,它是独立类别(API8:2019),但在 2023 年版中,注入被归入“不安全地使用 API”,该类别关注的是服务如何信任从第三方 API 接收的数据。
版本控制、演进与兼容性
API 在发布之后仍会不断变化,每一次变更都可能保留或打破已有调用程序所依赖的假设。破坏性变更(breaking change)是指可能导致原本正常工作的客户端出错的变更,例如删除或重命名字段、修改参数类型、新增必填参数、收紧校验规则,或改变状态码的含义。非破坏性变更则不会影响现有请求和响应的有效性,新增可选参数或新的响应字段通常是较为安全的做法。删除或重命名字段风险较大,因为读取该字段的客户端会立即失败。多出来的字段通常无害,但前提是客户端会忽略自己不认识的键。因此,服务提供方往往倾向于以增量方式演进接口,许多 API 设计指南也将其作为默认原则。
版本策略
必须进行破坏性变更的服务提供方,通常会在以下四种版本标识方式中选择一种,每种都有各自的权衡:
- URL 路径版本(例如在
/v2/前缀之外使用/v1/前缀)清晰明确,便于路由、日志记录和缓存。其代价是每个主版本都会形成一组独立的 URL,服务提供方可能还需要维护并行的代码路径。 - 自定义请求头保持 URL 稳定,由调用方在请求头中指定版本。与路径相比,这种方式不够显眼,因此在浏览器、日志和简单测试中更难检查。
- 媒体类型协商利用 HTTP 的
Accept请求头,请求一种包含版本信息的厂商专用媒体类型。这种方式与 HTTP 内容协商机制非常契合,但对初学者来说较为陌生,也更难手动测试。 - 基于日期的版本以发布日期标记每一次行为变更。调用方固定使用其接入时的当前版本,因此服务提供方可以用更新的日期发布变更,而旧的固定版本仍保持原有行为。支付类 API 是这种方式的典型例子。
无论采用哪种方案,最重要的原则都是将每个已发布的版本视为冻结状态。即使某项变更看起来只是修复,只要它改变了既有标签下的行为,也属于破坏性变更。
弃用、停用与迁移支持
弃用(deprecation)用于告知调用方某项功能仍可使用,但不应再继续使用,并可能在之后被移除。弃用策略通常会说明提前多久通知、旧行为将保留多长时间,以及在过渡期间提供哪些支持。有两个 HTTP 响应头支持这一流程。Sunset 响应头由 2019 年发布的 RFC 8594 定义,其中携带一个时间戳,表明某个 URI 可能停止响应的时间,规范将其描述为提示而非保证。之后由 RFC 9745 定义的 Deprecation 响应头则标记弃用生命周期的开始,因此两者常常配合使用。变更日志列出改动的内容及时间,迁移指南则通过前后对比的示例说明改动,并讲解如何找出受影响的调用。服务提供方还可以跟踪已弃用端点的使用情况,从而了解在移除之前仍有哪些调用方需要迁移。
库级别的兼容性
对于库和软件包,兼容性通常通过语义化版本(semantic versioning)来表达。在 SemVer 2.0.0 中,MAJOR.MINOR.PATCH 形式的版本号按照明确定义的规则变化:主版本号用于不兼容的 API 变更,次版本号用于向后兼容的功能新增,修订号用于向后兼容的缺陷修复。弃用公共功能应当触发一次次版本发布。版本 0.y.z 被明确视为初始开发阶段,其中任何内容都可能发生变化。该方案的实用性取决于公共 API 是否被明确声明,因此 SemVer 要求公共 API 必须在代码或文档中有所规定。包管理器通过版本范围建立在这些规则之上。例如,npm 的插入符(caret)范围允许次版本和修订版本的更新,但排除下一个主版本。
源代码兼容性与 ABI 稳定性是两回事。应用二进制接口(ABI)涵盖编译后的细节,例如符号名称、函数调用约定、数据布局和结构体字段偏移量。一项变更可能保持源代码兼容,却破坏已编译的二进制文件。典型例子包括为公共结构体新增字段,或修改已被编译器内联到调用方中的默认参数。因此,关心二进制使用者的库维护者必须将 ABI 变更与源代码层面的变更分开跟踪。
未文档化的行为与海勒姆定律
最棘手的兼容性问题在于,使用者往往依赖文档从未承诺过的行为。海勒姆定律(Hyrum's Law)通常归功于谷歌工程师海勒姆·赖特(Hyrum Wright),其内容是:只要用户足够多,系统的每一个可观察行为都会有人依赖,无论合约如何规定。排序、时序、错误信息的措辞以及副作用,都可能成为事实上的接口。人们常举 Microsoft Windows 的例子,说明一些应用依赖未文档化的行为,这些行为被改变后应用随之失效。某个库可能在文档中写明返回结果无序,但实际上始终返回排序后的结果,于是用户可能编写依赖该顺序的代码。这意味着语义化版本只能保护已声明的 API,内部的改动仍可能破坏某些使用者。缓解措施包括:明确记录有哪些保证、从使用者视角进行黑盒测试、以使用遥测数据为依据设置弃用窗口,以及使用功能开关实现逐步发布。
设计原则与最佳实践
好的 API 设计与其说依赖巧妙的功能,不如说依赖可预测性。一致性是首要的。命名、错误格式和资源结构应当在整个接口中遵循同一套模式,这样开发者学会了一个端点,就能猜到其余部分。在一处称为"users"、在另一处称为"customers",是造成困惑的常见原因。这一期望通常被表述为"最小惊讶原则"(也称最少意外原则)。该原则至少自 20 世纪 70 年代起就被用于描述人机交互,它同样适用于方法名和调用行为,而不仅限于界面。名为 deleteFile() 的方法应当删除文件,而不是悄悄将其归档,或因文件不存在而失败。另一个相关的例子是:数据库驱动程序的 close 调用却打开了第二个连接,用户会对此感到震惊。一致性也依赖于具体语境。金融行业的开发者可能期望每个写操作都带有幂等键,而游戏开发者则未必如此。
先设计后实现(API-first)
API 优先(API-first)是一种开发方法:团队在编写任何应用代码之前,先设计 API 契约(通常以 OpenAPI 规范的形式),然后依据这一已达成共识的契约来构建实现。在这种模式下,接口被视为一种独立的产品,而不是后端的副产品。团队在编写业务逻辑之前,就使用 OpenAPI 或 AsyncAPI 等规范格式定义端点、负载结构、响应格式和错误处理方式。其主要好处是,契约可以在修改成本仍然很低时接受审查。修改初步定义远比修改已部分实现的系统要省力。这种方法还使前端和后端团队能够针对模拟服务器并行工作。其代价是契约可能被过度规定,从而增加复杂性,或引入永远不会实现的功能。
最小暴露
接口应只公开消费者真正需要的内容。每一个公开的操作、字段或标识符都意味着一项承诺,之后移除它就属于破坏性变更。暴露内部模型尤其危险:当 API 照搬数据库表或内部类层次结构时,客户端就会与实现细节耦合,日常重构便可能导致其失效。泄露的内部字段还可能暴露本应保密的数据,这使最小暴露与网络安全以及本文其他部分讨论的访问控制联系在一起。实践中,设计者会保持较小的公开表面,将内部对象映射为专门设计的外部表示,并把每一次新增都视为一项承诺。
超媒体控制(HATEOAS)
HATEOAS,即"超媒体作为应用状态引擎"(hypermedia as the engine of application state),是 REST 中的一项约束,要求服务器告诉客户端接下来可以执行哪些操作。客户端通过服务器在响应中提供的超链接与 RESTful API 交互。例如,一本书的响应中可能包含购买、评价或查找相似书目的链接,因此客户端无需硬编码这些 URL。由于客户端在运行时发现可用操作,API 的变更不一定迫使客户端随之修改。尽管有这些优点,该方法的采用仍然有限。2019 年一项针对热门 Web API 的研究发现,所分析的 Web API 中不足五分之一提供了指向相关资源的链接。同一研究指出,HATEOAS 与早期严重依赖预定义接口的 Web 服务方法相比,是最大的偏离。PayPal 和 GitHub 是著名的例外,它们在文档中突出展示超媒体链接。因此,大多数生产环境中的 API 只是部分采用超媒体,例如使用分页的"下一页"链接,其余部分仍让客户端依赖文档中的 URL 模板。
文档与开发者体验
对大多数使用者而言,API 只能通过其文档来了解。一套良好的文档通常包含四个层次。参考页面列出每个端点、参数、数据类型、返回值和错误码,若能由机器可读的描述文件自动生成,则最为可靠。概念指南解释跨越多个端点的规则,例如身份验证、分页、速率限制、版本管理和幂等键。快速入门引导新用户从获取凭据走到第一次成功调用,可运行的示例(如可直接复制的请求片段或示例项目)则让开发者在编写自己的代码之前验证接口行为。这些层次服务于不同的读者:参考页面回答的是“这个字段是什么意思”,快速入门回答的是“今天怎样才能让某个功能跑起来”。若服务商把两者混在一起,往往会让两类读者都感到困惑。这类文档属于更广义的软件文档工作范畴。
开发者完成第一次成功请求的成本,是阻碍采用的主要因素之一,服务商通常通过测试环境来降低这一成本。沙箱是一个独立的环境,通常使用虚构或隔离的数据,在其中发出的请求不会影响生产记录。一些服务商提供任何人都可以创建的开放沙箱,付费客户则可获得带有额外模拟功能的私有沙箱,例如生成测试交易或触发 Webhook 回调。这一区别很重要:如果 API 默认操作的是真实数据,谨慎的责任就落到了开发者身上,这也是服务商建议为实验单独设立测试工作区的原因。交互式 API 浏览器是沙箱的补充。Swagger UI 等工具会把 OpenAPI 描述渲染成一个页面,开发者可以在页面上填写参数并发送真实请求;而 cURL 等命令行工具则让他们在终端或脚本中重现同样的调用。
官方 SDK 和自动生成的客户端库则以特定语言的形式处理身份验证头、序列化、错误解码和重试等工作,进一步减少集成工作量。许多服务商从生成参考页面的同一份规范中生成这些客户端,以保证文档所描述的接口与客户端提供的接口保持一致。OpenAPI Generator 等开源生成器支持多种目标语言,而一些商业及较新的工具则可以从同一份定义同时生成 SDK、文档站点和测试。不过,自动生成的代码未必是好代码,生成的 SDK 清晰与否,只取决于其源规范中的命名和描述。在代码之外,开发者门户提供账号注册、API 密钥的创建与轮换、用量仪表盘和入门清单等功能。社区论坛、变更日志和支持渠道则能把一个产品变成用户之间可以互相帮助的社群。
文档同时也是一种契约。一旦某项行为被公开描述,使用者就会合理地依赖它,因此文档中关于某个字段、某项限制或某个错误码的承诺,与端点本身具有同等的分量。文档既是指导,也是一种义务,这也是服务商对文档的修改与对代码的修改同样谨慎的原因。困难在于让两者保持同步。当开发者改变了行为却没有更新文字时,描述就会与实际脱节;示例响应会过时;弃用通知也可能被遗漏或延迟发布。常见的应对措施包括直接从规范生成参考资料、在持续集成中将文档示例作为自动化测试运行,以及对每一次破坏性或非破坏性变更都发布发行说明。即便如此,文档所说的内容与服务实际行为之间的差距,仍是最常见的集成故障来源之一,这也促使软件工程团队越来越多地把文档准确性视为需要验证的事项,而不是想当然的前提。
测试、可靠性与性能
对 API 的测试分为多个层次,每个层次能发现不同类别的缺陷。单元测试针对单个处理函数或客户端函数进行,通常会对依赖项做桩化(stub)处理。集成测试则将服务提供方与其真实的数据库、消息队列及下游服务一同运行。契约测试介于两者之间:它无需启动整个系统,即可验证提供方与消费方之间在网络传输层面的约定是否仍然成立。由于完整的端到端环境既缓慢又脆弱,团队通常依靠契约测试尽早发现破坏性变更。
契约测试与消费者驱动的契约
在消费者驱动的方法中,由客户端先编写第一个测试。消费者的测试声明它所发出的请求,以及它所依赖的最少响应字段,在提供方的模拟对象上运行,并生成一个契约文件。随后,提供方会将这些录制的交互在其真实实现上重放;如果某个响应不再满足消费者的预期,构建便会失败。Pact 是这一工作流程中最为人熟知的工具。它的价值在于揭示 API 中哪些部分实际被使用,从而使提供方可以自由修改未被使用的字段,同时在变更会破坏真实客户端时收到警告。其代价在于协调:提供方必须运行每一个消费方的契约,而相关团队还需就契约何时可以变更达成一致。这与本词条其他部分讨论的版本控制和兼容性问题直接相关。
性能指标与优化技术
性能通常用三个指标来描述。延迟是单个请求所花费的时间。对 API 而言,报告百分位数比报告平均值更有参考价值,因为一小部分极慢的请求(即尾延迟,常以 p99 表示)决定了响应最慢的用户所感受到的服务质量。吞吐量是系统在单位时间内能够完成的请求数量。第三个关注点是连接层面的资源效率。常用的技术包括:借助恰当的有效期响应头缓存响应、压缩负载、将大量小操作合并为一次调用,以及复用持久连接,使每个请求免于承担新建 TCP 与 TLS 握手的开销。HTTP/2 等现代协议还引入了多路复用,允许多个请求共享同一条连接。
可观测性
可观测性指的是能够根据运行中的 API 所发出的遥测数据,判断其正在做什么。三类信号通常结合使用。日志记录离散的事件,理想情况下应采用结构化格式并携带请求标识符。指标是聚合的计数器、仪表和直方图,通常按端点、状态码和消费方进行细分,使团队能够看出哪些操作被大量使用,以及错误率在何处上升。分布式追踪则跟踪单个请求在多个服务之间的流转,记录其在每一跳所耗费的时间;它是在微服务调用链中定位慢速依赖的主要工具。对 API 而言,良好的指标通常包括每个端点的请求速率、错误率和耗时,借助这些指标便能判断某个问题影响的是单一路由还是整个服务。
可靠性:服务等级目标、故障隔离与降级
可靠性目标通过两种形式表达:一是服务等级目标(SLO),即内部目标,例如某个月内成功请求所占的比例;二是服务等级协议(SLA),即具有合同约束力的承诺,可能附带经济赔偿条款。SLO 隐含着错误预算的概念:团队在发布新版本和进行实验时可以“消耗”的不可靠程度上限,一旦超出,就必须优先保证稳定性。API 能否达到其目标,在很大程度上取决于故障如何被遏制。Michael Nygard 于 2007 年出版的著作《Release It!》归纳了一系列稳定性模式,包括超时、舱壁模式(将资源分区,使某个出现故障的工作负载无法耗尽共享资源池)以及断路器。断路器位于远程依赖之前,在闭合、断开和半开三种状态之间切换:故障较少时允许调用通过;故障超过阈值时立即拒绝调用;并定期放行一个探测请求,以测试依赖是否已恢复。Netflix 的 Hystrix 库随后在微服务系统中推广了这一方法。优雅降级是对上述措施的补充:当某个依赖不可用时,API 可以返回缓存数据、省略非必要字段,或切换到更简单的算法,从而让核心功能继续运行,而不是完全失效。
API 管理、商业模式与 API 经济
网关与管理平台
一旦 API 暴露给单个团队之外的使用者,提供方通常会在其前面部署一个网关。API 网关是位于 API 调用方与后端服务之间的运行时组件。它通常负责请求路由、身份验证、速率限制、请求与响应转换以及协议转换,使策略无需修改应用代码即可调整。网关也是配额的执行点,限额可以按客户端 IP 地址、API 密钥、用户账户或其他因素设定。
网关只是更大技术栈的一部分。API 管理在此基础上增加了生命周期功能,包括供开发者发现和接入 API 的开发者门户、版本管理与弃用流程、使用情况分析、变现以及治理策略。接入通常意味着自助注册和密钥发放,使开发者无需提供方工作人员协助,即可从注册走到第一次成功调用。分析数据(例如各端点的调用次数和错误率)也会为定价决策提供依据。
变现模式
API 变现是指通过控制和计量对应用程序编程接口的访问,从中获取直接或间接收入的过程。最常见的直接模式包括:
- 免费增值(Freemium)。 提供一个无需付费的用量层级,直至达到某个用量阈值,超过该阈值后开始收费。谷歌地图是典型例子:提供有限次数的免费使用,额外使用则需付费。
- 按调用付费(Pay-per-call)。 每次请求都有价格。该模式常被引用的单价通常在每次调用 0.001 美元至 0.05 美元之间,具体取决于 API 的价值和计算成本。云网关定价是一个具体例子:AWS API Gateway 每百万次请求收费 3.50 美元。
- 分级订阅。 按固定月费提供包含一定配额的套餐,超出套餐的用量按档位另行计费。
- 收入分成。 提供方从 API 促成的交易中抽取一定比例,如支付类和市场类 API。
每种模式都有各自的权衡。按调用付费使收入随用量波动,难以预测;有一项比较研究将其列为收入不可预测的模式。它还可能不利于推广,因为使用 API 最多的客户付费也最多。订阅带来可预测的收入,但可能使重度用户的定价偏低。因此,将基础费用与按量计费的超额部分相结合的混合方案十分常见。定价还必须在提供方处理请求的成本与客户愿意支付的价格之间取得平衡,对于计算密集型的 AI 端点而言,这一点尤为敏感。
API 经济
这一术语指的是此类活动的商业层面。根据一种定义,API 经济是由应用程序编程接口催生的商业模式、合作关系和收入来源所构成的生态系统,这些接口使软件系统之间能够通信和共享数据。企业在两个方向上运用这一概念。一些企业将自身能力作为产品出售:Twilio 按调用次数出售通信功能,Stripe 和 OpenAI 则出售订阅套餐。另一些企业则向合作伙伴开放平台,由其在此基础上开发。例如,一家基因检测初创公司将其检测服务授权给国家地理学会和梅奥诊所等机构,供它们整合到自身产品中。API 经济指的是应用程序编程接口(API)通过规模效应和吸引新用户,对企业盈利能力产生积极影响的方式。
战略风险
依赖另一家企业的 API 会带来若干风险。
- 对单一提供方的依赖。 基于某个第三方接口构建的产品,会承受该提供方的价格、可用性和产品路线图。迁移到其他提供方需要投入工程资源,由此产生的转换成本事先往往难以衡量。
- 条款变更。 提供方可能在开发者已经投入之后,修改速率限制、价格或允许的使用方式。2023 年,多家大型社交平台终止了免费 API 访问或推出了付费套餐,依赖这些免费层级的部分第三方应用因此停止运行。
- 对接入权限的战略性使用。 控制某一接口的提供方可以限制或对其定价,以偏袒自身产品或打压竞争对手。此类行为涉及竞争法与市场势力问题,并可能强化已经存在的网络效应。这一问题将在法律部分进一步讨论。
网关和计量工具使这些政策更容易执行,这也说明,同一套用于保护服务的基础设施,同样可以用来决定谁与谁竞争。
法律、知识产权与竞争问题
关于API最旷日持久的法律纷争,是甲骨文(Oracle)与谷歌(Google)之间围绕Java的诉讼。2010年,甲骨文起诉谷歌,索赔超过十亿美元,指控安卓系统侵犯了其Java平台的版权。2012年,地方法官威廉·阿尔苏普(William Alsup)裁定这些API不受版权保护;但在2014年5月9日,联邦巡回上诉法院推翻了这一裁决,认定Java的API受版权保护,同时保留了合理使用抗辩的可能性。随后,第二个陪审团认定谷歌对声明代码的使用属于合理使用,但联邦巡回上诉法院在2018年再次推翻该结论,认定谷歌使用Java声明代码及API的结构、顺序和组织(SSO)在法律上不构成合理使用。
2021年,最高法院选择了另一条路径。以6比2的表决结果,最高法院判定谷歌胜诉,依据合理使用原则认定谷歌的复制行为不侵犯甲骨文对Java的版权。多数意见并未解决关于可版权性的前置问题:法院拒绝回答其原本同意审理的第一个问题,即Java API的声明代码是否根本具有可版权性。相反,法院在假定整个Java API受版权保护的前提下作出裁决。从绝对数量看,被复制的内容并不多,裁决涉及的是对甲骨文Java SE API约11,500行代码的复制。多数意见的论证重点在于再利用的目的,即让开发者能够在新平台上使用既有的编程接口。
结构与实现
本案的争议焦点在于两者的区分:一是API的声明代码,即调用者必须匹配的名称、函数签名及组织方式;二是API的实现代码,即执行具体工作的内部逻辑。谷歌自行编写了实现代码,这些代码构成了其API的绝大部分。联邦巡回上诉法院将声明代码以及软件包的结构、顺序和组织(SSO)视为受保护的表达,而地方法院则认为这些要素不受保护。由于最高法院是假定其受保护而非作出认定,这一问题在美国法律中仍未定论。其他司法辖区采取了不同的做法。例如,欧盟软件指令将程序接口背后的思想和原理排除在保护范围之外,并为以实现互操作为目的的反编译设立了例外。结果是,企业在特定司法辖区的法院就事实作出裁决之前,可能无法确定重新实现某一接口是否合法。
互操作性与监管
最高法院的论证十分重视竞争问题。多数意见认为,版权所有者不应利用版权设置人为障碍,阻止开发者迁移到新平台。这将接口版权问题与更广泛的转换成本和网络效应问题联系起来,而这些因素可能巩固占主导地位的平台。
监管机构已直接回应了这一关切。欧盟的数字市场法要求被指定的守门人允许第三方访问其自身服务或硬件所能使用的同一操作系统硬件和软件功能。该法还有一条更窄的规定适用于即时通讯领域,要求被指定的守门人在较小的即时通讯平台提出请求时向其开放互联。欧盟委员会为这些义务辩护,指出存在非常强的网络效应、显著的规模经济、连接企业用户与大量终端用户的能力,以及终端用户被锁定的情况,这些因素共同可能削弱市场的可竞争性。执行主要通过规格程序进行:委员会在程序中确定守门人必须采取的具体措施,第三方可以就措施草案提出意见。
合同约束与未公开的接口
在版权保护存在不确定性的情况下,服务提供者转而依赖合同和保密手段。使用条款和许可协议可以限制第三方调用API的方式,禁止某些用途,或限制逆向工程,同一协议中还可以设定调用频率限制。未公开或仅供内部使用的端点通常被视为商业秘密,而认定商业秘密一般要求该信息处于秘密状态,且所有者已采取合理措施予以保密。此类合同和商业秘密主张能在多大程度上针对外部开发者执行,因司法辖区而异,并且很大程度上取决于具体条款和相关行为。因此,依赖某个从未被提供者记录在案的端点的使用者,面临接口可能在未经通知的情况下发生变更或消失的风险。这使该法律问题与本词条其他部分讨论的未文档化行为问题联系了起来。
跨领域应用
移动应用和网页应用是最常见的 API 使用者之一。应用通常通过 HTTP 将自身的后端与外部服务结合起来。登录按钮可能使用 OAuth 2.0 或 OpenID Connect,把身份验证交给第三方身份提供商处理。地图可以由地图服务商的瓦片和地理编码端点绘制,结账表单则可能是支付服务商提供的托管组件,它收集银行卡信息后向商户服务器返回一个令牌。在这些情况下,应用持有的都是仅限特定用途的密钥或访问令牌,因此服务商无需改动应用自身的代码,即可统计用量或撤销访问权限。这类嵌入式服务让小团队能够复用自己无法独立构建的基础设施,但同时也使产品的可用性、定价和条款受制于外部服务商。此类流程的身份验证与授权机制在安全章节及本文的相关章节中有所说明。
在云计算和软件即服务(SaaS)中,API 是创建和管理资源的机制。虚拟机、存储桶、网络、数据库和负载均衡器都以 API 操作的形式对外开放,服务商的网页控制台实际上也只是该接口的一个客户端。基础设施即代码工具利用这些调用使环境可以复现。一种说法将这种方法描述为编写一个既便于人阅读、又便于机器读取的文件;另一种说法则指出,这些工具会调用服务商的 API,使资源达到声明的状态。Terraform、Pulumi 和 Crossplane 等多云工具在各服务商专属的 API 之上增加了一层配置,使同一份定义可以面向多个平台。SaaS 厂商则反向采用同样的模式,开放数据和管理操作,让客户能够将账户、记录和账单与自有系统同步。运行这些基础设施依赖于云平台,而这些平台的 API 与其他公共接口一样,都有版本划分和速率限制。
科学数据和公共部门的数据获取是另一个主要用途。政府机构和研究数据库通常同时发布批量下载和程序化接口,一方面是为了满足信息公开的要求,另一方面也是为了支持科研中的数据再利用。一份大学图书馆指南列出,NASA 的开放数据门户提供超过 31,000 个数据集和约 30 个 API。欧洲航天局的气候变化计划门户则通过 OpenSearch、OPeNDAP、WMS 等协议提供程序化访问。美国国家生物技术信息中心提供 E-utilities,作为查询 Entrez 系统的服务器端程序;OpenAlex 等学术元数据服务则让研究人员能够大规模收集引文和出版记录。CKAN 等开源门户软件的设计以 API 为先,围绕目录操作展开。程序化访问使研究能够被重复进行,但也带来了速率限制、数据集版本管理以及模式变更等问题,这些变化可能在不知不觉中改变重新运行后的分析结果。这与数据治理以及更广泛的大规模数据分析趋势密切相关。
金融服务表明,法律可以塑造 API 的形态。在欧盟,修订后的《支付服务指令》(PSD2)要求银行在客户同意的前提下,通过标准化接口向持牌第三方开放客户账户数据和支付发起功能。英国和澳大利亚也推出了类似的制度。该法规规定了安全要求,包括强客户认证,但技术设计则交由标准化机构决定,例如柏林集团的 NextGenPSD2 框架和英国的开放银行标准。用户授权有时效,到期须重新获取,银行还必须实时核验第三方是否获得授权。这些义务使开放银行成为最明确的案例之一:在这里,API 是一项法律义务,而非商业上的选择。该理念已延伸至保险、投资和养老金领域,被称为开放金融。
在物联网和工业自动化中,API 必须连接能力差异很大的异构硬件。资源受限的传感器通常使用 MQTT 等轻量级消息协议,而不同厂商的工厂设备可能通过 OPC UA 暴露数据,这是一种具有明确信息模型的标准。设备的使用寿命很长,固件更新缓慢,因此接口必须多年保持稳定,并能兼容旧版客户端。嵌入式固件中硬编码的凭据以及未经身份验证的设备端点,是长期存在的安全隐患,这也是为什么联网设备通常前置网关,由网关代替硬件处理身份验证、协议转换以及数据隐私方面的义务。
与其他领域和概念的关系
API 的思想位于软件工程的核心附近,其理论渊源可以追溯到模块化编程。David Parnas 在 1972 年关于信息隐藏的研究提出,模块应只暴露其他模块需要了解的内容,其内部设计决策则应保持隐藏。这一原则同时也是接口值得被明确规定的原因。支持抽象数据类型的编程语言将这一思想明确化:接口就是可以作用于某个值的一组操作,而其表示方式被隐藏起来。例如,栈是由 push、pop 和 peek 等操作定义的,而不是由其背后的数据结构定义的。面向对象语言对此作了扩展,将数据和操作组合进类中,并通过声明接口或抽象类,使多个实现都能满足同一规范。在这种情境下,关键的检验标准是可替换性:只要某个实现遵守相同的接口及其文档化的行为,它就应当能够替代其他实现。
面向服务的体系结构在 20 世纪 90 年代末和 21 世纪头十年变得十分突出,它将业务功能打包为可通过网络访问的服务。之后的微服务架构则把系统划分为若干小型的、可独立部署的服务。在这两种设计中,服务之间只通过网络接口进行通信,它们不共享内存或类层次结构,理想情况下也不共享数据库。因此,API 是组件之间唯一的契约,而这些组件往往分属不同团队,对接口的任何改动都会直接影响这些团队。这种隔离也带来了进程内调用所没有的代价。远程调用可能很慢,可能在中途失败,也可能被重复投递。这些风险使超时、重试和幂等性(本条目其他部分有所讨论)成为核心关注点,而不再只是可有可无的细化处理。
远程接口也是 API 设计与分布式计算交汇之处。关于消息顺序、故障检测和一致性的假设必须写入契约之中,否则收到超时的客户端就无法推断操作是否已经发生。形式验证提供了精确描述此类契约的方法。Bertrand Meyer 在 20 世纪 80 年代随 Eiffel 语言提出的契约式设计(design by contract),为操作附加了前置条件、后置条件和不变式。类似的思想也出现在运行时断言检查中,以及针对现有语言的规范语言中,例如 Java Modeling Language。接口描述语言扮演的角色较为轻量,但应用更为广泛:它们生成的桩代码会依据规范进行类型检查,这是一种较为温和的验证形式。在更大的规模上,Amazon Web Services 的工程师曾描述过在实现分布式协议之前使用 TLA+ 规范语言对其建模,这表明在任何代码存在之前,就可以对预期的 API 行为进行形式化检验。
最后,API 也是人机交互的一个案例,因为开发者本身就是用户,其遇到的困难可以被观察和测量。Brad Myers 和 Jeffrey Stylos 等研究者主张,应像评估其他用户界面一样评估 API 的可用性,具体方法包括观察程序员、出声思考(think-aloud)式研究以及对备选设计进行受控比较。这类研究反复发现,命名方式、操作的可发现性、错误信息的清晰度以及是否提供完整示例,都会强烈影响开发者上手的速度。认知心理学和符号设计领域的框架,例如符号的认知维度(cognitive dimensions of notations),也已被应用于 API 设计。由此,接口的可用性被视为一种可以通过经验检验的属性,而不仅仅是个人品味问题。这也使 API 研究与更广泛的计算机科学学科联系起来,后者研究的正是人们如何推理形式系统。
未解决的问题与未来方向
语法上兼容,并不保证两个系统彼此理解。两个 API 可以在端点、字段名和 JSON 类型上完全一致,却对数值的含义产生分歧:金额单位是分还是元,时间戳是本地时间还是 UTC,状态“inactive”意味着什么。因此,语义互操作性关注的不仅是数据的封装方式(语法),还包括数据传输时同时携带的含义(语义)。共享模式(schema)可以解决封装问题,而含义则需要另一层,通常是受控词表或本体,将每个字段与一个约定的概念相对应。这一般通过为数据添加关于数据的信息(元数据)来实现,把每个数据元素与受控的共享词表关联起来。实际上,就这些词表达成一致并加以维护的成本很高,这也是语义互操作性仍比本词条其他部分所述的机器可读规范更难实现的原因。
第二个问题是规模。微服务和云原生架构使接口数量的增长速度远超组织的跟踪能力。微服务与云原生架构带来了规模庞大、大多缺乏有效管控的 API 增长。关于一家大型企业运行多少 API 的估计差异很大,而且许多数字来自有利益关系的供应商。一家网关供应商称,企业平均在其基础设施中管理着 354 个以上的 API;另一家则称大型企业拥有 10,000 个以上的 API,其中很多是冗余的或治理不善的。常见的情况是可见性丧失:未记录的(即所谓“影子”)端点游离于清单之外,这会带来合规问题。如果处理个人数据的 API 从未被编目,它们就可能逃脱 GDPR 或 HIPAA 等审计的审查。治理工具(目录、网关、生命周期策略)是通常的应对手段,其采用程度则与更广泛的数据治理和网络安全计划相关联。
最引人注目的新动向,是将 API 用作 AI 智能体的工具。除非能够调用外部函数,大语言模型与现实世界的数据和系统是隔绝的。在标准化之前,每个模型供应商都提供各自的工具调用格式,每一种组合都需要重新构建集成。模型上下文协议(Model Context Protocol,MCP)由 Anthropic 于 2024 年 11 月开源,现由 Linux 基金会旗下的 Agentic AI Foundation 管理,它通过为工具、资源和提示词定义统一的客户端–服务器协议来解决这一问题。其传输格式为 JSON-RPC 2.0,每个工具都声明其名称、描述以及输入的 JSON Schema。该规范还建议,在操作执行前通过确认提示让人类参与其中。该协议仍在演进:2026-07-28 版修订引入了无状态核心,以及允许网关在不解析请求体的情况下完成路由与授权的 HTTP 头。智能体驱动的流量也使运维更加复杂,因为它可能产生非确定性的请求模式,而速率限制和容量规划并非为此设计。以自然语言编写的工具描述如今也成为契约的一部分,这就引出了关于测试的问题,以及模型如何理解含糊描述的问题。
仍有若干问题未得到解决。其一是大规模下的安全问题:一个组织若拥有数千个接口,其中一些还不为人知,就很难在所有接口上统一实施认证、配额和监控。其二是免费公共访问的经济问题:提供开放数据或免费套餐的供应商必须决定如何为带宽和维护提供资金,而它们设定的条款可能在无预先通知的情况下发生变化。其三是长期保存问题:使用者对某个接口的依赖,可能超过提供者继续运营该接口的时间;一旦服务被撤下,依赖它的软件可能随之失效,除非该协议已被公开记录或被重新实现。像 MCP 这样的标准,或旧服务的开源重新实现,能否使接口超越其原始所有者而继续存在,仍是一个悬而未决的问题。
参考来源
- The Preparation of Programs for an Electronic Digital Computeren.wikipedia.org
- APIen.wikipedia.org
- The Evolution of APIs: From RPC to SOAP and XML (Part 1)konghq.com
- Posix Standardlinuxhint.com
- APIencyclopedia.thefreedictionary.com
- POSIX Portable Operating System Interface for uniXtelecomtrainer.com
- What Is POSIX (Portable Operating System Interface)?phoenixnap.com
- The hunt for POSIX.1-1988luplab.cs.ucdavis.edu
- A Guide to POSIXbaeldung.com
- Object-oriented programming: some history, and challenges for the next fifty yearsarxiv.org
- Tracing the History of APIs: From Mainframes to the Cloudsensedia.com
- The History and Evolution of APIstraefik.io
- The Enviable Pedigree of UNIX® and POSIX® - The Open Group Blogblog.opengroup.org
- Types of APIsblog.axway.com
- Public, Private, Partner, and Internal APIsalgomaster.io
- What Are the Types of APIs and Their Differences?techtarget.com
- Types of APIs & Popular REST API Protocol - Blogblog.dreamfactory.com
- Framework vs Library - Key Differences Explained 2026sencha.com
- The Difference Between a Framework and a Libraryfreecodecamp.org
- Libraries vs frameworks: key differences and how to choosehackmamba.io
- What is OpenAPI? A Guide to the OpenAPI Specificationscalar.com
- OpenAPI Supportdocs.readme.com
- What is OpenAPI Specification? A Complete Guide for Developers.digitalapi.ai
- Web Services Description Language (WSDL) Version 2.0 Part 1: Core Languagew3.org
- Web Services Description Languageen.wikipedia.org
- Language Guide (editions)protobuf.dev
- Protocol Buffers Language Specification (Proto3)protobuf.dev
- Proto3 language guide - Protocol Buffersprotocolbuffers-protobuf-45.mintlify.app
- Cheatsheet - Protocol Buffers (Protobuf)hackingnote.com
- HTTP Status Codes explainedhttp.dev
- What are HTTP status codes? Complete Guide for API Developersblog.postman.com
- HTTP Status Codes Cheat Sheet — 1xx to 5xxdevtools.tools
- Cursor vs Offset Pagination: A Practical Guide — CODERCOPSblog.codercops.com
- Idempotency Keys for APIs: Safe Retries, Explainedmyappapi.com
- Response Codes and Retry Logicpostgrid.readme.io
- Idempotency & Request Retriesapiguide.dev
- The Idempotency Pattern: Making Retries Safe in Distributed Systems - DEV Communitydev.to
- Understanding HTTP Status Codes: A Complete Developer Guidemojoauth.com
- Stop Retrying Immediately. Exponential Backoff Fixes It. - DEV Communitydev.to
- Pagination Patterns: Cursor vs Offset and Why It Mattersyashveerlabs.vercel.app
- OAuth 2.0 RFC 6749: the delegated authorisation standardnoze.it
- Demystifying RFC 6749: OAuth 2.0 Authorization Framework for the Technically Astutezerosday.com
- JSON Web Token Introduction - jwt.iojwt.io
- RFC 7519: JSON Web Token (JWT)rfc-editor.org
- OWASP API Security Top 10 Vulnerabilities: 2023 - API Security Newsapisecurity.io
- OWASP API Security: Top 10 Security Risks & Remedies for 2026blog.axway.com
- OWASP Top 10 API Security Risksowasp.org
- Protect against OWASP API security Top 10 Vulnerabilities42crunch.com
- Technical Deconstruction of MCP Authorization: A Deep Dive into OAuth 2.1 and IETF RFC Specificationskane.mx
- OWASP API Top 10: How to Secure Your APIs, Complete Guidepynt.io
- Semantic Versioning 2.0.0semver.org
- RFC 8594: The Sunset HTTP Header Fieldrfc-editor.org
- Sunset Header — API Provider, Schemasapis.io
- Hyrum's Lawlawsofsoftwareengineering.com
- Hyrum's Law: API Compatibility and Hidden Dependencies — Urhobaurhoba.net
- Semantic Versioning (SemVer) - Glossaryethora.com
- Characteristics of Good APIs - DaedTechdaedtech.com
- Principle of least astonishmenten.wikipedia.org
- Principle of Least Astonishmentlawsofsoftwareengineering.com
- APIs and the Principle of Least Surprise - DaedTechdaedtech.com
- Enforcing API consistency - Speakeasyspeakeasy.com
- API-First Approach: What It Is and How to Adopt Itmoesif.com
- A Guide to API-First Design Principles and Practicesrequestly.com
- Microservice API Evolution in Practice: A Study on Strategies and Challengesarxiv.org
- API-first vs Code-first: Choosing the Right Approach for Your Projectmedium.com
- Mastering REST APIs: HATEOAS (Hypermedia as the Engine of Application State)medium.com
- RESTful or RESTless -- Current State of Today's Top Web APIsarxiv.org
- Application of HATEOAS Principle in RESTful API Designieeexplore.ieee.org
- Why API first approach matters and what it means for development in 2026buildwithfern.com
- Core API Quick Startmarqeta.com
- The Most Effective API Quick Start Guides, in 7 Examples - ReadMe: Resource Libraryblog.readme.com
- How to Design a Quick Start Guide for Your APIapimatic.io
- Quick start guidedevelopers.asana.com
- Documentation/API documentation - MediaWikimediawiki.org
- GitHub - OpenAPITools/openapi-generator: OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3) · GitHubgithub.com
- 10+ Tools To Automatically Generate SDKs for Your APInordicapis.com
- How to Document REST APIs with OpenAPIoneuptime.com
- 7 SDK Generator Tools for APIs in 2025medium.com
- GitHub - pact-foundation/pact-net: .NET version of Pact. Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project. · GitHubgithub.com
- Stop Breaking My API: A Practical Guide to Contract Testing with Pactmedium.com
- API Contract Testingstevekinney.com
- API Contract Testing with Pact — Consumer-Driven Contracts for Microservicescodelit.io
- Circuit Breaker Pattern in Microservices - by Scortiergrindengineer.substack.com
- Circuit Breaker Pattern — Build Resilient Microservices - DevKits - DEV Communitydev.to
- Bulkhead patternen.wikipedia.org
- Circuit Breaker Pattern Explained: The Complete Guide - Ajit Singhsinghajit.com
- Best API Gateways in 2026: A Developer's Guide to Choosing - Zuplozuplo.com
- What Is an API Gateway? - Palo Alto Networkspaloaltonetworks.com
- What Is an API Gateway? How It Works, Benefits & Use Caseskonghq.com
- API Monetization Strategy: Models & Azure Setuptechnetmagazine.com
- API Monetization: Models, Strategies, and What Actually Workstreblle.com
- Unlocking API Revenue: Monetization Strategies for Product and Project Managerstheneo.io
- API Monetization: Models, Strategies & Implementation Guideapisix.apache.org
- API Monetization Platforms Compared (2026): Metering, Billing - Zuplozuplo.com
- API Economy — Definition & Meaningopag.io
- What Is The “API Economy” And How Brands Can Benefit From Itmedium.com
- API Gateway Architecture: Rate Limiting, Authentication and Traffic Management Patterns for Scaleaskantech.com
- API Monetization Models and Strategies that Workblog.axway.com
- The 5 API monetization models (and which fits your AI product)credyt.ai
- What is API Economytektelic.com
- Supreme Court Declines Ruling in Oracle v. Google Copyright Case - SGR Lawsgrlaw.com
- Oracle v. Googleeff.org
- Google v. Oracle: Supreme Court Rules for Google in Landmark Software Copyright Casecongress.gov
- SCOTUS Says 'Fair Use' in Google v. Oracle Copyright Battlemcdermottlaw.com
- News & Analysis as ofjdsupra.com
- Google LLC v. Oracle America, Inc.supreme.justia.com
- Planet of the APIs: U.S. Supreme Court Rules Google’s Use of Java APIs in Android Is Fair Useairdberlis.com
- Interoperability - Digital Markets Act (DMA) - European Commissiondigital-markets-act.ec.europa.eu
- Interoperability, Privacy, and the Limits of the Digital Markets Actprivacyinternational.org
- Oracle Am., Inc. v. Google Inc., No. 13-1021 (Fed. Cir. 2014) :: Justialaw.justia.com
- Implications Around PSD2 and Open Bankingokta.com
- What are open banking APIs? Complete guide to specifications and standardstyk.io
- Open Banking APIs Explained: What PSD2 Compliance Actually Requires From Your Engineering Team - DEV Communitydev.to
- PSD2 Regulation: Definition, Key Features and Complianceqwist.com
- Open financeen.wikipedia.org
- APIs - Scholarly Resources - Data & Statistics Sources - LibGuides at University of California San Diegoucsd.libguides.com
- The ESA Climate Change Initiative Open Data Portalclimate.esa.int
- List of APIs - Text and Data Mining (TDM) at University of Toronto - Research Guides at University of Torontoguides.library.utoronto.ca
- Research Paper APIs for Scientific Literature in 2026intuitionlabs.ai
- Socrata Developersdev.socrata.com
- What is Cloud Provisioning? Process, Types & Best Practicesspacelift.io
- Semantic interoperabilityen.wikipedia.org
- API governance: Where Equixly delivers value and why it matters nowequixly.com
- API Sprawl in 2026: Why 354+ APIs Per Enterprise Breaks Traditional Gateways - Zuplozuplo.com
- API Sprawl Leads to API Chaos: Regain Control of Your Enterprise - digitalMLdigitalml.com
- What Is the Model Context Protocol (MCP) and How It Worksdescope.com
- Model Context Protocolen.wikipedia.org
- The 2026-07-28 Specificationblog.modelcontextprotocol.io
- Tools - Model Context Protocolmodelcontextprotocol.io
- Managing API Sprawl: The Growing Risk Of Shadow APIs & How To Mitigate Itcybersecurityintelligence.com